IDEA-19061 Integrate the Rearranger-plugin into core-IDEA

Initial bundling iteration. The changes to the initial version available at http://java.net/projects/rearranger/sources:
* switched from log4j to IJ logging;
* 'Rearranger' component is service now;
* plugin descriptor is adapted to the common IJ scheme (id, vendor etc);
* IJ project is configured to have new 'rearranger' module;
* build script is adjusted to process 'rearranger' plugin as well;
* almost all tests are commented and their refactoring is started;
This commit is contained in:
Denis.Zhdanov
2012-05-14 13:19:12 +04:00
parent 6f6eef2487
commit 6169cf7a3e
321 changed files with 34764 additions and 0 deletions
+1
View File
@@ -91,6 +91,7 @@
<module fileurl="file://$PROJECT_DIR$/platform/platform-resources-en/platform-resources-en.iml" filepath="$PROJECT_DIR$/platform/platform-resources-en/platform-resources-en.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-tests/platform-tests.iml" filepath="$PROJECT_DIR$/platform/platform-tests/platform-tests.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/properties/properties.iml" filepath="$PROJECT_DIR$/plugins/properties/properties.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/rearranger/rearranger.iml" filepath="$PROJECT_DIR$/plugins/rearranger/rearranger.iml" />
<module fileurl="file://$PROJECT_DIR$/xml/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/xml/relaxng/relaxng.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/resources/resources.iml" filepath="$PROJECT_DIR$/resources/resources.iml" />
<module fileurl="file://$PROJECT_DIR$/resources-en/resources-en.iml" filepath="$PROJECT_DIR$/resources-en/resources-en.iml" />
+6
View File
@@ -226,6 +226,12 @@ public def layoutCommunityPlugins(String home) {
module("gradle")
}
}
layoutPlugin("rearranger") {
jar("rearranger.jar") {
module("rearranger")
}
}
layoutPlugin("git4idea") {
jar("git4idea-rt.jar") {
+1
View File
@@ -89,6 +89,7 @@
<orderEntry type="module" module-name="android" />
<orderEntry type="module" module-name="relaxng" />
<orderEntry type="module" module-name="gradle" />
<orderEntry type="module" module-name="rearranger" />
</component>
</module>
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/src" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="core-api" />
<orderEntry type="module" module-name="java-psi-api" />
<orderEntry type="library" name="JUnit4" level="project" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="openapi" />
<orderEntry type="module" module-name="java-impl" scope="TEST" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
<orderEntry type="module" module-name="idea-ui" />
</component>
</module>
@@ -0,0 +1,46 @@
<idea-plugin url="http://confluence.jetbrains.com/display/IDEADEV/Rearranger+plugin">
<id>org.jetbrains.plugins.rearranger</id>
<name>Rearranger</name>
<description>
Rearranges (reorders) class and class member declarations according to a user-specified order and/or method call hierarchy;
generates section-marking comments;
provides several controls for spacing within and between methods and classes; and
permits the user to manually rearrange items.
</description>
<vendor url="http://www.jetbrains.com">JetBrains Inc.</vendor>
<depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceImplementation="com.wrq.rearranger.Rearranger"/>
</extensions>
<actions>
<action id="Rearranger.Rearrange"
class="com.wrq.rearranger.RearrangerAction"
text="Rearranger"
description="Rearrange class and class member declarations according to a user-specified order.">
<keyboard-shortcut first-keystroke="control alt shift R" keymap="$default"/>
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
<add-to-group group-id="EditMenu" anchor="last"/>
</action>
<action id="Rearranger.ProjectTree"
class="com.wrq.rearranger.ProjectTreeActionHandler"
text="Rearranger"
description="Rearrange class and class member declarations according to a user-specified order.">
<!-- <add-to-group group-id="EditMenu" anchor="last"/> -->
<add-to-group group-id="ProjectViewPopupMenu" anchor="last"/>
</action>
<action id="Rearranger.RearrangeLive"
class="com.wrq.rearranger.LiveRearrangerAction"
text="Live Rearranger"
description="Permits user to manually rearrange class and class member declarations.">
<keyboard-shortcut first-keystroke="ctrl COMMA" keymap="$default"/>
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
<add-to-group group-id="EditMenu" anchor="last"/>
</action>
</actions>
</idea-plugin>
Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
import com.intellij.openapi.editor.actionSystem.EditorAction;
/** Called by IDEA to instantiate the live rearranger action handler. */
public class LiveRearrangerAction
extends EditorAction
{
// --------------------------- CONSTRUCTORS ---------------------------
public LiveRearrangerAction() {
super(new LiveRearrangerActionHandler());
}
}
@@ -0,0 +1,206 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
import com.intellij.openapi.actionSystem.DataConstants;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.popup.ILiveRearranger;
import com.wrq.rearranger.popup.LiveRearrangerDialog;
import com.wrq.rearranger.popup.LiveRearrangerPopup;
import com.wrq.rearranger.rearrangement.Mover;
import com.wrq.rearranger.rearrangement.Parser;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.CommentUtil;
import java.awt.*;
import java.util.List;
/** Supports manual rearrangement of a file. */
public final class LiveRearrangerActionHandler
extends EditorActionHandler
{
// ------------------------------------------------------- FIELDS ------------------------------------------------------
private static final Logger LOG = Logger.getInstance("#" + LiveRearrangerActionHandler.class.getName());
private static boolean inProgress = false;
private final static boolean useDialog = true; // set to false for Popup
// -------------------------- OTHER METHODS --------------------------
public final void execute(final Editor editor, final DataContext context) {
if (editor == null) {
return;
}
final Project project = (Project)context.getData(DataConstants.PROJECT);
LOG.debug("project=" + project);
LOG.debug("editor=" + editor);
final Document document = editor.getDocument();
final CaretModel caret = editor.getCaretModel();
int cursorOffset = caret.getOffset();
final PsiFile psiFile = getFile(editor, context);
if (!psiFile.getName().endsWith(".java")) {
LOG.debug("not a .java file -- skipping " + psiFile.getName());
return;
}
if (!RearrangerActionHandler.isFileWritable(psiFile)) {
LOG.debug("not a writable .java file -- skipping " + psiFile.getName());
return;
}
LOG.debug("inProgress=" + inProgress);
if (!useDialog) {
if (inProgress) {
return;
}
setInProgress(true);
}
buildLiveRearrangerData(project, document, psiFile, cursorOffset);
}
private static PsiFile getFile(final Editor editor,
final DataContext context)
{
final Project project = (Project)context.getData(DataConstants.PROJECT);
final Document document = editor.getDocument();
final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
final VirtualFile virtualFile = fileDocumentManager.getFile(document);
final PsiManager psiManager = PsiManager.getInstance(project);
return psiManager.findFile(virtualFile);
}
public static void setInProgress(boolean inProgress) {
LOG.debug("set inProgress=" + inProgress);
LiveRearrangerActionHandler.inProgress = inProgress;
}
/**
* must be called from within an IDEA read-action thread.
*
* @param project
* @param document
* @param psiFile
*/
void buildLiveRearrangerData(final Project project,
final Document document,
final PsiFile psiFile,
final int cursorOffset)
{
/**
* Per instructions from IntelliJ, we have to commit any changes to the document to the Psi
* tree.
*/
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
documentManager.commitDocument(document);
final RearrangerSettings settings = new RearrangerSettings(); // use default settings with no rules
settings.setAskBeforeRearranging(true);
settings.setRearrangeInnerClasses(true);
if (useDialog) {
final Application application = ApplicationManager.getApplication();
application.runWriteAction(
new Runnable() {
public void run() {
liveRearrangeDocument(project, psiFile, settings, document, cursorOffset);
}
}
);
}
else {
final Runnable task = new Runnable() {
public void run() {
LOG.debug("liveRearrangeDocument task started");
liveRearrangeDocument(project, psiFile, settings, document, cursorOffset);
}
};
Thread t = new Thread(
new Runnable() {
public void run() {
LOG.debug("started thread " + Thread.currentThread().getName());
final Application application = ApplicationManager.getApplication();
application.runReadAction(
new Runnable() {
public void run() {
LOG.debug(
"enter application.runReadAction() on thread " +
Thread.currentThread().getName()
);
task.run();
LOG.debug(
"exit application.runReadAction() on thread " +
Thread.currentThread().getName()
);
}
}
);
}
}, "Live Rearranger parser"
);
t.start();
}
LOG.debug("exit buildLiveRearrangerData on thread " + Thread.currentThread().getName());
}
public final void liveRearrangeDocument(final Project project,
final PsiFile psiFile,
final RearrangerSettings settings,
final Document document,
final int cursorOffset)
{
LOG.debug("enter liveRearrangeDocument on thread " + Thread.currentThread().getName());
new CommentUtil(settings); // create CommentUtil singleton
final Window window = WindowManager.getInstance().suggestParentWindow(project);
ILiveRearranger fsp;
if (useDialog) {
fsp = new LiveRearrangerDialog(settings, psiFile, document, window, cursorOffset);
}
else {
fsp = new LiveRearrangerPopup(settings, psiFile, document, project, window, cursorOffset);
}
final Parser p = new Parser(project, settings, psiFile);
final List<ClassContentsEntry> outerClasses = p.parseOuterLevel();
if (outerClasses.size() > 0) {
final Mover mover = new Mover(outerClasses, settings);
final List<IRuleInstance> resultRuleInstances = mover.rearrangeOuterClasses();
fsp.setResultRuleInstances(resultRuleInstances);
fsp.liveRearranger();
}
LOG.debug("exit liveRearrangeDocument on thread " + Thread.currentThread().getName());
}
}
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
/** Additional "modifier" flags, used to identify other boolean attributes of a field, method or class. */
public final class ModifierConstants {
// ------------------------------ FIELDS ------------------------------
/*
* dummy modifier values -- chosen to not conflict with other Java modifiers
*/
public static final int OVERRIDDEN = 0x2000;
public static final int CONSTRUCTOR = 0x4000;
public static final int CANONICAL = 0x200000;
public static final int OTHER_METHOD = 0x10000;
public static final int OVERRIDING = 0x20000;
public static final int IMPLEMENTING = 0x100000;
public static final int INIT_TO_ANON_CLASS = 0x40000;
public static final int INITIALIZER = 0x80000;
public static final int IMPLEMENTED = 0x400000;
public static final int ENUM = 0x800000;
private ModifierConstants() {
}
public static String toString(int constants) {
String result = "";
if ((constants & OVERRIDDEN) > 0) result += "OVERRIDDEN ";
if ((constants & CONSTRUCTOR) > 0) result += "CONSTRUCTOR ";
if ((constants & CANONICAL) > 0) result += "CANONICAL ";
if ((constants & OTHER_METHOD) > 0) result += "OTHER_METHOD ";
if ((constants & OVERRIDING) > 0) result += "OVERRIDING ";
if ((constants & IMPLEMENTED) > 0) result += "IMPLEMENTED ";
if ((constants & IMPLEMENTING) > 0) result += "IMPLEMENTING ";
if ((constants & INIT_TO_ANON_CLASS) > 0) result += "INIT_TO_ANON_CLASS ";
if ((constants & INITIALIZER) > 0) result += "INITIALIZER ";
if ((constants & ENUM) > 0) result += "ENUM ";
return result.trim();
}
}
@@ -0,0 +1,347 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataConstants;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.Constraints;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
/** Handles right-click in project view; applies rearrangement to a directory and its files recursively. */
public final class ProjectTreeActionHandler
extends AnAction
{
// ------------------------------ FIELDS ------------------------------
private static final Logger LOG = Logger.getInstance("#" + ProjectTreeActionHandler.class.getName());
// -------------------------- OTHER METHODS --------------------------
public final void actionPerformed(final AnActionEvent anActionEvent) {
LOG.debug("entered actionPerformed");
// we're being called on the Swing event dispatch thread. Spin off another thread to do the
// rearranging and let Swing's thread go.
Thread t = new Thread(
new Runnable() {
public void run() {
new RearrangeIt(anActionEvent.getDataContext()).run();
}
}, "RearrangerThread"
);
t.start();
}
// -------------------------- INNER CLASSES --------------------------
abstract class VirtualFileVisitor {
volatile boolean cancel = false;
final void accept(final VirtualFile f) {
if (f != null) {
visitVirtualFile(f);
}
final VirtualFile[] vfa = f.getChildren();
if (vfa != null) {
for (VirtualFile aVfa : vfa) {
if (!cancel) {
accept(aVfa);
}
}
}
}
abstract void visitVirtualFile(VirtualFile f);
}
final class RearrangeIt
implements Runnable
{
final DataContext dc;
final Project project;
final JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL);
final JLabel filename = new JLabel();
class BoolHolder {
boolean value;
}
public RearrangeIt(final DataContext dc) {
this.dc = dc;
if (dc != null) {
this.project = (Project)dc.getData(DataConstants.PROJECT);
}
else {
this.project = null;
}
}
public final void run() {
final VirtualFile virtualFile = (VirtualFile)dc.getData(DataConstants.VIRTUAL_FILE);
final List<VirtualFile> files = new ArrayList<VirtualFile>();
final IntHolder count = new IntHolder();
final VirtualFileVisitor counter = new VirtualFileVisitor() {
void visitVirtualFile(final VirtualFile file) {
if (!file.isDirectory()) {
count.n++;
LOG.debug("" + count.n + ": file " + file.getName());
files.add(file);
}
}
};
final Application application = ApplicationManager.getApplication();
application.runReadAction(
new Runnable() {
public void run() {
counter.accept(virtualFile);
}
}
);
LOG.debug("counted " + count.n + " files");
final RearrangerActionHandler rah = new RearrangerActionHandler();
final PsiDocumentManager dm = PsiDocumentManager.getInstance(project);
final PsiManager pm = PsiManager.getInstance(project);
final BoolHolder cancelled = new BoolHolder();
final JDialog dialog = getProgressFrame(cancelled, count.n);
dialog.setVisible(true);
for (int currentCount = 0; currentCount < files.size(); currentCount++) {
if (cancelled.value) {
LOG.debug("cancelled rearrangement");
break;
}
final VirtualFile f = files.get(currentCount);
final int k = currentCount;
Runnable fn = new Runnable() {
public void run() {
final PsiFile psiFile = pm.findFile(f);
LOG.debug("SDT setting filename to " + psiFile.getName());
filename.setText(psiFile.getName());
filename.repaint();
}
};
Runnable r = new Runnable() {
public void run() {
final PsiFile psiFile = pm.findFile(f);
if (psiFile != null &&
psiFile.getName().endsWith(".java") &&
psiFile.isWritable())
{
LOG.debug("SDT rearranging file " + psiFile.getName());
final Document document = dm.getDocument(psiFile);
final Application application = ApplicationManager.getApplication();
application.runWriteAction(
new Runnable() {
public void run() {
final Application application = ApplicationManager.getApplication();
final Rearranger rearranger = application.getComponent(Rearranger.class);
RearrangerSettings settings = rearranger.getSettings();
settings = settings.deepCopy();
// avoid showing confirmation dialog for each file done
settings.setAskBeforeRearranging(false);
rah.runWriteActionRearrangement(project, document, psiFile, settings);
}
;
}
);
}
;
if (!cancelled.value) {
LOG.debug("SDT setting progress bar value to " + (k + 1));
bar.setValue(k + 1);
bar.repaint();
}
}
};
try {
SwingUtilities.invokeAndWait(fn);
SwingUtilities.invokeAndWait(r);
}
catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
catch (InvocationTargetException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
dialog.setVisible(false);
dialog.dispose();
}
final JDialog getProgressFrame(final BoolHolder cancelled, final int max) {
Object parent = null;
if (project != null) {
parent = WindowManager.getInstance().suggestParentWindow(project);
}
LOG.debug("suggested parent window=" + parent);
final JDialog dialog = parent == null ?
new JDialog() :
(parent instanceof JDialog ?
new JDialog((JDialog)parent) :
new JDialog((JFrame)parent));
final Container pane = dialog.getContentPane();
final JLabel rearrangingLabel = new JLabel("Rearranging files, please wait...");
final JPanel progressPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.newRow();
constraints.insets = new Insets(15, 15, 0, 0);
progressPanel.add(rearrangingLabel, constraints.weightedLastCol());
constraints.newRow();
bar.setMinimum(0);
bar.setMaximum(max);
bar.setPreferredSize(new Dimension(500, 15));
bar.setMinimumSize(new Dimension(500, 15));
bar.setStringPainted(true);
constraints.insets = new Insets(15, 15, 5, 15);
progressPanel.add(bar, constraints.weightedFirstCol());
constraints.insets = new Insets(9, 0, 5, 15);
final JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(
new ActionListener() {
public void actionPerformed(final ActionEvent e) {
LOG.debug("cancel button pressed");
filename.setText("cancelling...");
cancelled.value = true;
}
}
);
progressPanel.add(cancelButton, constraints.weightedLastCol());
constraints.weightedLastRow();
constraints.insets = new Insets(0, 15, 15, 0);
filename.setSize(500, 15);
filename.setPreferredSize(new Dimension(500, 15));
// filename.setFont(new Font("dialog", Font.PLAIN, 12));
progressPanel.add(filename, constraints.weightedLastCol());
pane.add(progressPanel, BorderLayout.CENTER);
dialog.setTitle(Rearranger.COMPONENT_NAME);
dialog.addWindowListener(
new WindowListener() {
public void windowClosed(final WindowEvent e) {
//To change body of implemented methods use Options | File Templates.
}
public void windowActivated(final WindowEvent e) {
//To change body of implemented methods use Options | File Templates.
}
public void windowClosing(final WindowEvent e) {
LOG.debug("dialog closed, cancel Rearranger");
filename.setText("cancelling...");
cancelled.value = true;
}
public void windowDeactivated(final WindowEvent e) {
//To change body of implemented methods use Options | File Templates.
}
public void windowDeiconified(final WindowEvent e) {
//To change body of implemented methods use Options | File Templates.
}
public void windowIconified(final WindowEvent e) {
//To change body of implemented methods use Options | File Templates.
}
public void windowOpened(final WindowEvent e) {
//To change body of implemented methods use Options | File Templates.
}
}
);
dialog.pack();
return dialog;
}
final class IntHolder {
public int n;
}
}
// --------------------------- main() method ---------------------------
/**
* Test progress bar functionality. Read 10 "filenames" from console, pausing between each to update the
* progress bar dialog. Handle cancel button and dialog window close button properly.
*
* @param args
*/
public static void main(final String[] args) {
// test the progress bar.
final BufferedReader reader;
final ProjectTreeActionHandler ptah = new ProjectTreeActionHandler();
final RearrangeIt ri = ptah.new RearrangeIt(null);
final RearrangeIt.IntHolder cancelled = ri.new IntHolder();
reader = new BufferedReader(new InputStreamReader(System.in));
RearrangeIt.BoolHolder c = ri.new BoolHolder();
final JDialog dialog = ri.getProgressFrame(c, 10);
int count = 0;
dialog.pack();
dialog.setVisible(true);
while (count <= 10 && cancelled.n == 0) {
String s = null;
try {
s = reader.readLine();
}
catch (IOException e) {
e.printStackTrace();
}
if (cancelled.n == 0) {
ri.filename.setText(s);
count++;
ri.bar.setValue(count);
}
}
dialog.setVisible(false);
dialog.dispose();
System.exit(0);
}
}
@@ -0,0 +1,212 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.util.JDOMExternalizable;
import com.wrq.rearranger.configuration.RearrangerSettingsPanel;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.IconUtil;
import org.jdom.Element;
import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/**
* The rearranger is an IntelliJ IDEA plugin that rearranges the order of class declarations and
* class member declarations within a Java file. The user configures an ordering of fields, methods, and classes.
* Subsequently, whenever the rearranger plugin is invoked on a Java file, the order of declarations is rearranged
* according to the configuration.
*/
public final class Rearranger
implements ApplicationComponent, Configurable, JDOMExternalizable
{
// ------------------------------ FIELDS ------------------------------
public static final String COMPONENT_NAME = "Rearranger";
public static final String VERSION = "5.5";
private static final Logger LOG = Logger.getInstance("#" + Rearranger.class.getName());
private transient RearrangerSettingsPanel preferencesPanel;
private RearrangerSettings settings = new RearrangerSettings();
private boolean haveReadExternalSettings;
// --------------------------- CONSTRUCTORS ---------------------------
public Rearranger() {
// logger.setAdditivity(false);
// logger.addAppender(new ConsoleAppender(new PatternLayout("[%7r] %6p - %30.30c - %m \n")));
// logger.setLevel(Level.DEBUG);
// logger.setLevel(Level.INFO);
LOG.debug("constructor called for " + COMPONENT_NAME + " plugin version " + VERSION);
preferencesPanel = null;
/**
* If the Reformat plugin is present, register for a callback after code reformatting
* takes place. This allows user to optimize imports, reformat code, and rearrange all
* with one keystroke.
*/
try {
if (Class.forName("org.intellij.psi.codeStyle.ReformatManager") != null) {
/**
* Reformat plugin is available. Hook it by calling code in RearrangeUtility.
* Do this dynamically using reflection so we don't get class loading problems.
*/
LOG.debug("found ReformatManager class, attempting to hook.");
/**
* if the Reformat plugin is present, obtain a reference to our RearrangerUtility class, which will register
* for callbacks from the Reformat plugin.
*/
Class rearrangerUtilityClass = Class.forName("org.intellij.psi.codeStyle.RearrangerUtility");
final Method hookit = rearrangerUtilityClass.getMethod("hookReformatPlugin", new Class[]{});
hookit.invoke(null, (Object)null);
}
}
catch (ClassNotFoundException e) {
/**
* no reformat plugin available. Just continue with normal rearranger plugin behavior.
*/
LOG.debug("did not find class org.intellij.psi.codeStyle.RearrangerUtility");
}
catch (NoSuchMethodException e) {
LOG.info(e.toString(), e);
}
catch (IllegalAccessException e) {
LOG.info(e.toString(), e);
}
catch (InvocationTargetException e) {
LOG.info(e.toString(), e);
}
}
// --------------------- GETTER / SETTER METHODS ---------------------
// End Methods of Interface JDOMExternalizable
public RearrangerSettings getSettings() {
return settings;
}
public void setSettings(RearrangerSettings settings) {
this.settings = settings;
}
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface BaseComponent ---------------------
public void initComponent() {
LOG.debug("initComponent()");
}
public void disposeComponent() {
LOG.debug("disposeComponent()");
}
// --------------------- Interface Configurable ---------------------
public String getDisplayName() {
return COMPONENT_NAME;
}
public Icon getIcon() {
return IconUtil.getIcon("RearrangerIcon");
}
public String getHelpTopic() {
return null;
}
// --------------------- Interface JDOMExternalizable ---------------------
public void readExternal(final Element element) //throws InvalidDataException
{
LOG.debug("rearranger.readExternal()");
haveReadExternalSettings = true;
final List entries = element.getChildren(COMPONENT_NAME);
if (entries.size() > 0) {
LOG.debug("element 'Rearranger' seen; configuration loading");
final Element entry = (Element)entries.get(0);
LOG.debug("element has " + entry.getChildren().size() + " children");
settings.readExternal(entry);
}
}
public void writeExternal(final Element element) //throws WriteExternalException
{
LOG.debug("rearranger.writeExternal()");
final Element our_element = new Element(COMPONENT_NAME);
settings.writeExternal(our_element);
element.getChildren().clear();
element.addContent(our_element);
}
// --------------------- Interface NamedComponent ---------------------
public String getComponentName() {
return COMPONENT_NAME;
}
// --------------------- Interface UnnamedConfigurable ---------------------
public JComponent createComponent() {
LOG.debug("createComponent: haveReadExternalSettings=" + haveReadExternalSettings);
RearrangerSettings rs;
if (!haveReadExternalSettings) {
LOG.debug("createComponent: reading default settings");
rs = RearrangerSettings.getDefaultSettings();
if (rs == null) {
LOG.debug("createComponent: could not find default settings");
}
haveReadExternalSettings = true;
}
else {
rs = settings;
}
preferencesPanel = new RearrangerSettingsPanel(rs);
return preferencesPanel;
}
public boolean isModified() {
final boolean result = !preferencesPanel.settings.equals(settings);
LOG.debug("rearranger.isModified(): returning " + result);
return result;
}
public void apply() {
LOG.debug("rearranger.apply()");
settings = preferencesPanel.settings.deepCopy();
}
public void reset() {
LOG.debug("rearranger.reset()");
}
public void disposeUIResources() {
preferencesPanel = null;
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
import com.intellij.openapi.editor.actionSystem.EditorAction;
public final class RearrangerAction
extends EditorAction
{
// --------------------------- CONSTRUCTORS ---------------------------
public RearrangerAction() {
super(new RearrangerActionHandler());
}
}
@@ -0,0 +1,227 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
import com.intellij.openapi.actionSystem.DataConstants;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.popup.FileStructurePopup;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.rearrangement.Mover;
import com.wrq.rearranger.rearrangement.Parser;
import com.wrq.rearranger.rearrangement.Spacer;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.CommentUtil;
import java.awt.dnd.DragSource;
import java.util.List;
/** This class performs rearrangement actions requested by the user. */
public final class RearrangerActionHandler extends EditorActionHandler {
// ------------------------------ FIELDS ------------------------------
private static final Logger LOG = Logger.getInstance("#" + RearrangerActionHandler.class.getName());
private static int rightMargin;
private static int tabSize;
// -------------------------- STATIC METHODS --------------------------
public static int getRightMargin() {
return rightMargin;
}
public static int getTabSize() {
return tabSize;
}
public void setTabSize(int tabSize) {
RearrangerActionHandler.tabSize = tabSize;
}
// -------------------------- OTHER METHODS --------------------------
public final void execute(final Editor editor, final DataContext context) {
if (editor == null) {
return;
}
LOG.debug("enter RearrangerActionHandler.execute()");
final Project project = (Project)context.getData(DataConstants.PROJECT);
final Document document = editor.getDocument();
final PsiFile psiFile = getFile(editor, context);
LOG.debug("suggested tool window = " +
WindowManager.getInstance().suggestParentWindow(project));
LOG.debug("drag source image supported = " + DragSource.isDragImageSupported());
if (!psiFile.getName().endsWith(".java")) {
LOG.debug("not a .java file -- skipping " + psiFile.getName());
return;
}
if (!psiFile.isWritable()) {
LOG.debug("not a writable .java file -- skipping " + psiFile.getName());
return;
}
rightMargin = editor.getSettings().getRightMargin(project);
tabSize = editor.getSettings().getTabSize(project);
LOG.debug("right margin=" + rightMargin + ", tabSize=" + tabSize);
final Application application = ApplicationManager.getApplication();
application.runWriteAction(new Runnable() {
public void run() {
final Rearranger rearranger = ServiceManager.getService(Rearranger.class);
final RearrangerSettings settings = rearranger.getSettings();
runWriteActionRearrangement(project, document, psiFile, settings);
}
}
);
}
private static PsiFile getFile(final Editor editor,
final DataContext context)
{
final Project project = (Project)context.getData(DataConstants.PROJECT);
final Document document = editor.getDocument();
final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
final VirtualFile virtualFile = fileDocumentManager.getFile(document);
final PsiManager psiManager = PsiManager.getInstance(project);
return psiManager.findFile(virtualFile);
}
/**
* must be called from within an IDEA write-action thread.
*
* @param project
* @param document
* @param psiFile
*/
void runWriteActionRearrangement(final Project project,
final Document document,
final PsiFile psiFile,
final RearrangerSettings settings)
{
/**
* Per instructions from IntelliJ, we have to commit any changes to the document to the Psi
* tree.
*/
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
documentManager.commitDocument(document);
final WaitableBoolean wb = new WaitableBoolean();
if (psiFile != null &&
isFileWritable(psiFile) &&
psiFile.getName().endsWith(".java"))
{
LOG.debug("schedule rearranger task");
final Runnable task = new rearrangerTask(project, psiFile, settings, document, wb);
CommandProcessor.getInstance().executeCommand(project, task, "Rearrange", null);
}
try {
LOG.debug("wait for rearranger task to complete.");
wb.whenTrue();
}
catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
LOG.debug("end execute");
}
public static boolean isFileWritable(PsiElement element) {
VirtualFile file = element.getContainingFile().getVirtualFile();
return file != null && file.isWritable();
}
public final void rearrangeDocument(final Project project,
final PsiFile psiFile,
final RearrangerSettings settings,
final Document document)
{
LOG.debug("enter rearrangeDocument");
new CommentUtil(settings); // create CommentUtil singleton
final Parser p = new Parser(project, settings, psiFile);
final List<ClassContentsEntry> outerClasses = p.parseOuterLevel();
if (outerClasses.size() > 0) {
final Mover m = new Mover(outerClasses, settings);
final List<IRuleInstance> resultRuleInstances = m.rearrangeOuterClasses();
boolean rearrange = true;
if (settings.isAskBeforeRearranging()) {
FileStructurePopup fsp = new FileStructurePopup(settings, resultRuleInstances, psiFile);
rearrange = fsp.displayRearrangement();
}
if (rearrange) {
final Emitter e = new Emitter(psiFile, resultRuleInstances, document);
e.emitRearrangedDocument();
}
}
LOG.debug("respacing document");
PsiDocumentManager.getInstance(project).commitDocument(document);
Spacer spacer = new Spacer(project, psiFile, document, settings);
if (spacer.respace()) {
PsiDocumentManager.getInstance(project).commitDocument(document);
}
LOG.debug("exit rearrangeDocument");
}
// -------------------------- INNER CLASSES --------------------------
final class rearrangerTask implements Runnable {
final Project project;
final PsiFile psiFile;
final RearrangerSettings settings;
final Document document;
final WaitableBoolean wb;
public rearrangerTask(final Project project,
final PsiFile psiFile,
final RearrangerSettings settings,
final Document document,
final WaitableBoolean wb)
{
this.project = project;
this.psiFile = psiFile;
this.settings = settings;
this.document = document;
this.wb = wb;
}
public final void run() {
try {
rearrangeDocument(project, psiFile, settings, document);
}
finally {
wb.set();
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
/** Test method attributes: overriding, implementing, overridden, implemented. */
abstract public class TestOverImpl
implements Runnable
{
public String toString() {
// overrides Object.toString()
return super.toString(); //To change body of overridden methods use File | Settings | File Templates.
}
public void run() {
// implements Runnable.run()
}
abstract void abstractMethod(); // is implemented
abstract void isntImplementedMethod();
void overrideableMethod() // is overridden
{
// do nothing
}
}
abstract class TestOverImpl2 extends TestOverImpl {
void abstractMethod() // implements
{
// implements abstractMethod()
}
void overrideableMethod() // overrides
{
super.overrideableMethod(); //To change body of overridden methods use File | Settings | File Templates.
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger;
/**
* Class to permit a thread to wait until another thread has finished work and set the boolean
* to true.
*/
public final class WaitableBoolean {
// ------------------------------ FIELDS ------------------------------
private boolean value_;
private final Object lock_;
// --------------------------- CONSTRUCTORS ---------------------------
/**
* Make a new WaitableBoolean with the given initial value,
* and using its own internal lock.
*/
public WaitableBoolean() {
lock_ = this;
value_ = false;
}
// -------------------------- OTHER METHODS --------------------------
public final void set() {
set(true);
}
/** Set to newValue. */
public final void set(final boolean value) {
synchronized (lock_) {
lock_.notifyAll();
value_ = value;
}
}
/**
* wait until value is true, then run action if nonnull.
* The action is run with the synchronization lock held.
*/
public final void whenTrue() throws InterruptedException {
synchronized (lock_) {
while (!value_) lock_.wait();
}
}
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.settings.attributeGroups.AttributeGroup;
import javax.swing.*;
/** Represents a labeled button that corresponds to a customized subpanel. */
public abstract class ChoiceObject {
// ------------------------------ FIELDS ------------------------------
protected AttributeGroup choiceObject;
protected AttributeGroup editingObject;
protected final String buttonName;
// --------------------------- CONSTRUCTORS ---------------------------
ChoiceObject(final String buttonName) {
this.buttonName = buttonName;
choiceObject = null;
editingObject = null;
}
// --------------------- GETTER / SETTER METHODS ---------------------
final AttributeGroup getChoiceObject() {
return choiceObject;
}
// ------------------------ CANONICAL METHODS ------------------------
public final String toString() {
return choiceObject.toString();
}
// -------------------------- OTHER METHODS --------------------------
void acceptEdited() {
choiceObject = editingObject;
editingObject = null;
}
abstract JPanel createJPanel();
abstract void createObject();
}
@@ -0,0 +1,155 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Panel which contains a number of buttons (choices) and a customized subpanel which corresponds to the chosen
* button.
*/
final class ChoicePanel
extends JPanel
{
// ------------------------------ FIELDS ------------------------------
private final ChoiceObject[] choices;
private int choice;
private final String choicePanelName;
// --------------------------- CONSTRUCTORS ---------------------------
ChoicePanel(final ChoiceObject[] choices,
final String choicePanelName)
{
super(new GridBagLayout());
this.choices = choices;
choice = 0;
this.choicePanelName = choicePanelName;
initializeChoices();
}
private void initializeChoices() {
for (ChoiceObject choice1 : choices) {
choice1.createObject();
}
choice = 0;
}
// ------------------------ CANONICAL METHODS ------------------------
public String toString() {
return choices[choice].toString();
}
// -------------------------- OTHER METHODS --------------------------
void configurePanel() {
final Border border = BorderFactory.createEmptyBorder();
final TitledBorder tb = new TitledBorder(border, choicePanelName);
setBorder(tb);
final GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.BOTH;
constraints.gridheight = 1;
constraints.weighty = 0;
final ButtonGroup group = new ButtonGroup();
final JRadioButton[] buttons = new JRadioButton[choices.length];
final JPanel[] panels = new JPanel[choices.length];
final Dimension max = new Dimension();
// make two columns of choice buttons to save some panel space.
for (int i = 0; i < choices.length; i++) {
buttons[i] = new JRadioButton(choices[i].buttonName);
group.add(buttons[i]);
constraints.gridx = i % 2;
constraints.gridy = i >> 1;
constraints.gridwidth = (i % 2 == 1) ?
GridBagConstraints.REMAINDER : 1;
constraints.weightx = (i % 2 == 1) ? 1 : 0;
add(buttons[i], constraints);
choices[i].editingObject = choices[i].choiceObject.deepCopy();
panels[i] = choices[i].createJPanel();
/**
* calculate largest dimension of any of the replaceable panels.
*/
final Dimension dimension = panels[i].getPreferredSize();
if (dimension.height > max.height) max.height = dimension.height;
if (dimension.width > max.width) max.width = dimension.width;
}
buttons[choice].setSelected(true);
constraints.gridheight = GridBagConstraints.REMAINDER;
constraints.gridwidth = 2;
constraints.weighty = 1;
constraints.gridx = 0;
constraints.gridy = (choices.length >> 1) + 1;
for (int i = 0; i < choices.length; i++) {
final int j = i;
panels[i].setPreferredSize(max);
buttons[i].addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (buttons[j].isSelected()) {
remove(choices.length);
add(panels[j], constraints);
panels[j].invalidate();
panels[j].repaint();
validate();
choice = j;
}
}
});
}
final JPanel beginning_panel = panels[choice];
add(beginning_panel, constraints);
}
void copyChoices(final ChoicePanel currentMsg) {
System.arraycopy(currentMsg.choices, 0, choices, 0, choices.length);
choice = currentMsg.choice;
}
void acceptEdited() {
for (ChoiceObject choice1 : choices) {
choice1.acceptEdited();
}
}
ChoiceObject getChoice() {
return choices[choice];
}
public ChoiceObject[] getChoices() {
return choices;
}
public void setChoice(int choice) {
this.choice = choice;
}
public String getChoicePanelName() {
return choicePanelName;
}
}
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.settings.CommentRule;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.FieldAttributes;
import com.wrq.rearranger.settings.attributeGroups.InnerClassAttributes;
import com.wrq.rearranger.settings.attributeGroups.InterfaceAttributes;
import com.wrq.rearranger.settings.attributeGroups.MethodAttributes;
import javax.swing.*;
/** UI code for Class Member (field, method, inner class) dialog. */
final class ClassMemberSettingsPane
extends SettingsPane
{
// --------------------------- CONSTRUCTORS ---------------------------
ClassMemberSettingsPane(final RearrangerSettings settings) {
super(settings, settings.getItemOrderAttributeList());
}
// -------------------------- OTHER METHODS --------------------------
ChoicePanel createChoicePanel() {
final ChoiceObject[] choices = new ChoiceObject[5];
int index = 0;
choices[index++] = new ChoiceObject("Field") {
void createObject() {
choiceObject = new FieldAttributes();
}
JPanel createJPanel() {
return ((FieldAttributes)editingObject).getFieldAttributes();
}
};
choices[index++] = new ChoiceObject("Method") {
void createObject() {
choiceObject = new MethodAttributes(settings.getDefaultGSDefinition());
}
JPanel createJPanel() {
return ((MethodAttributes)editingObject).getMethodAttributes();
}
};
choices[index++] = new ChoiceObject("Interface Methods") {
void createObject() {
choiceObject = new InterfaceAttributes();
}
JPanel createJPanel() {
return ((InterfaceAttributes)editingObject).getInterfaceAttributes();
}
};
choices[index++] = new ChoiceObject("Inner Class") {
void createObject() {
choiceObject = new InnerClassAttributes();
}
JPanel createJPanel() {
return ((InnerClassAttributes)editingObject).getInnerClassAttributes();
}
};
choices[index++] = new ChoiceObject("Separator Comment") {
void createObject() {
choiceObject = new CommentRule();
}
JPanel createJPanel() {
return ((CommentRule)editingObject).getCommentPanel();
}
};
return new ChoicePanel(choices, "Class Member Order");
}
}
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.settings.CommentRule;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.ClassAttributes;
import javax.swing.*;
/** UI code for Outer Class order dialog. */
final class ClassOrderSettingsPane
extends SettingsPane
{
// --------------------------- CONSTRUCTORS ---------------------------
public ClassOrderSettingsPane(final RearrangerSettings settings) {
super(settings, settings.getClassOrderAttributeList());
}
// -------------------------- OTHER METHODS --------------------------
ChoicePanel createChoicePanel() {
final ChoiceObject[] choices = new ChoiceObject[2];
choices[0] = new ChoiceObject("Class") {
void createObject() {
choiceObject = new ClassAttributes();
}
JPanel createJPanel() {
return ((ClassAttributes)editingObject).getClassAttributesPanel();
}
};
choices[1] = new ChoiceObject("Separator Comment") {
void createObject() {
choiceObject = new CommentRule();
}
JPanel createJPanel() {
return ((CommentRule)editingObject).getCommentPanel();
}
};
final ChoicePanel panel = new ChoicePanel(choices, "Outer Class Order");
return panel;
}
}
@@ -0,0 +1,428 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.settings.CommentRule;
import com.wrq.rearranger.settings.RelatedMethodsSettings;
import com.wrq.rearranger.util.Constraints;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/** Configuration settings for handling ordering of extracted methods. */
public class ExtractedMethodsPane {
// --------------------------- main() method ---------------------------
// ---------- START Level 1 ----------
// ---------- START Level 2 ----------
JPanel getExtractedMethodsPane(final RelatedMethodsSettings rms) {
final JPanel containerPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.weightedLastRow();
final JTabbedPane pane = new JTabbedPane();
final JPanel relatedMethodsArrangementPane = getExtractedMethodsArrangementPane(rms);
final JPanel relatedMethodsCommentsPane = getRelatedMethodsCommentsPane(rms);
pane.addTab("Arrangement", null, relatedMethodsArrangementPane,
"Options controlling arrangement of extracted methods");
pane.addTab("Comments", null, relatedMethodsCommentsPane,
"Extracted method comments");
pane.setSelectedIndex(0);
containerPanel.add(pane, constraints.weightedLastCol());
return containerPanel;
}
// ---------- START Level 3 ----------
private JPanel getExtractedMethodsArrangementPane(final RelatedMethodsSettings rms) {
final JPanel pane = new JPanel(new GridBagLayout());
final JPanel innerPanel = new JPanel(new GridBagLayout());
final Border border = BorderFactory.createEtchedBorder();
final TitledBorder tb = new TitledBorder(border, "Options controlling arrangement of extracted methods");
innerPanel.setBorder(tb);
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
JPanel traversalOrderPanel = getTraversalOrderPanel(rms);
JPanel orderingPanel = getOrderingPanel(rms);
JPanel extractedPanel = getExtractedPanel(rms);
innerPanel.add(getMoveMethodsPanel(rms, new JPanel[]{traversalOrderPanel, orderingPanel, extractedPanel}),
constraints.weightedLastCol());
constraints.newRow();
constraints.insets = new Insets(0, 20, 0, 0);
innerPanel.add(traversalOrderPanel, constraints.weightedLastCol());
constraints.newRow();
innerPanel.add(orderingPanel, constraints.weightedLastCol());
constraints.weightedLastRow();
innerPanel.add(extractedPanel, constraints);
Dimension d = innerPanel.getPreferredSize();
innerPanel.setPreferredSize(d);
innerPanel.setMaximumSize(d);
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = constraints.gridy = 0;
pane.add(innerPanel, constraints);
return pane;
}
// ---------- START Level 4 ----------
JPanel getTraversalOrderPanel(final RelatedMethodsSettings rms) {
final JPanel traversalOrderPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.weightedLastRow();
{
constraints.insets = new Insets(5, 5, 5, 0);
JLabel performLabel = new JLabel("Perform");
traversalOrderPanel.add(performLabel, constraints.firstCol());
}
{
final JComboBox traversalOrderBox = new JComboBox(new String[]{"depth first", "breadth first"});
traversalOrderPanel.add(traversalOrderBox, constraints.nextCol());
traversalOrderBox.setSelectedIndex(1);
Dimension d = traversalOrderBox.getPreferredSize();
d.width += 3;
traversalOrderBox.setPreferredSize(d);
traversalOrderBox.setSelectedIndex(rms.isDepthFirstOrdering() ? 0 : 1);
traversalOrderBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
rms.setDepthFirstOrdering(traversalOrderBox.getSelectedIndex() == 0);
}
});
}
{
JLabel remainderLabel = new JLabel("ordering on nested method calls");
traversalOrderPanel.add(remainderLabel, constraints.lastCol());
}
return traversalOrderPanel;
}
JPanel getOrderingPanel(final RelatedMethodsSettings rms) {
final JPanel orderingPanel = new JPanel(new GridBagLayout());
final Border border = BorderFactory.createEtchedBorder();
final TitledBorder tb = new TitledBorder(border, "Ordering options");
orderingPanel.setBorder(tb);
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
final JRadioButton invocationButton = new JRadioButton("Place in order of invocation");
final JRadioButton originalButton = new JRadioButton("Retain original order");
final JRadioButton alphabetizeButton = new JRadioButton("Alphabetize");
ButtonGroup group = new ButtonGroup();
group.add(invocationButton);
group.add(originalButton);
group.add(alphabetizeButton);
orderingPanel.add(invocationButton, constraints.weightedLastCol());
constraints.newRow();
orderingPanel.add(originalButton, constraints.weightedLastCol());
constraints.weightedLastRow();
orderingPanel.add(alphabetizeButton, constraints.weightedLastCol());
switch (rms.getOrdering()) {
case RelatedMethodsSettings.INVOCATION_ORDER:
invocationButton.setSelected(true);
break;
case RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER:
originalButton.setSelected(true);
break;
case RelatedMethodsSettings.ALPHABETICAL_ORDER:
alphabetizeButton.setSelected(true);
break;
}
invocationButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (invocationButton.isSelected()) {
rms.setOrdering(RelatedMethodsSettings.INVOCATION_ORDER);
}
}
});
originalButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (originalButton.isSelected()) {
rms.setOrdering(RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER);
}
}
});
alphabetizeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (alphabetizeButton.isSelected()) {
rms.setOrdering(RelatedMethodsSettings.ALPHABETICAL_ORDER);
}
}
});
return orderingPanel;
}
JPanel getExtractedPanel(final RelatedMethodsSettings rms) {
final JPanel extractedPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.insets = new Insets(5, 5, 5, 0);
JLabel label = new JLabel("Consider a non-private method as an extracted method:");
extractedPanel.add(label, constraints.weightedLastCol());
constraints.insets = new Insets(0, 15, 0, 0);
final JRadioButton neverButton = new JRadioButton("never");
constraints.newRow();
extractedPanel.add(neverButton, constraints.weightedLastCol());
final JRadioButton oneButton = new JRadioButton("when it is called by only one method in the class");
constraints.newRow();
extractedPanel.add(oneButton, constraints.weightedLastCol());
final JRadioButton moreButton = new JRadioButton("when it has one or more callers in the class");
constraints.weightedLastRow();
extractedPanel.add(moreButton, constraints.weightedLastCol());
ButtonGroup g = new ButtonGroup();
g.add(neverButton);
g.add(oneButton);
g.add(moreButton);
switch (rms.getNonPrivateTreatment()) {
case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_NEVER:
neverButton.setSelected(true);
break;
case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ONE_CALLER:
oneButton.setSelected(true);
break;
case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ANY_CALLERS:
moreButton.setSelected(true);
break;
}
neverButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (neverButton.isSelected()) {
rms.setNonPrivateTreatment(RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_NEVER);
}
}
});
oneButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (oneButton.isSelected()) {
rms.setNonPrivateTreatment(RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ONE_CALLER);
}
}
});
moreButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (moreButton.isSelected()) {
rms.setNonPrivateTreatment(RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ANY_CALLERS);
}
}
});
return extractedPanel;
}
JPanel getMoveMethodsPanel(final RelatedMethodsSettings rms, final JPanel[] dependentPanels) {
final JPanel moveMethodsPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.weightedLastRow();
{
constraints.insets = new Insets(5, 5, 5, 0);
final JCheckBox moveBox = new JCheckBox("Move extracted methods below");
moveBox.setSelected(rms.isMoveExtractedMethods());
moveBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
rms.setMoveExtractedMethods(moveBox.isSelected());
enableComponents(moveMethodsPanel, moveBox.isSelected());
enableOtherComponents(dependentPanels, moveBox.isSelected());
}
});
moveMethodsPanel.add(moveBox, constraints.firstCol());
}
{
final JComboBox firstLastBox = new JComboBox(new String[]{"first", "last"});
firstLastBox.setSelectedIndex(0);
Dimension d = firstLastBox.getPreferredSize();
d.width += 3;
firstLastBox.setPreferredSize(d);
firstLastBox.setSelectedIndex(rms.isBelowFirstCaller() ? 0 : 1);
firstLastBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
rms.setBelowFirstCaller(firstLastBox.getSelectedIndex() == 0);
}
});
moveMethodsPanel.add(firstLastBox, constraints.nextCol());
}
{
constraints.insets = new Insets(8, 5, 5, 0);
JLabel usageLabel = new JLabel("usage");
moveMethodsPanel.add(usageLabel, constraints.weightedLastCol());
}
enableComponents(moveMethodsPanel, rms.isMoveExtractedMethods());
enableOtherComponents(dependentPanels, rms.isMoveExtractedMethods());
return moveMethodsPanel;
}
// ---------- START Level 5 ----------
private void enableComponents(JPanel pane, boolean selected) {
for (int i = 1; i < pane.getComponents().length; i++) {
pane.getComponents()[i].setEnabled(selected);
}
}
private void enableOtherComponents(JPanel[] otherPanels, boolean selected) {
for (JPanel otherPanel : otherPanels) {
enablePanel(otherPanel, selected);
}
}
// ---------- START Level 6 ----------
private void enablePanel(JPanel otherPanel, boolean selected) {
for (int i = 0; i < otherPanel.getComponents().length; i++) {
Component c = otherPanel.getComponents()[i];
if (c instanceof JPanel) {
enablePanel((JPanel)c, selected);
}
else {
c.setEnabled(selected);
}
}
}
// ---------- END Level 6 ----------
// ---------- END Level 5 ----------
// ---------- END Level 4 ----------
private JPanel getRelatedMethodsCommentsPane(final RelatedMethodsSettings rms) {
JPanel rmcPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0.0d;
constraints.weighty = 0.0d;
JLabel commentTypeLabel = new JLabel("Emit comment at");
final JComboBox commentType = new JComboBox(new String[]{
"top level",
"each level",
"each method",
"family change (up level, or next sibling has children)"
});
commentType.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
rms.setCommentType(commentType.getSelectedIndex());
}
});
commentType.setSelectedIndex(rms.getCommentType());
JLabel legendLabel = new JLabel("Comment Substitutions: use");
JLabel legendLabel_1 = new JLabel("%TL% for top level method");
JLabel legendLabel_2 = new JLabel("%MN% for method name");
JLabel legendLabel_4 = new JLabel("%LV% for level number");
JLabel legendLabel_3 = new JLabel("%AM% for all method names");
JLabel precedingCommentLabel = new JLabel("Preceding Comment:");
JLabel trailingCommentLabel = new JLabel("Trailing Comment:");
JPanel precedingCommentPanel = getCommentAreaPanel(rms.getPrecedingComment());
JPanel trailingCommentPanel = getCommentAreaPanel(rms.getTrailingComment());
constraints.insets = new Insets(3, 5, 0, 0);
rmcPanel.add(commentTypeLabel, constraints.firstCol());
rmcPanel.add(commentType, constraints.lastCol());
JPanel legendPanel = new JPanel(new GridBagLayout());
{
final Border border = BorderFactory.createEtchedBorder();
legendPanel.setBorder(border);
final Constraints legendConstraints = new Constraints(GridBagConstraints.NORTHWEST);
legendConstraints.fill = GridBagConstraints.BOTH;
legendConstraints.insets = new Insets(5, 5, 0, 0);
legendPanel.add(legendLabel, legendConstraints.firstCol());
legendConstraints.insets = new Insets(5, 5, 0, 5);
legendPanel.add(legendLabel_1, legendConstraints.nextCol());
legendPanel.add(legendLabel_2, legendConstraints.lastCol());
legendConstraints.newRow();
legendConstraints.firstCol(); // skip first column
legendConstraints.insets = new Insets(5, 5, 5, 5);
legendPanel.add(legendLabel_3, legendConstraints.nextCol());
legendPanel.add(legendLabel_4, legendConstraints.lastCol());
}
constraints.newRow();
constraints.insets = new Insets(5, 5, 0, 5);
rmcPanel.add(legendPanel, constraints.weightedLastCol());
constraints.newRow();
rmcPanel.add(precedingCommentLabel, constraints.weightedLastCol());
constraints.weightedNewRow(0.50d);
rmcPanel.add(precedingCommentPanel, constraints.weightedLastCol());
constraints.newRow();
rmcPanel.add(trailingCommentLabel, constraints.weightedLastCol());
constraints.weightedNewRow(0.50d);
constraints.insets = new Insets(5, 5, 5, 5);
rmcPanel.add(trailingCommentPanel, constraints.weightedLastCol());
constraints.lastRow();
rmcPanel.add(rms.getCommentFillString().getCommentFillStringPanel(), constraints.weightedLastCol());
return rmcPanel;
}
// ---------- START Level 4 ----------
private JPanel getCommentAreaPanel(final CommentRule comment) {
JPanel commentPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.weightedLastRow();
final JTextArea commentArea = new JTextArea(4, 40);
commentArea.setText(comment.getCommentText());
final JScrollPane scrollPane = new JScrollPane(commentArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
commentPanel.add(scrollPane, constraints.weightedFirstCol());
commentArea.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(final DocumentEvent e) {
comment.setCommentText(commentArea.getText());
}
public void insertUpdate(final DocumentEvent e) {
comment.setCommentText(commentArea.getText());
}
public void removeUpdate(final DocumentEvent e) {
comment.setCommentText(commentArea.getText());
}
});
return commentPanel;
}
// ---------- END Level 4 ----------
// ---------- END Level 3 ----------
// ---------- END Level 2 ----------
// ---------- END Level 1 ----------
}
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import javax.swing.*;
/** Describes objects that can be handled by ListManager. */
public interface IListManagerObject {
String getDescription();
void setDescription(String description);
JPanel getPanel();
IListManagerObject deepcopy();
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import java.util.List;
/** Handles creation and removal of list manager objects. */
public interface IListManagerObjectFactory {
IListManagerObject create(String name);
List getObjectList();
}
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.NumberFormatter;
import java.awt.*;
import java.text.NumberFormat;
/**
* A JTextField tied to a numeric field. Initialize the JTextField from the field and update
* the field whenever the JTextField's text changes.
*/
public class IntTextField
extends JFormattedTextField
{
public interface IGetSet {
public int get();
public void set(int value);
}
public IntTextField(final IGetSet getset, final Integer minimum, final Integer maximum) {
final NumberFormat integerInstance = NumberFormat.getIntegerInstance();
int maxDigits = 2;
if (maximum != null && (maximum) > 99) {
maxDigits = maximum.toString().length();
}
integerInstance.setMaximumIntegerDigits(maxDigits);
integerInstance.setMinimumIntegerDigits(1);
setFormatterFactory(new DefaultFormatterFactory(new NumberFormatter(integerInstance)));
setValue(maximum != null ? maximum : new Integer("88"));
final Dimension d = getPreferredSize();
d.width += 3;
setPreferredSize(d);
setValue(getset.get());
setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
setText("" + getValue());
getDocument().addDocumentListener(new DocumentListener() {
private void setit() {
try {
// allow empty string, else must be valid number
if (getText().length() != 0) {
int value = Integer.parseInt(getText());
if (minimum != null) {
if (value < (minimum)) value = (minimum);
}
if (maximum != null) {
if (value > (maximum)) value = (maximum);
}
getset.set(value);
}
}
catch (NumberFormatException e) {
// leave value alone
}
}
public void insertUpdate(DocumentEvent e) {
setit();
}
public void removeUpdate(DocumentEvent e) {
setit();
}
public void changedUpdate(DocumentEvent e) {
setit();
}
});
}
}
@@ -0,0 +1,303 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.util.IconUtil;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Generic manager for a panel with a list combo box, add/delete/copy buttons,
* a name field, and a subpanel to get contents of current item.
*/
public class ListManager
extends JPanel
{
JLabel nameLabel;
JTextField name;
JButton addButton;
JButton removeButton;
JButton copyButton;
JList list;
GridBagConstraints constraints;
final IListManagerObjectFactory factory;
IListManagerObject currentObject;
boolean buttonPressInProgress;
private JButton makeButton(String iconName) {
Icon icon = IconUtil.getIcon(iconName);
JButton result = new JButton(icon);
result.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
return result;
}
public ListManager(final IListManagerObjectFactory factory, String nameLabelText) {
super(new GridBagLayout());
this.factory = factory;
currentObject = null;
nameLabel = new JLabel(nameLabelText);
name = new JTextField(3);
addButton = makeButton("general/add");
removeButton = makeButton("general/remove");
copyButton = makeButton("general/copy");
list = new JList(new DefaultListModel());
/**
* declare callback handlers for buttons.
*/
addButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonPressInProgress = true;
currentObject = factory.create(getUniqueName("unnamed"));
factory.getObjectList().add(currentObject);
((DefaultListModel)list.getModel()).addElement(currentObject);
list.setSelectedIndex(list.getModel().getSize() - 1);
updateListSelection();
buttonPressInProgress = false;
}
}
);
removeButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonPressInProgress = true;
DefaultListModel dlm = ((DefaultListModel)list.getModel());
int selectedIndex = list.getSelectedIndex();
IListManagerObject lmo = (IListManagerObject)dlm.getElementAt(selectedIndex);
factory.getObjectList().remove(lmo);
dlm.remove(selectedIndex);
if (selectedIndex >= dlm.getSize()) {
selectedIndex = dlm.getSize() - 1;
}
list.setSelectedIndex(selectedIndex);
currentObject =
(IListManagerObject)(selectedIndex < 0 ? null : dlm.getElementAt(selectedIndex));
updateListSelection();
buttonPressInProgress = false;
}
}
);
copyButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonPressInProgress = true;
DefaultListModel dlm = ((DefaultListModel)list.getModel());
int selectedIndex = list.getSelectedIndex();
IListManagerObject lmo = (IListManagerObject)dlm.getElementAt(selectedIndex);
currentObject = lmo.deepcopy();
currentObject.setDescription(getUniqueName(lmo.getDescription()));
dlm.addElement(currentObject);
list.setSelectedIndex(list.getModel().getSize() - 1);
updateListSelection();
buttonPressInProgress = false;
}
}
);
name.getDocument().addDocumentListener(
new DocumentListener() {
private void updateList() {
if (buttonPressInProgress) {
return;
}
String newText = name.getText();
final IListManagerObject listObject = (IListManagerObject)list.getSelectedValue();
if (listObject != null) {
listObject.setDescription(newText);
}
int index = list.getSelectedIndex();
DefaultListModel dlm = ((DefaultListModel)list.getModel());
dlm.setElementAt(listObject, index);
validate();
}
public void changedUpdate(DocumentEvent e) {
updateList();
}
public void insertUpdate(DocumentEvent e) {
updateList();
}
public void removeUpdate(DocumentEvent e) {
updateList();
}
}
);
list.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (buttonPressInProgress) {
return; // list selection changes due to add/remove/copy button handled elsewhere
}
buttonPressInProgress = true;
int selectedIndex = list.getSelectedIndex();
DefaultListModel dlm = ((DefaultListModel)list.getModel());
currentObject =
(IListManagerObject)(selectedIndex < 0 ? null : ((java.lang.Object)dlm.getElementAt(selectedIndex)));
updateListSelection();
buttonPressInProgress = false;
}
}
);
}
public final JPanel getPane() {
constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.NONE;
constraints.gridwidth = 1;
constraints.gridheight = GridBagConstraints.REMAINDER;
constraints.weightx = 0.0d;
constraints.weighty = 0.0d;
constraints.gridy = constraints.gridx = 0;
constraints.insets = new Insets(0, 0, 0, 5);
JPanel buttonPanel = new JPanel(new GridBagLayout());
buttonPanel.setBorder(BorderFactory.createEtchedBorder()); // todo remove
addButton.setBorderPainted(false);
removeButton.setBorderPainted(false);
copyButton.setBorderPainted(false);
buttonPanel.add(addButton, constraints);
constraints.gridx++;
buttonPanel.add(removeButton, constraints);
constraints.gridx++;
// constraints.gridwidth = GridBagConstraints.REMAINDER;
// constraints.weightx = 1;
buttonPanel.add(copyButton, constraints);
constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.NONE;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0.0d;
constraints.weighty = 0.0d;
constraints.gridy = constraints.gridx = 0;
constraints.insets = new Insets(3, 3, 3, 3);
add(buttonPanel, constraints);
buttonPanel.setPreferredSize(buttonPanel.getPreferredSize()); // todo determine effect if any
constraints.gridx++;
add(nameLabel, constraints);
constraints.gridx++;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
add(name, constraints);
list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// addButton.setEnabled(true);
JScrollPane scrollPane = new JScrollPane(list);
Dimension d = buttonPanel.getPreferredSize();
d.width = d.width * 5 / 3;
scrollPane.setPreferredSize(d);
scrollPane.setMinimumSize(d);
for (Object object : factory.getObjectList()) {
((DefaultListModel)list.getModel()).addElement(object);
}
list.setSelectedIndex(list.getModel().getSize() - 1);
constraints.gridheight = GridBagConstraints.REMAINDER;
constraints.gridwidth = 1;
constraints.gridx = 0;
constraints.gridy++;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.VERTICAL;
add(scrollPane, constraints);
constraints.gridx++;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1;
constraints.weighty = 1;
final JPanel contents = new JPanel();
contents.setBorder(BorderFactory.createEtchedBorder()); // todo remove
add(contents, constraints);
updateListSelection();
validate();
return this;
}
/**
* Enable add/remove/copy buttons and fill in name of selected list item. Called whenever
* the list selection changes.
*/
private void updateListSelection() {
if (list.getModel().getSize() > 0) {
name.setEnabled(true);
nameLabel.setEnabled(true);
name.setText(((IListManagerObject)list.getSelectedValue()).getDescription());
removeButton.setEnabled(true);
copyButton.setEnabled(true);
}
else {
name.setEnabled(false);
nameLabel.setEnabled(false);
removeButton.setEnabled(false);
copyButton.setEnabled(false);
name.setText("");
}
remove(getComponentCount() - 1);
final JPanel contents = new JPanel();
contents.setBorder(BorderFactory.createEtchedBorder()); // todo remove
add(currentObject == null ? contents : ((javax.swing.JPanel)currentObject.getPanel()), constraints);
validate();
}
public String getUniqueName(String name) {
String result;
if (name != null) {
// test initially supplied name; if not duplicate, return it.
if (!dupName(name)) {
return name;
}
}
result = (name == null) ? "unnamed" : name;
int suffix = 0;
String testName;
do {
suffix++;
testName = result + "_" + suffix;
}
while (dupName(testName));
return testName;
}
/**
* @param name
* @return true if the supplied name is identical to any other primary method name.
*/
public boolean dupName(String name) {
for (int i = 0; i < list.getModel().getSize(); i++) {
IListManagerObject lmo = (IListManagerObject)list.getModel().getElementAt(i);
if (lmo.getDescription().equals(name)) {
return true;
}
}
return false; //To change body of created methods use File | Settings | File Templates.
}
}
@@ -0,0 +1,227 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.intellij.ui.DocumentAdapter;
import com.wrq.rearranger.util.Constraints;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.text.NumberFormat;
/**
* Getters and setters are defined by their method names (eg., beginning with "get"), number of parameters,
* return type, and body contents. This class provides support for these common rule attributes.
* Other attributes, like number of parameters or return type, are already specified in MethodAttributes.
*/
public class MethodSpec {
/**
* pattern for property name. Must contain one or more regular expression groups, one of which will be
* regarded as the property. Will be matched against the candidate method's name.
*/
String propertyPattern;
/** Group number which identifies which regex group contains the pattern. */
int propertyGroup;
/** true if first letter of property should be lowercased. */
boolean lowercaseFirstLetterOfProperty;
/** if true, the property name must match a field in the class, else the method will not match. */
boolean propertyMustMatchField;
/**
* pattern of method body (excluding comments and newline characters). Substitutions will be performed
* in this pattern before matching against the method's body as follows:
* <pre>
* %PATTERN% this method's pattern
* %TYPE% this method's type
* %PARAMNAME<n>% name of parameter <n>, <n> = 1, 2, 3, ...
* $PARAMTYPE<n>% type of parameter <n>, <n> = 1, 2, 3, ...
* $PARENT% parent's property
* </pre>
*/
String body;
/** true if body matching should be done against method body stripped of comments. */
boolean ignoreComments;
/**
* value of "parent property", which is the property of the field or method executing this rule.
* If this is the top level rule (not being called by another rule to associate methods matching this
* rule with the parent), then there is no parent property.
*/
final String parentProperty;
public MethodSpec(String parentProperty) {
this.parentProperty = parentProperty;
}
public String getPropertyPattern() {
return propertyPattern;
}
public void setPropertyPattern(String propertyPattern) {
this.propertyPattern = propertyPattern;
}
public int getPropertyGroup() {
return propertyGroup;
}
public void setPropertyGroup(int propertyGroup) {
this.propertyGroup = propertyGroup;
}
public boolean isLowercaseFirstLetterOfProperty() {
return lowercaseFirstLetterOfProperty;
}
public void setLowercaseFirstLetterOfProperty(boolean lowercaseFirstLetterOfProperty) {
this.lowercaseFirstLetterOfProperty = lowercaseFirstLetterOfProperty;
}
public boolean isPropertyMustMatchField() {
return propertyMustMatchField;
}
public void setPropertyMustMatchField(boolean propertyMustMatchField) {
this.propertyMustMatchField = propertyMustMatchField;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public boolean isIgnoreComments() {
return ignoreComments;
}
public void setIgnoreComments(boolean ignoreComments) {
this.ignoreComments = ignoreComments;
}
boolean isMatch() {
return false; // todo
}
private JFormattedTextField getIntField(int initialValue) {
final NumberFormat integerInstance = NumberFormat.getIntegerInstance();
integerInstance.setMaximumIntegerDigits(2);
integerInstance.setMinimumIntegerDigits(1);
final JFormattedTextField intField = new JFormattedTextField(integerInstance);
intField.setValue(new Integer("88"));
final Dimension d = intField.getPreferredSize();
d.width += 3;
intField.setPreferredSize(d);
intField.setValue(initialValue);
intField.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
return intField;
}
public JPanel getPanel() {
JPanel panel = new JPanel(new GridBagLayout());
Constraints constraints = new Constraints();
constraints.insets = new Insets(3, 3, 3, 3);
JLabel propertyPatternLabel = new JLabel("Property pattern:");
propertyPatternLabel.setToolTipText("Regex pattern which method name must match; " +
"parenthesize portion which will be regarded as the method's property" +
", e.g. \"(get|is|has)([A-Z]\\w*)\"");
panel.add(propertyPatternLabel, constraints.firstCol());
constraints.fill = GridBagConstraints.HORIZONTAL;
final JTextField propertyPatternField = new JTextField(this.propertyPattern);
propertyPatternField.getDocument().addDocumentListener(
new DocumentAdapter() {
protected void textChanged(DocumentEvent event) {
propertyPattern = propertyPatternField.getText();
}
}
);
panel.add(propertyPatternField, constraints.weightedLastCol(0.5));
constraints.newRow();
constraints.fill = GridBagConstraints.NONE;
final JLabel propertyGroupLabel = new JLabel("Property group number:");
propertyGroupLabel.setToolTipText("Regular expression parenthesized group corresponding to the property name");
panel.add(propertyGroupLabel, constraints.firstCol());
final JFormattedTextField propertyGroupField = getIntField(propertyGroup);
panel.add(propertyGroupField, constraints.nextCol());
constraints.newRow();
JCheckBox lowerCase = new JCheckBox("Lowercase first letter of property");
lowerCase.setToolTipText("If selected, lower cases the first letter of the property found in the regular expression");
panel.add(lowerCase, constraints.lastCol());
constraints.newRow();
JCheckBox mustMatch = new JCheckBox("Property must match field name");
mustMatch.setToolTipText("If selected, the property name derived from the regular expression must match the " +
"name of a field in the same class as the method; if no such field exists, the " +
"method will not match the rule");
panel.add(mustMatch, constraints.lastCol());
// propertyGroupField.get
constraints.newRow();
JLabel bodyLabel = new JLabel("Body:");
bodyLabel.setToolTipText("Regex pattern for method body (excluding comments);\n" +
"use \"%FN%\" for field name, \"%P1%\" for param 1, etc.");
constraints.fill = GridBagConstraints.NONE;
panel.add(bodyLabel, constraints.firstCol());
JCheckBox stripComments = new JCheckBox("Strip comments");
stripComments.setToolTipText("If selected, comments will be stripped from the method body before attempting" +
" to match the supplied expression");
panel.add(stripComments, constraints.lastCol());
constraints.weightedLastRow();
constraints.fill = GridBagConstraints.BOTH;
JTextArea body = new JTextArea(4, 40);
JScrollPane sp = new JScrollPane(body);
panel.add(sp, constraints.weightedLastCol());
return panel;
}
public MethodSpec deepcopy() {
MethodSpec result = new MethodSpec(parentProperty);
result.body = body;
result.ignoreComments = ignoreComments;
result.lowercaseFirstLetterOfProperty = lowercaseFirstLetterOfProperty;
result.propertyGroup = propertyGroup;
result.propertyMustMatchField = propertyMustMatchField;
result.propertyPattern = propertyPattern;
result.body = body;
return result;
}
public static void main(String[] args) {
MethodSpec ms = new MethodSpec(null);
final JDialog frame = new JDialog((Frame)null, "SwingApplication");
final GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1.0d;
constraints.weighty = 1.0d;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.gridx = 0;
constraints.gridy = 0;
frame.getContentPane().setLayout(new GridBagLayout());
frame.getContentPane().add(ms.getPanel(), constraints);
//Finish setting up the frame, and show it.
frame.pack();
frame.setResizable(true);
frame.setModal(true);
frame.setVisible(true);
}
}
@@ -0,0 +1,566 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.Rearranger;
import com.wrq.rearranger.settings.CommentRule;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.AttributeGroup;
import com.wrq.rearranger.settings.attributeGroups.RegexUtil;
import com.wrq.rearranger.util.CommentUtil;
import com.wrq.rearranger.util.Constraints;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.PatternSyntaxException;
/** Code for top level configuration panel. */
public final class RearrangerSettingsPanel
extends JPanel
{
// ------------------------------ FIELDS ------------------------------
public RearrangerSettings settings;
// --------------------------- CONSTRUCTORS ---------------------------
// ---------- START Level 1 ----------
public RearrangerSettingsPanel(final RearrangerSettings externalSettings) {
RearrangerSettings settings = externalSettings.deepCopy();
setLayout(new GridBagLayout());
createSettingsPanel(settings);
}
// ---------- START Level 2 ----------
private void createSettingsPanel(RearrangerSettings settings) {
this.settings = settings;
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.weightedLastRow();
while (getComponents().length > 0) {
remove(0);
}
add(getSettingsPanel(), constraints.weightedLastCol());
validate();
}
// ---------- START Level 3 ----------
private JPanel getSettingsPanel() {
final JPanel containerPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.weightedLastRow();
final JTabbedPane pane = new JTabbedPane();
final SettingsPane classMemberSettingsPane = new ClassMemberSettingsPane(settings);
final SettingsPane classOrderSettingsPane = new ClassOrderSettingsPane(settings);
final SpacingPane spacingPane = new SpacingPane(settings);
final ExtractedMethodsPane extractedMethodsSettings = new ExtractedMethodsPane();
final JPanel generalSettingsPane = getGeneralSettingsPane();
final RelatedByNamePane rbnp = new RelatedByNamePane(settings.getExtractedMethodsSettings().getRbnms());
pane.addTab(
"Class Member Order",
null,
classMemberSettingsPane.getPane(),
"Options controlling arrangement of fields, methods and inner classes"
);
pane.addTab(
"Outer Class Order",
null,
classOrderSettingsPane.getPane(),
"Options controlling arrangement of outer classes"
);
pane.addTab(
"Extracted Methods",
null,
extractedMethodsSettings.getExtractedMethodsPane(settings.getExtractedMethodsSettings()),
"Options controlling arrangement of extracted methods"
);
pane.addTab(
"General",
null,
generalSettingsPane,
"General options"
);
pane.addTab(
"Spacing",
null,
spacingPane.getPane(),
"Options controlling number of blank lines before and after braces"
);
pane.addTab(
"Configuration",
null,
getConfigurationPane(),
"Load, save, clear configuration, or set to default"
);
// pane.addTab("Related By Name", null, // todo - add when ready; replace "Extracted Methods" pane above
// rbnp.getPane(), "Global definitions for methods related by name (\"getters/setters\")");
pane.setSelectedIndex(0);
containerPanel.add(pane, constraints.weightedLastCol());
return containerPanel;
}
// ---------- START Level 4 ----------
private JPanel getGeneralSettingsPane() {
final JPanel gsPanel = new JPanel(new GridBagLayout());
final Border border = BorderFactory.createEtchedBorder();
gsPanel.setBorder(border);
final GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.gridx = constraints.gridy = 0;
constraints.insets = new Insets(5, 5, 0, 0);
final JCheckBox getterSetterBox = new JCheckBox("Keep getters/setters together");
getterSetterBox.setSelected(settings.isKeepGettersSettersTogether());
final JCheckBox gettersSettersWithPropertyBox = new JCheckBox("Keep getters/setters with property");
gettersSettersWithPropertyBox.setSelected(settings.isKeepGettersSettersWithProperty());
gettersSettersWithPropertyBox.setEnabled(settings.isKeepGettersSettersTogether());
final JCheckBox overloadedMethodsBox = new JCheckBox("Keep overloaded methods/constructors together");
overloadedMethodsBox.setSelected(settings.isKeepOverloadedMethodsTogether());
final JLabel overloadOrderLabel = new JLabel("Ordering of constructors and overloaded methods:");
final JComboBox overloadOrderBox = new JComboBox(
new String[]{
"Retain original order",
"Order by number of parameters (ascending)",
"Order by number of parameters (descending)"
}
);
overloadOrderLabel.setEnabled(settings.isKeepOverloadedMethodsTogether());
overloadOrderBox.setEnabled(settings.isKeepOverloadedMethodsTogether());
overloadOrderBox.setSelectedIndex(settings.getOverloadedOrder());
overloadedMethodsBox.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
settings.setKeepOverloadedMethodsTogether(overloadedMethodsBox.isSelected());
overloadOrderLabel.setEnabled(settings.isKeepOverloadedMethodsTogether());
overloadOrderBox.setEnabled(settings.isKeepOverloadedMethodsTogether());
}
}
);
final JCheckBox confirmBox = new JCheckBox("Confirm before rearranging");
confirmBox.setSelected(settings.isAskBeforeRearranging());
confirmBox.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
settings.setAskBeforeRearranging(confirmBox.isSelected());
}
}
);
final JCheckBox rearrangeInnerClasses = new JCheckBox("Rearrange contents of inner classes");
rearrangeInnerClasses.setSelected(settings.isRearrangeInnerClasses());
rearrangeInnerClasses.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
settings.setRearrangeInnerClasses(rearrangeInnerClasses.isSelected());
}
});
gsPanel.add(getterSetterBox, constraints);
constraints.gridy++;
gsPanel.add(gettersSettersWithPropertyBox, constraints);
constraints.gridy++;
// constraints.insets = new Insets(0, 0, 0, 0);
gsPanel.add(overloadedMethodsBox, constraints);
constraints.gridy++;
constraints.insets = new Insets(0, 30, 3, 0);
gsPanel.add(overloadOrderLabel, constraints);
constraints.gridy++;
constraints.insets = new Insets(0, 30, 10, 0);
constraints.fill = GridBagConstraints.NONE;
gsPanel.add(overloadOrderBox, constraints);
constraints.fill = GridBagConstraints.BOTH;
constraints.gridy++;
constraints.insets = new Insets(5, 5, 0, 0);
gsPanel.add(confirmBox, constraints);
constraints.gridy++;
gsPanel.add(rearrangeInnerClasses, constraints);
constraints.gridy++;
//
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1.0d;
constraints.weighty = 0.0d;
final JPanel gsDefaultPane = settings.getDefaultGSDefinition().getGSDefinitionPanel();
constraints.insets = new Insets(5, 5, 0, 5);
constraints.gridx = 1;
int oldGridy = constraints.gridy;
constraints.gridheight = constraints.gridy;
constraints.gridy = 0;
Border b = gsDefaultPane.getBorder();
TitledBorder tb = BorderFactory.createTitledBorder(b, "Default Getter/Setter Definition");
gsDefaultPane.setBorder(tb);
gsPanel.add(gsDefaultPane, constraints);
constraints.gridy = oldGridy;
//
constraints.gridx = 0;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.gridy++;
constraints.weightx = 0; // was 1
constraints.insets = new Insets(5, 5, 0, 0);
final JLabel commentLabel = new JLabel("Comment pattern:");
final JButton createPatternButton = new JButton("Generate pattern");
final JButton verifyCommentsButton = new JButton("Verify comments against pattern");
gsPanel.add(commentLabel, constraints);
constraints.gridx++;
constraints.anchor = GridBagConstraints.NORTH;
gsPanel.add(createPatternButton, constraints);
constraints.anchor = GridBagConstraints.NORTHEAST;
constraints.gridx++;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = 1; // was 0
constraints.insets = new Insets(5, 0, 0, 5);
constraints.fill = GridBagConstraints.NONE; // new line
gsPanel.add(verifyCommentsButton, constraints);
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.insets = new Insets(5, 5, 5, 5);
constraints.gridy++;
constraints.weighty = 1.0d;
constraints.gridheight = GridBagConstraints.REMAINDER;
final JTextArea commentArea = new JTextArea(4, 40);
commentArea.setText(settings.getGlobalCommentPattern());
constraints.gridheight = GridBagConstraints.REMAINDER;
final JScrollPane scrollPane = new JScrollPane(commentArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
gsPanel.add(scrollPane, constraints);
getterSetterBox.addActionListener(
new ActionListener() {
public void actionPerformed(final ActionEvent e) {
settings.setKeepGettersSettersTogether(getterSetterBox.isSelected());
gettersSettersWithPropertyBox.setEnabled(settings.isKeepGettersSettersTogether());
}
}
);
gettersSettersWithPropertyBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
settings.setKeepGettersSettersWithProperty(gettersSettersWithPropertyBox.isSelected());
}
});
overloadOrderBox.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
settings.setOverloadedOrder(overloadOrderBox.getSelectedIndex());
}
}
);
commentArea.getDocument().addDocumentListener(
new DocumentListener() {
public void changedUpdate(final DocumentEvent e) {
settings.setGlobalCommentPattern(commentArea.getText());
}
public void insertUpdate(final DocumentEvent e) {
settings.setGlobalCommentPattern(commentArea.getText());
}
public void removeUpdate(final DocumentEvent e) {
settings.setGlobalCommentPattern(commentArea.getText());
}
}
);
createPatternButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
String t = commentArea.getText();
if (t.length() > 0) {
int result = JOptionPane.showConfirmDialog(
null, "This will replace the existing comment pattern with the generated pattern." +
" Are you sure?",
"Replace existing pattern",
JOptionPane.YES_NO_CANCEL_OPTION
);
if (result != 0) return;
}
String s = generateCommentPattern(settings);
commentArea.setText(s);
}
}
);
verifyCommentsButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
checkCommentsAgainstGlobalPattern(settings);
}
}
);
return gsPanel;
}
// ---------- START Level 5 ----------
private String generateCommentPattern(RearrangerSettings settings) {
new CommentUtil(settings);
String result = RegexUtil.combineExpressions(CommentUtil.getCommentStrings());
return result;
}
/**
* Compare all comments specified by the user against the global comment pattern. If all match, then
* the global pattern will catch all the user's comments and remove them before rearranging and inserting
* new ones. If any don't match, bring up a dialog box listing them.
*
* @param settings current Rearranger settings.
*/
public void checkCommentsAgainstGlobalPattern(RearrangerSettings settings) {
String pattern = settings.getGlobalCommentPattern();
if (pattern == null || pattern.trim().length() == 0) {
JOptionPane.showMessageDialog(
null, "No global comment pattern exists!"
, "Verify Comments Against Pattern",
JOptionPane.WARNING_MESSAGE
);
return;
}
try {
" ".matches(pattern);
}
catch (PatternSyntaxException pse) {
JOptionPane.showMessageDialog(
null,
"Invalid global pattern:" + pse.toString(),
"Verify Comments Against Pattern",
JOptionPane.ERROR_MESSAGE
);
return;
}
int nCommentsSeen = 0;
List<String> mismatches = new ArrayList<String>();
// first check all rules in the class order settings panes.
nCommentsSeen =
checkAttributeListForErrors(settings.getClassOrderAttributeList(), nCommentsSeen, pattern, mismatches);
// now check all the class member attributes.
nCommentsSeen =
checkAttributeListForErrors(settings.getItemOrderAttributeList(), nCommentsSeen, pattern, mismatches);
// now check all comments for extracted methods. Expand keywords to make the match realistic.
CommentRule rule = settings.getExtractedMethodsSettings().getPrecedingComment();
String preceding = rule.getCommentText();
if (preceding != null && preceding.trim().length() > 0) {
nCommentsSeen++;
checkExtractedComment(rule, "Preceding", pattern, mismatches);
}
rule = settings.getExtractedMethodsSettings().getTrailingComment();
String trailing = rule.getCommentText();
if (preceding != null && preceding.trim().length() > 0) {
nCommentsSeen++;
checkExtractedComment(rule, "Trailing", pattern, mismatches);
}
/**
* if any strings mismatch, display a dialog showing them; otherwise display a dialog indicating that
* everything is ok.
*/
if (nCommentsSeen == 0) {
JOptionPane.showMessageDialog(
null, "No user-defined comments have been configured"
, "Verify Comments Against Pattern",
JOptionPane.PLAIN_MESSAGE
);
}
else if (mismatches.size() == 0) {
JOptionPane.showMessageDialog(
null,
nCommentsSeen +
" user-defined comments seen; " +
"all match the global comment pattern",
"Verify Comments Against Pattern",
JOptionPane.PLAIN_MESSAGE
);
}
else {
mismatches.add(0, nCommentsSeen + " user-defined comments seen; following comments did not match:");
JOptionPane.showMessageDialog(
null, mismatches.toArray(),
"Verify Comments Against Pattern", JOptionPane.WARNING_MESSAGE
);
}
}
// ---------- START Level 6 ----------
private int checkAttributeListForErrors(List<AttributeGroup> list,
int nCommentsSeen,
String pattern,
List<String> mismatches)
{
int index = 0;
for (AttributeGroup group : list) {
index++;
nCommentsSeen += group.getCommentCount();
if (!group.commentsMatchGlobalPattern(pattern)) {
List badComments = group.getOffendingPatterns(pattern);
for (Object badComment : badComments) {
mismatches.add("Class Member item #" + index + ": \"" + badComment + "\"");
}
}
}
return nCommentsSeen;
}
private void checkExtractedComment(final CommentRule commentRule,
final String which,
String pattern,
List<String> mismatches)
{
String comment = commentRule.getCommentText();
if (comment.length() == 0) return;
// make some 'typical' substitutions for wildcard expansion to check against pattern.
// hand-expand the %FS% (fill string) because the fill string could contain special characters that
// replaceAll interprets and changes.
String expanded = comment.replaceAll("%LV%", "12");
expanded = expanded.replaceAll("%TL%", "topLevelMethod()");
expanded = expanded.replaceAll("%MN%", "methodName()");
expanded = expanded.replaceAll("%AM%", "method1().[method1A(),method1B()]");
expanded = expanded.replaceAll("%IF%", "Interface_ExampleName0");
expanded = RegexUtil.replaceAllFS(expanded, commentRule.getCommentFillString().getFillString());
if (!expanded.matches(pattern)) {
mismatches.add(which + " comment for extracted methods: \"" + comment + "\"");
}
}
// ---------- END Level 6 ----------
// ---------- END Level 5 ----------
private JPanel getConfigurationPane() {
final JPanel gcPanel = new JPanel(new GridBagLayout());
Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets = new Insets(5, 5, 0, 5);
final JButton clearConfig = new JButton("Clear configuration");
final JButton loadDefaultConfig = new JButton("Load default configuration");
final JButton readConfig = new JButton("Read configuration from file...");
final JButton writeConfig = new JButton("Write configuration to file...");
clearConfig.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
createSettingsPanel(new RearrangerSettings());
}
});
loadDefaultConfig.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
RearrangerSettings defaultSettings = RearrangerSettings.getDefaultSettings();
if (defaultSettings == null) {
JOptionPane.showMessageDialog(null, "Could not obtain default configuration.",
"No default configuration available", JOptionPane.WARNING_MESSAGE);
}
else {
createSettingsPanel(defaultSettings);
}
}
});
readConfig.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser();
int returnVal = fc.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
RearrangerSettings fileSettings = RearrangerSettings.getSettingsFromFile(file);
if (fileSettings == null) {
JOptionPane.showMessageDialog(null, "Could not read configuration.",
"File or file contents invalid", JOptionPane.WARNING_MESSAGE);
}
else {
createSettingsPanel(fileSettings);
}
}
}
});
writeConfig.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser();
int returnVal = fc.showSaveDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
settings.writeSettingsToFile(file);
}
}
});
gcPanel.add(clearConfig, constraints.weightedLastCol());
constraints.newRow();
gcPanel.add(loadDefaultConfig, constraints.weightedLastCol());
constraints.newRow();
gcPanel.add(readConfig, constraints.weightedLastCol());
constraints.newRow();
gcPanel.add(writeConfig, constraints.weightedLastCol());
// now create outer panel so that buttons aren't stretched across creation.
JPanel outerPanel = new JPanel(new GridBagLayout());
constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.weightedLastRow();
outerPanel.add(gcPanel, constraints.weightedLastCol());
JPanel extraPanel = new JPanel(new GridBagLayout());
final Border border = BorderFactory.createEtchedBorder();
extraPanel.setBorder(border);
constraints = new Constraints(GridBagConstraints.SOUTHEAST);
extraPanel.add(outerPanel, constraints.firstCol());
constraints.weightedNewRow();
constraints.firstCol(); // skip first column
extraPanel.add(new JLabel(), constraints.weightedNextCol());
constraints.lastRow();
constraints.firstCol(); // skip first column
constraints.nextCol(); // skip second column
constraints.weightx = constraints.weighty = 0;
constraints.insets = new Insets(5, 5, 5, 5);
JLabel version = new JLabel("Rearranger plugin, version " + Rearranger.VERSION);
extraPanel.add(version, constraints.lastCol());
return extraPanel;
}
// --------------------------- main() method ---------------------------
// ---------- END Level 4 ----------
// ---------- END Level 3 ----------
// ---------- END Level 2 ----------
// ---------- END Level 1 ----------
}
@@ -0,0 +1,217 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.settings.PrimaryMethodSetting;
import com.wrq.rearranger.settings.RelatedByNameMethodsSettings;
import javax.swing.*;
import java.util.List;
/** Configuration settings for handling ordering of extracted methods. */
public class RelatedByNamePane {
RelatedByNameMethodsSettings rbnms;
public RelatedByNamePane(RelatedByNameMethodsSettings rbnms) {
this.rbnms = rbnms;
}
public final JPanel getPane() {
IListManagerObjectFactory lmof = new IListManagerObjectFactory() {
public IListManagerObject create(String name) {
PrimaryMethodSetting pms = new PrimaryMethodSetting();
pms.setDescription(name);
return pms;
}
public List getObjectList() {
return rbnms.getMethodList();
}
};
ListManager result = new ListManager(lmof, "Primary method name:");
// constraints = new GridBagConstraints();
// constraints.anchor = GridBagConstraints.NORTHWEST;
// constraints.fill = GridBagConstraints.NONE;
// constraints.gridwidth = 1;
// constraints.gridheight = 1;
// constraints.weightx = 0.0d;
// constraints.weighty = 0.0d;
// constraints.gridy = constraints.gridx = 0;
// constraints.insets = new Insets(3, 3, 3, 3);
// addButton.setBorderPainted(false);
// removeButton.setBorderPainted(false);
// copyButton.setBorderPainted(false);
// containerPanel.add(addButton, constraints);
// constraints.gridx++;
// containerPanel.add(removeButton, constraints);
// constraints.gridx++;
// containerPanel.add(copyButton, constraints);
// constraints.gridx++;
// containerPanel.add(nameLabel, constraints);
// constraints.gridx++;
// constraints.gridwidth = GridBagConstraints.REMAINDER;
// constraints.weightx = 1;
// constraints.fill = GridBagConstraints.HORIZONTAL;
// containerPanel.add(name, constraints);
// /**
// * declare callback handlers for buttons.
// */
// addButton.addActionListener(new ActionListener()
// {
// public void actionPerformed(ActionEvent e)
// {
// PrimaryMethodSetting pms = new PrimaryMethodSetting();
// pms.setName("unnamed");
// ((DefaultListModel)rbnmlist.getModel()).addElement(pms);
// rbnmlist.setSelectedIndex(rbnmlist.getModel().getSize() - 1);
// updateListSelection();
// }
// });
// removeButton.addActionListener(new ActionListener()
// {
// public void actionPerformed(ActionEvent e)
// {
// DefaultListModel dlm = ((DefaultListModel)rbnmlist.getModel());
// int selectedIndex = rbnmlist.getSelectedIndex();
// PrimaryMethodSetting pms = (PrimaryMethodSetting) dlm.getElementAt(selectedIndex);
// rbnms.getMethodList().remove(pms);
// dlm.remove(selectedIndex);
// if (selectedIndex >= dlm.getSize()) {
// selectedIndex = dlm.getSize() - 1;
// }
// rbnmlist.setSelectedIndex(selectedIndex);
// updateListSelection();
// }
// });
// copyButton.addActionListener(new ActionListener()
// {
// public void actionPerformed(ActionEvent e)
// {
// DefaultListModel dlm = ((DefaultListModel)rbnmlist.getModel());
// int selectedIndex = rbnmlist.getSelectedIndex();
// PrimaryMethodSetting pms = (PrimaryMethodSetting) dlm.getElementAt(selectedIndex);
// dlm.addElement(pms.deepcopy());
// rbnmlist.setSelectedIndex(rbnmlist.getModel().getSize() - 1);
// updateListSelection();
// }
// });
// rbnmlist.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// addButton.setEnabled(true);
// name.getDocument().addDocumentListener(new DocumentListener()
// {
// private void updateList()
// {
// String newText = name.getText();
// final PrimaryMethodSetting primaryMethodSetting = (PrimaryMethodSetting)rbnmlist.getSelectedValue();
// primaryMethodSetting.setName(newText);
// int index = rbnmlist.getSelectedIndex();
// DefaultListModel dlm = ((DefaultListModel)rbnmlist.getModel());
// dlm.remove(index);
// dlm.add(index, primaryMethodSetting);
// rbnmlist.setSelectedIndex(index);
// }
// public void changedUpdate(DocumentEvent e)
// {
// updateList();
// }
//
// public void insertUpdate(DocumentEvent e)
// {
// updateList();
// }
//
// public void removeUpdate(DocumentEvent e)
// {
// updateList();
// }
// });
// JScrollPane scrollPane = new JScrollPane(rbnmlist);
// scrollPane.setPreferredSize(new Dimension(80, 300));
// ListIterator li = rbnms.getMethodList().listIterator();
// while (li.hasNext())
// {
// PrimaryMethodSetting pms = (PrimaryMethodSetting) li.next();
// ((DefaultListModel)rbnmlist.getModel()).addElement(pms);
// }
// rbnmlist.setSelectedIndex(rbnmlist.getModel().getSize() - 1);
// constraints.gridheight = GridBagConstraints.REMAINDER;
// constraints.gridx = 0;
// constraints.gridy++;
// constraints.gridwidth = 3;
// constraints.weightx = .2;
// constraints.weighty = 1;
// constraints.fill = GridBagConstraints.BOTH;
// containerPanel.add(scrollPane, constraints);
// constraints.gridx += 3;
// constraints.gridwidth = GridBagConstraints.REMAINDER;
// constraints.fill = GridBagConstraints.BOTH;
// constraints.weightx = .8;
// containerPanel.add(getPrimaryMethodPanel(), constraints);
// updateListSelection();
return result.getPane();
}
/**
* Enable add/remove/copy buttons and fill in name of selected list item. Called whenever
* the list selection changes.
*/
// private void updateListSelection()
// {
// if (rbnmlist.getModel().getSize() > 0)
// {
// rbnmlist.setSelectedIndex(0);
// name.setEnabled(true);
// nameLabel.setEnabled(true);
// name.setText(((PrimaryMethodSetting) rbnmlist.getSelectedValue()).getName());
// removeButton.setEnabled(true);
// copyButton.setEnabled(true);
// }
// else
// {
// name.setEnabled(false);
// nameLabel.setEnabled(false);
// removeButton.setEnabled(false);
// copyButton.setEnabled(false);
// name.setText("");
// }
// containerPanel.remove(containerPanel.getComponentCount() - 1);
// containerPanel.add(getPrimaryMethodPanel(), constraints);
// containerPanel.validate();
// }
/**
* Get a primary method panel based on values for the currently selected primary item.
* @return
*/
// private JPanel getPrimaryMethodPanel()
// {
// PrimaryMethodSetting pms = (PrimaryMethodSetting) rbnmlist.getSelectedValue();
// if (pms == null) {
// return new JPanel(); // empty
// }
// else {
// return pms.getPanel();
// }
// }
// ---------- START Level 4 ----------
}
@@ -0,0 +1,549 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.AttributeGroup;
import com.wrq.rearranger.settings.attributeGroups.IPrioritizableRule;
import com.wrq.rearranger.settings.attributeGroups.IRule;
import com.wrq.rearranger.util.Constraints;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
/** Code common to dialog managing creation and maintenance of a list of rules. */
public abstract class SettingsPane {
// ------------------------------ FIELDS ------------------------------
public static final int SEQUENCE_COLUMN = 0;
public static final int PRIORITY_COLUMN = 1;
public static final int DESCRIPTION_COLUMN = 2;
public static final int NUM_COLUMNS = 3;
protected final RearrangerSettings settings;
private final List<AttributeGroup> list;
private List<ChoicePanel> modelData;
private JTable jTable;
private AbstractTableModel model;
private JPanel pane;
// --------------------------- CONSTRUCTORS ---------------------------
SettingsPane(final RearrangerSettings settings, List<AttributeGroup> list) {
this.settings = settings;
this.list = list;
modelData = new ArrayList<ChoicePanel>(list.size());
createConfigurationPane();
}
private void createConfigurationPane() {
pane = new JPanel(new GridBagLayout());
final Border border = BorderFactory.createEmptyBorder();
pane.setBorder(border);
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.weightedNewRow();
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(10, 10, 10, 10);
pane.add(createScrollableTablePanel(), constraints.weightedFirstCol());
pane.add(createAddRemovePanel(), constraints.nextCol());
}
private JPanel createScrollableTablePanel() {
final JPanel cmlPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.weightedLastRow();
constraints.fill = GridBagConstraints.BOTH;
final JTextField priorityField = new JTextField();
priorityField.setHorizontalAlignment(JTextField.RIGHT);
TableCellEditor priorityEditor = new DefaultCellEditor(priorityField);
model = new AbstractTableModel() {
public int getColumnCount() {
return NUM_COLUMNS; // sequence, priority, rule description
}
public int getRowCount() {
return list.size();
}
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case SEQUENCE_COLUMN:
return rowIndex + 1;
case PRIORITY_COLUMN:
ChoicePanel cp = (modelData.get(rowIndex));
IRule rule = cp.getChoice().getChoiceObject();
return new Priority(rule.getPriority());
case DESCRIPTION_COLUMN:
return list.get(rowIndex).toString();
}
return null;
}
public String getColumnName(int column) {
switch (column) {
case SEQUENCE_COLUMN:
return "Seq";
case PRIORITY_COLUMN:
return "Pri";
case DESCRIPTION_COLUMN:
return "Rule";
}
return null;
}
public Class getColumnClass(int columnIndex) {
switch (columnIndex) {
case SEQUENCE_COLUMN:
return Integer.class;
case PRIORITY_COLUMN:
return Priority.class;
case DESCRIPTION_COLUMN:
return String.class;
}
return Object.class;
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex == PRIORITY_COLUMN && rowIndex >= 0) {
ChoicePanel cp = (modelData.get(rowIndex));
IRule rule = cp.getChoice().getChoiceObject();
if (rule instanceof IPrioritizableRule) {
return true;
}
}
return false;
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == PRIORITY_COLUMN) {
ChoicePanel cp = (modelData.get(rowIndex));
IRule rule = cp.getChoice().getChoiceObject();
if (rule instanceof IPrioritizableRule) {
int priority;
try {
priority = (new Integer((String)aValue));
}
catch (NumberFormatException nfe) {
return;
}
if (priority > 0 && priority < 100) {
rule.setPriority(priority);
fireTableCellUpdated(rowIndex, columnIndex);
}
}
}
}
};
TableCellRenderer priorityRenderer = new DefaultTableCellRenderer() {
protected void setValue(Object value) {
Priority p = (Priority)value;
if (p.priority <= 0) {
setText("n/a");
setHorizontalAlignment(JLabel.CENTER);
}
else {
setText("" + p.priority + " ");
setHorizontalAlignment(JLabel.RIGHT);
}
}
};
TableSorter sorter = new TableSorter(model) {
public void sortByColumn(int column, boolean ascending) {
if (column == SEQUENCE_COLUMN ||
column == PRIORITY_COLUMN)
{
super.sortByColumn(column, ascending);
}
}
public boolean defaultSortOrderAscending(int column) {
switch (column) {
case SEQUENCE_COLUMN:
return true;
case PRIORITY_COLUMN:
return false;
}
return true;
}
};
jTable = new JTable(sorter);
sorter.addMouseListenerToHeaderInTable(jTable);
jTable.setShowHorizontalLines(false);
jTable.setShowVerticalLines(true);
jTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
jTable.setDragEnabled(false);
jTable.setRowSelectionAllowed(true);
jTable.setColumnSelectionAllowed(false);
jTable.setPreferredScrollableViewportSize(jTable.getPreferredSize());
jTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
TableColumnModel tcm = jTable.getColumnModel();
tcm.getColumn(0).setPreferredWidth(new JLabel("SEQ").getWidth() * 3);
tcm.getColumn(1).setPreferredWidth(new JLabel("MMM").getWidth() * 3);
tcm.getColumn(1).setCellRenderer(priorityRenderer);
tcm.getColumn(1).setCellEditor(priorityEditor);
final JScrollPane scrollPane = new JScrollPane(jTable);
for (AttributeGroup ca : list) {
modelData.add(createOptionsPaneMsg(ca));
}
if (list.size() > 0) {
jTable.getSelectionModel().setSelectionInterval(0, 0);
}
cmlPanel.add(scrollPane, constraints.weightedLastCol());
setTableColumnWidths();
return cmlPanel;
}
/**
* @param ca FieldAttributes, MethodAttributes, InnerClassAttributes, or CommentRule object
* @return ItemPanel corresponding to the value of param.
*/
private ChoicePanel createOptionsPaneMsg(final AttributeGroup ca) {
final ChoicePanel result = createChoicePanel();
for (int i = 0; i < result.getChoices().length; i++) {
final AttributeGroup choiceObject = result.getChoices()[i].getChoiceObject();
if (ca.getClass() == choiceObject.getClass()) {
result.setChoice(i);
result.getChoice().choiceObject = ca;
break;
}
}
return result;
}
abstract ChoicePanel createChoicePanel();
private void setTableColumnWidths() {
int columnCount = jTable.getColumnCount();
TableColumnModel tcm = jTable.getColumnModel();
final int SPARE = 24;
for (int i = 0; i < columnCount; i++) {
int width = calculateColumnWidth(i);
width += SPARE;
TableColumn column = tcm.getColumn(i);
column.setMinWidth(width);
if (i < columnCount - 1) {
column.setMaxWidth(width);
}
}
}
private int calculateColumnWidth(int columnIndex) {
int result = 0;
int rowCount = jTable.getRowCount();
for (int i = 0; i < rowCount; i++) {
TableCellRenderer tcr = jTable.getCellRenderer(i, columnIndex);
Component comp = tcr.getTableCellRendererComponent(
jTable,
jTable.getValueAt(i, columnIndex),
true, true, i, columnIndex
);
int compWidth = comp.getPreferredSize().width;
if (compWidth > result) {
result = compWidth;
}
}
TableCellRenderer tcr = jTable.getColumnModel().getColumn(columnIndex).getHeaderRenderer();
if (tcr == null) {
tcr = jTable.getDefaultRenderer(String.class);
}
Component comp = tcr.getTableCellRendererComponent(
jTable,
model.getColumnName(columnIndex), true, true, -1, columnIndex
);
int compWidth = comp.getPreferredSize().width;
if (compWidth > result) {
result = compWidth;
}
if (columnIndex == DESCRIPTION_COLUMN) {
if (result < 400) result = 400;
}
return result;
}
private JPanel createAddRemovePanel() {
final JPanel addRemovePanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTH);
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets = new Insets(0, 0, 10, 0);
final JButton addButton = new JButton("Add");
final JButton editButton = new JButton("Edit");
final JButton removeButton = new JButton("Remove");
final JButton duplicateButton = new JButton("Duplicate");
final JButton moveUpButton = new JButton("Move up");
final JButton moveDownButton = new JButton("Move down");
addRemovePanel.add(addButton, constraints.firstCol());
constraints.newRow();
addRemovePanel.add(editButton, constraints.firstCol());
constraints.newRow();
addRemovePanel.add(duplicateButton, constraints.firstCol());
constraints.newRow();
addRemovePanel.add(removeButton, constraints.firstCol());
constraints.newRow();
addRemovePanel.add(moveUpButton, constraints.firstCol());
constraints.weightedNewRow();
constraints.insets = new Insets(0, 0, 0, 0);
addRemovePanel.add(moveDownButton, constraints.firstCol());
if (jTable.getSelectedRow() < 0) {
editButton.setEnabled(false);
duplicateButton.setEnabled(false);
removeButton.setEnabled(false);
moveUpButton.setEnabled(false);
moveDownButton.setEnabled(false);
}
if (jTable.getSelectedRow() == 0) {
moveUpButton.setEnabled(false);
}
if (jTable.getSelectedRowCount() > 0 &&
jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1] == jTable.getModel().getRowCount() - 1)
{
moveDownButton.setEnabled(false);
}
jTable.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(final ListSelectionEvent e) {
if (e.getValueIsAdjusting() || (e.getFirstIndex() < 0)) {
return;
}
final int index = jTable.getSelectedRow();
final boolean selectionExists = index >= 0;
editButton.setEnabled(selectionExists);
duplicateButton.setEnabled(selectionExists);
removeButton.setEnabled(selectionExists);
moveUpButton.setEnabled(selectionExists && index > 0);
int lastSelectedRow = 0;
if (selectionExists) {
lastSelectedRow = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1];
}
moveDownButton.setEnabled(selectionExists &&
lastSelectedRow < jTable.getModel().getRowCount() - 1);
}
}
);
jTable.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
int index = jTable.getSelectedRow();
editRow(addRemovePanel);
jTable.getSelectionModel().setLeadSelectionIndex(index);
}
}
});
addButton.addActionListener(
new ActionListener() {
public void actionPerformed(final ActionEvent e) {
// add new rule after last selected rule
final int currentIndex;
if (jTable.getSelectedRowCount() <= 0) {
currentIndex = 0;
}
else {
currentIndex = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1] + 1;
}
final ChoicePanel choicePanel = getOptionsPaneMsg(null);
final JOptionPane op = new JOptionPane(
choicePanel,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
null, null, null
);
final JDialog jd = op.createDialog(addRemovePanel, choicePanel.getChoicePanelName());
jd.setVisible(true);
final Object result = op.getValue();
if (result != null &&
((Integer)result) == JOptionPane.OK_OPTION)
{
final ChoicePanel value = (ChoicePanel)op.getMessage();
value.acceptEdited();
modelData.add(currentIndex, value);
list.add(currentIndex, ((com.wrq.rearranger.settings.attributeGroups.AttributeGroup)value.getChoice().getChoiceObject()));
model.fireTableRowsInserted(currentIndex, currentIndex);
jTable.getSelectionModel().setSelectionInterval(currentIndex, currentIndex);
}
setTableColumnWidths();
}
}
);
editButton.addActionListener(
new ActionListener() {
public void actionPerformed(final ActionEvent e) {
editRow(addRemovePanel);
}
}
);
jTable.addMouseListener(
new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() >= 2) {
editRow(addRemovePanel);
}
}
}
);
duplicateButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
// duplicate all selected rows as a block
AttributeGroup[] newRules = new AttributeGroup[jTable.getSelectedRowCount()];
for (int row = 0; row < jTable.getSelectedRowCount(); row++) {
final int currentIndex = jTable.getSelectedRows()[row];
final ChoicePanel choicePanel = (modelData.get(currentIndex));
AttributeGroup rule = choicePanel.getChoice().getChoiceObject();
AttributeGroup newRule = rule.deepCopy();
newRules[row] = newRule;
}
// now insert the new rows at the correct place
final int offset = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1] + 1;
for (int row = 0; row < newRules.length; row++) {
final AttributeGroup newRule = newRules[row];
modelData.add(row + offset, createOptionsPaneMsg(newRule));
list.add(row + offset, newRule);
model.fireTableRowsInserted(row + offset, row + offset);
}
}
}
);
removeButton.addActionListener(
new ActionListener() {
public void actionPerformed(final ActionEvent e) {
// remove a block of rules.
final int currentIndex = jTable.getSelectedRow();
if (currentIndex >= 0) {
final int first = jTable.getSelectedRows()[0];
final int last = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1];
for (int i = first; i <= last; i++) {
list.remove(currentIndex);
modelData.remove(currentIndex);
}
model.fireTableRowsDeleted(currentIndex, currentIndex);
int newSelIndex = (currentIndex >= model.getRowCount())
? model.getRowCount() - 1
: currentIndex;
jTable.getSelectionModel().setSelectionInterval(newSelIndex, newSelIndex);
setTableColumnWidths();
}
}
}
);
moveUpButton.addActionListener(
new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final int first = jTable.getSelectedRows()[0];
if (first <= 0) return;
final int last = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1];
for (int i = first; i <= last; i++) {
list.add(i - 1, list.remove(i));
modelData.add(i - 1, modelData.remove(i));
model.fireTableRowsUpdated(i - 1, i);
}
jTable.getSelectionModel().setSelectionInterval(first - 1, last - 1);
}
}
);
moveDownButton.addActionListener(
new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final int first = jTable.getSelectedRows()[0];
final int last = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1];
if (last + 1 >= jTable.getModel().getRowCount()) return;
for (int i = last; i >= first; i--) {
list.add(i + 1, (list.remove(i)));
modelData.add(i + 1, (modelData.remove(i)));
model.fireTableRowsUpdated(i, i + 1);
}
jTable.getSelectionModel().setSelectionInterval(first + 1, last + 1);
}
}
);
return addRemovePanel;
}
private ChoicePanel getOptionsPaneMsg(final ChoicePanel currentMsg) {
final ChoicePanel result = createChoicePanel();
if (currentMsg != null) {
result.copyChoices(currentMsg);
}
result.configurePanel();
return result;
}
private void editRow(final JPanel addRemovePanel) {
// edit first row of all rows selected
final int currentIndex = jTable.getSelectedRow();
final ChoicePanel o = modelData.get(currentIndex);
final ChoicePanel choicePanel = getOptionsPaneMsg(o);
final JOptionPane op = new JOptionPane(
choicePanel,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
null, null, null
);
final JDialog jd = op.createDialog(addRemovePanel, choicePanel.getChoicePanelName());
jd.setVisible(true);
final Object result = op.getValue();
if (result != null &&
((Integer)result) == JOptionPane.OK_OPTION)
{
final ChoicePanel value = (ChoicePanel)op.getMessage();
value.acceptEdited();
modelData.set(currentIndex, value);
list.set(currentIndex, ((com.wrq.rearranger.settings.attributeGroups.AttributeGroup)value.getChoice().getChoiceObject()));
model.fireTableRowsUpdated(currentIndex, currentIndex);
}
setTableColumnWidths();
}
// --------------------- GETTER / SETTER METHODS ---------------------
public final JPanel getPane() {
return pane;
}
// -------------------------- INNER CLASSES --------------------------
class Priority {
int priority;
public Priority(int priority) {
this.priority = priority;
}
public String toString() {
return "" + priority;
}
}
}
@@ -0,0 +1,145 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import com.wrq.rearranger.settings.ForceBlankLineSetting;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.Constraints;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
/** UI code for Spacing rules dialog. */
public class SpacingPane {
// ------------------------------ FIELDS ------------------------------
private final RearrangerSettings settings;
// --------------------------- CONSTRUCTORS ---------------------------
public SpacingPane(RearrangerSettings settings) {
this.settings = settings;
}
// -------------------------- OTHER METHODS --------------------------
public JPanel getPane() {
final JPanel panel = new JPanel(new GridBagLayout());
final Border border = BorderFactory.createEtchedBorder();
panel.setBorder(border);
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = 1.0d;
constraints.insets = new Insets(3, 3, 0, 0);
panel.add(getForceBlankLinePanel(settings.getAfterClassLBrace()), constraints.weightedLastCol());
constraints.newRow();
panel.add(getForceBlankLinePanel(settings.getBeforeClassRBrace()), constraints.weightedLastCol());
constraints.newRow();
panel.add(getForceBlankLinePanel(settings.getAfterClassRBrace()), constraints.weightedLastCol());
constraints.newRow();
panel.add(getForceBlankLinePanel(settings.getBeforeMethodLBrace()), constraints.weightedLastCol());
constraints.newRow();
panel.add(getForceBlankLinePanel(settings.getAfterMethodLBrace()), constraints.weightedLastCol());
constraints.newRow();
panel.add(getForceBlankLinePanel(settings.getBeforeMethodRBrace()), constraints.weightedLastCol());
constraints.newRow();
panel.add(getForceBlankLinePanel(settings.getAfterMethodRBrace()), constraints.weightedLastCol());
constraints.newRow();
panel.add(getForceBlankLinePanel(settings.getNewlinesAtEOF()), constraints.weightedLastCol());
constraints.weightedLastRow();
final JCheckBox insideBlockBox = new JCheckBox("Remove initial and final blank lines inside code block");
insideBlockBox.setSelected(settings.isRemoveBlanksInsideCodeBlocks());
panel.add(insideBlockBox, constraints.weightedLastCol());
insideBlockBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
settings.setRemoveBlanksInsideCodeBlocks(insideBlockBox.isSelected());
}
});
return panel;
}
private JPanel getForceBlankLinePanel(final ForceBlankLineSetting fbl) {
final JPanel panel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.lastRow();
final JCheckBox forceBox = new JCheckBox("Force");
forceBox.setSelected(fbl.isForce());
panel.add(forceBox, constraints.weightedFirstCol());
final NumberFormat integerInstance = NumberFormat.getIntegerInstance();
integerInstance.setMaximumIntegerDigits(2);
integerInstance.setMinimumIntegerDigits(1);
final JFormattedTextField nBlankLines = new JFormattedTextField(integerInstance);
nBlankLines.setValue(new Integer("88"));
Dimension d = nBlankLines.getPreferredSize();
d.width += 3;
nBlankLines.setPreferredSize(d);
nBlankLines.setValue(fbl.getnBlankLines());
nBlankLines.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
constraints.insets = new Insets(0, 3, 0, 0);
panel.add(nBlankLines, constraints.weightedNextCol());
nBlankLines.addPropertyChangeListener("value", new PropertyChangeListener() {
public void propertyChange(final PropertyChangeEvent evt) {
int n = ((Number)nBlankLines.getValue()).intValue();
if (n < 0) {
n = 0;
nBlankLines.setValue(n);
}
fbl.setnBlankLines(n);
}
});
String labelText = "blank lines " +
(fbl.isBefore() ? "before" : "after");
switch (fbl.getObject()) {
case ForceBlankLineSetting.CLASS_OBJECT:
labelText += " class ";
break;
case ForceBlankLineSetting.METHOD_OBJECT:
labelText += " method ";
break;
}
labelText += fbl.isOpenBrace() ? "open brace \"{\""
: "close brace \"}\"";
if (fbl.getObject() == ForceBlankLineSetting.EOF_OBJECT) {
labelText = "newline characters at end of file";
}
final JLabel blankLineLabel = new JLabel(labelText);
panel.add(blankLineLabel, constraints.lastCol());
nBlankLines.setEnabled(forceBox.isSelected());
blankLineLabel.setEnabled(forceBox.isSelected());
forceBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fbl.setForce(forceBox.isSelected());
nBlankLines.setEnabled(forceBox.isSelected());
blankLineLabel.setEnabled(forceBox.isSelected());
}
});
return panel;
}
}
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
* A JTextArea tied to a String field of this class. Initialize the JTextField from the field and update
* the field whenever the JTextField's text changes.
*/
public abstract class StringTextArea
extends JTextArea
{
abstract public void setValue(String value);
abstract public String getValue();
public StringTextArea() {
super();
setText(getValue());
getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
setValue(getText());
}
public void removeUpdate(DocumentEvent e) {
setValue(getText());
}
public void changedUpdate(DocumentEvent e) {
setValue(getText());
}
});
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
* A JTextField tied to a String field of this class. Initialize the JTextField from the field and update
* the field whenever the JTextField's text changes.
*/
public abstract class StringTextField
extends JTextField
{
abstract public void setValue(String value);
abstract public String getValue();
public StringTextField() {
super();
setText(getValue());
getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
setValue(getText());
}
public void removeUpdate(DocumentEvent e) {
setValue(getText());
}
public void changedUpdate(DocumentEvent e) {
setValue(getText());
}
});
}
}
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
/**
* In a chain of data manipulators some behaviour is common. TableMap
* provides most of this behaviour and can be subclassed by filters
* that only need to override a handful of specific methods. TableMap
* implements TableModel by routing all requests to its model, and
* TableModelListener by routing all events to its listeners. Inserting
* a TableMap which has not been subclassed into a chain of table filters
* should have no effect.
*
* @version 1.4 12/17/97
* @author Philip Milne
*/
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
public class TableMap
extends AbstractTableModel
implements TableModelListener
{
// ------------------------------ FIELDS ------------------------------
protected TableModel model;
// --------------------- GETTER / SETTER METHODS ---------------------
public void setModel(TableModel model) {
this.model = model;
model.addTableModelListener(this);
}
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface TableModel ---------------------
public int getColumnCount() {
return (model == null) ? 0 : model.getColumnCount();
}
public int getRowCount() {
return (model == null) ? 0 : model.getRowCount();
}
public boolean isCellEditable(int row, int column) {
return model.isCellEditable(row, column);
}
public Class getColumnClass(int aColumn) {
return model.getColumnClass(aColumn);
}
// By default, implement TableModel by forwarding all messages
// to the model.
public Object getValueAt(int aRow, int aColumn) {
return model.getValueAt(aRow, aColumn);
}
public void setValueAt(Object aValue, int aRow, int aColumn) {
model.setValueAt(aValue, aRow, aColumn);
}
public String getColumnName(int aColumn) {
return model.getColumnName(aColumn);
}
// --------------------- Interface TableModelListener ---------------------
//
// Implementation of the TableModelListener interface,
//
// By default forward all events to all the listeners.
public void tableChanged(TableModelEvent e) {
fireTableChanged(e);
}
}
@@ -0,0 +1,341 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.configuration;
/**
* A sorter for TableModels. The sorter has a model (conforming to TableModel)
* and itself implements TableModel. TableSorter does not store or copy
* the data in the TableModel, instead it maintains an array of
* integers which it keeps the same size as the number of rows in its
* model. When the model changes it notifies the sorter that something
* has changed eg. "rowsAdded" so that its internal array of integers
* can be reallocated. As requests are made of the sorter (like
* getValueAt(row, col) it redirects them to its model via the mapping
* array. That way the TableSorter appears to hold another copy of the table
* with the rows in a different order. The sorting algorthm used is stable
* which means that it does not move around rows when its comparison
* function returns 0 to denote that they are equivalent.
*
* @version 1.5 12/17/97
* @author Philip Milne
*/
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Date;
import java.util.List;
import java.util.Vector;
public class TableSorter extends TableMap {
// ------------------------------ FIELDS ------------------------------
int[] indexes;
List<Integer> sortingColumns = new Vector<Integer>();
boolean ascending = true;
int compares;
// --------------------------- CONSTRUCTORS ---------------------------
public TableSorter() {
indexes = new int[0]; // for consistency
}
public TableSorter(TableModel model) {
setModel(model);
}
public void setModel(TableModel model) {
super.setModel(model);
reallocateIndexes();
}
public void reallocateIndexes() {
int rowCount = model.getRowCount();
// Set up a new array of indexes with the right number of elements
// for the new data model.
indexes = new int[rowCount];
// Initialise with the identity mapping.
for (int row = 0; row < rowCount; row++) {
indexes[row] = row;
}
}
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface TableModel ---------------------
// The mapping only affects the contents of the data rows.
// Pass all requests to these rows through the mapping array: "indexes".
public Object getValueAt(int aRow, int aColumn) {
checkModel();
return model.getValueAt(indexes[aRow], aColumn);
}
public void setValueAt(Object aValue, int aRow, int aColumn) {
checkModel();
model.setValueAt(aValue, indexes[aRow], aColumn);
}
// --------------------- Interface TableModelListener ---------------------
public void tableChanged(TableModelEvent e) {
reallocateIndexes();
super.tableChanged(e);
}
// -------------------------- OTHER METHODS --------------------------
// There is nowhere else to put this.
// Add a mouse listener to the Table to trigger a table sort
// when a column heading is clicked in the JTable.
public void addMouseListenerToHeaderInTable(JTable table) {
final TableSorter sorter = this;
final JTable tableView = table;
tableView.setColumnSelectionAllowed(false);
MouseAdapter listMouseListener = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
TableColumnModel columnModel = tableView.getColumnModel();
int viewColumn = columnModel.getColumnIndexAtX(e.getX());
int column = tableView.convertColumnIndexToModel(viewColumn);
if (e.getClickCount() == 1 && column != -1) {
int shiftPressed = e.getModifiers() & InputEvent.SHIFT_MASK;
boolean ascending = defaultSortOrderAscending(column) ^ (shiftPressed != 0);
sorter.sortByColumn(column, ascending);
}
}
};
JTableHeader th = tableView.getTableHeader();
th.addMouseListener(listMouseListener);
}
public boolean defaultSortOrderAscending(int column) {
return true;
}
public void sortByColumn(int column, boolean ascending) {
this.ascending = ascending;
sortingColumns.clear();
sortingColumns.add(column);
sort(this);
super.tableChanged(new TableModelEvent(this));
}
public void sort(TableSorter sender) {
checkModel();
compares = 0;
// n2sort();
// qsort(0, indexes.length-1);
shuttlesort(indexes.clone(), indexes, 0, indexes.length);
}
public void checkModel() {
if (indexes.length != model.getRowCount()) {
throw new RuntimeException("Sorter not informed of a change in model.");
}
}
// This is a home-grown implementation which we have not had time
// to research - it may perform poorly in some circumstances. It
// requires twice the space of an in-place algorithm and makes
// NlogN assigments shuttling the values between the two
// arrays. The number of compares appears to vary between N-1 and
// NlogN depending on the initial order but the main reason for
// using it here is that, unlike qsort, it is stable.
public void shuttlesort(int[] from, int[] to, int low, int high) {
if (high - low < 2) {
return;
}
int middle = (low + high) / 2;
shuttlesort(to, from, low, middle);
shuttlesort(to, from, middle, high);
int p = low;
int q = middle;
/* This is an optional short-cut; at each recursive call,
check to see if the elements in this subset are already
ordered. If so, no further comparisons are needed; the
sub-array can just be copied. The array must be copied rather
than assigned otherwise sister calls in the recursion might
get out of sinc. When the number of elements is three they
are partitioned so that the first set, [low, mid), has one
element and and the second, [mid, high), has two. We skip the
optimisation when the number of elements is three or less as
the first compare in the normal merge will produce the same
sequence of steps. This optimisation seems to be worthwhile
for partially ordered lists but some analysis is needed to
find out how the performance drops to Nlog(N) as the initial
order diminishes - it may drop very quickly. */
if (high - low >= 4 && compare(from[middle - 1], from[middle]) <= 0) {
for (int i = low; i < high; i++) {
to[i] = from[i];
}
return;
}
// A normal merge.
for (int i = low; i < high; i++) {
if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
to[i] = from[p++];
}
else {
to[i] = from[q++];
}
}
}
public int compare(int row1, int row2) {
compares++;
for (Integer column : sortingColumns) {
int result = compareRowsByColumn(row1, row2, column);
if (result != 0) {
return ascending ? result : -result;
}
}
return 0;
}
public int compareRowsByColumn(int row1, int row2, int column) {
Class type = model.getColumnClass(column);
TableModel data = model;
// Check for nulls.
Object o1 = data.getValueAt(row1, column);
Object o2 = data.getValueAt(row2, column);
// If both values are null, return 0.
if (o1 == null && o2 == null) {
return 0;
}
else if (o1 == null) { // Define null less than everything.
return -1;
}
else if (o2 == null) {
return 1;
}
/*
* We copy all returned values from the getValue call in case
* an optimised model is reusing one object to return many
* values. The Number subclasses in the JDK are immutable and
* so will not be used in this way but other subclasses of
* Number might want to do this to save space and avoid
* unnecessary heap allocation.
*/
if (type.getSuperclass() == java.lang.Number.class) {
Number n1 = (Number)data.getValueAt(row1, column);
double d1 = n1.doubleValue();
Number n2 = (Number)data.getValueAt(row2, column);
double d2 = n2.doubleValue();
if (d1 < d2) {
return -1;
}
else if (d1 > d2) {
return 1;
}
else {
return 0;
}
}
else if (type == java.util.Date.class) {
Date d1 = (Date)data.getValueAt(row1, column);
long n1 = d1.getTime();
Date d2 = (Date)data.getValueAt(row2, column);
long n2 = d2.getTime();
if (n1 < n2) {
return -1;
}
else if (n1 > n2) {
return 1;
}
else {
return 0;
}
}
else if (type == String.class) {
String s1 = (String)data.getValueAt(row1, column);
String s2 = (String)data.getValueAt(row2, column);
int result = s1.compareTo(s2);
if (result < 0) {
return -1;
}
else if (result > 0) {
return 1;
}
else {
return 0;
}
}
else if (type == Boolean.class) {
Boolean bool1 = (Boolean)data.getValueAt(row1, column);
boolean b1 = bool1;
Boolean bool2 = (Boolean)data.getValueAt(row2, column);
boolean b2 = bool2;
if (b1 == b2) {
return 0;
}
else if (b1) { // Define false < true
return 1;
}
else {
return -1;
}
}
else {
Object v1 = data.getValueAt(row1, column);
String s1 = v1.toString();
Object v2 = data.getValueAt(row2, column);
String s2 = v2.toString();
int result = s1.compareTo(s2);
if (result < 0) {
return -1;
}
else if (result > 0) {
return 1;
}
else {
return 0;
}
}
}
}
@@ -0,0 +1,360 @@
<!--
~ Copyright (c) 2003, 2010, Dave Kriewall
~ All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
~ following conditions are met:
~
~ 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
~ disclaimer.
~
~ 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
~ disclaimer in the documentation and/or other materials provided with the distribution.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
~ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
~ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
~ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<component name="Rearranger">
<Rearranger KeepGettersSettersTogether="true" KeepGettersSettersWithProperty="false" KeepOverloadedMethodsTogether="true"
ConfirmBeforeRearranging="false" RearrangeInnerClasses="false" globalCommentPattern="" overloadedOrder="1"
ShowParameterTypes="true" ShowParameterNames="false" ShowFields="true" ShowTypeAfterMethod="true" ShowRules="true"
ShowMatchedRules="false" ShowComments="false" RemoveBlanksInsideCodeBlocks="true">
<Items>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="7" allPrecedingRules="true" allSubsequentRules="false"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ ------------------------------\ FIELDS\
------------------------------\n
</Comment>
<Field priority="1">
<ProtectionLevel public="true" private="false" protected="false" package="false" invert="false"/>
<Static value="true" invert="false"/>
<Final value="true" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<InitializedToAnonymousClass value="false" invert="false"/>
<Transient value="false" invert="false"/>
<Volatile value="false" invert="false"/>
<TypeMatch match="false" invert="false" pattern=""/>
</Field>
<Field priority="1">
<ProtectionLevel public="true" private="false" protected="false" package="false" invert="false"/>
<Static value="true" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<InitializedToAnonymousClass value="false" invert="false"/>
<Transient value="false" invert="false"/>
<Volatile value="false" invert="false"/>
<TypeMatch match="false" invert="false" pattern=""/>
</Field>
<Field priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="true" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<InitializedToAnonymousClass value="false" invert="false"/>
<Transient value="false" invert="false"/>
<Volatile value="false" invert="false"/>
<TypeMatch match="false" invert="false" pattern=""/>
</Field>
<Field priority="1">
<ProtectionLevel public="true" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<InitializedToAnonymousClass value="false" invert="false"/>
<Transient value="false" invert="false"/>
<Volatile value="false" invert="false"/>
<TypeMatch match="false" invert="false" pattern=""/>
</Field>
<Field priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="true" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<InitializedToAnonymousClass value="false" invert="false"/>
<Transient value="false" invert="false"/>
<Volatile value="false" invert="false"/>
<TypeMatch match="false" invert="false" pattern=""/>
</Field>
<Field priority="1">
<ProtectionLevel public="false" private="false" protected="true" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<InitializedToAnonymousClass value="false" invert="false"/>
<Transient value="false" invert="false"/>
<Volatile value="false" invert="false"/>
<TypeMatch match="false" invert="false" pattern=""/>
</Field>
<Field priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<InitializedToAnonymousClass value="false" invert="false"/>
<Transient value="false" invert="false"/>
<Volatile value="false" invert="false"/>
<TypeMatch match="false" invert="false" pattern=""/>
</Field>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ --------------------------\ STATIC\ METHODS\
--------------------------\n
</Comment>
<Method priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="true" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Native value="false" invert="false"/>
<Synchronized value="false" invert="false"/>
<Overridden value="false" invert="false"/>
<Overriding value="false" invert="false"/>
<Implemented value="false" invert="false"/>
<Implementing value="false" invert="false"/>
<Initializer value="false" invert="false"/>
<ReturnTypeMatch match="false" invert="false" pattern=""/>
<MIN_PARAMS match="false" opType="0" value="0"/>
<MAX_PARAMS match="false" opType="1" value="0"/>
<Misc constructorMethod="false" getterSetter="false" canonicalMethod="false" otherMethod="false" invertMethod="false"
noExtractedMethods="false"/>
<GetterSetterDefinition getterBody="0" getterName="0" setterBody="0" setterName="0"/>
</Method>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ ---------------------------\ CONSTRUCTORS\
---------------------------\n
</Comment>
<Method priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Native value="false" invert="false"/>
<Synchronized value="false" invert="false"/>
<Overridden value="false" invert="false"/>
<Overriding value="false" invert="false"/>
<Implemented value="false" invert="false"/>
<Implementing value="false" invert="false"/>
<Initializer value="false" invert="false"/>
<ReturnTypeMatch match="false" invert="false" pattern=""/>
<MIN_PARAMS match="false" opType="0" value="0"/>
<MAX_PARAMS match="false" opType="1" value="0"/>
<Misc constructorMethod="true" getterSetter="false" canonicalMethod="false" otherMethod="false" invertMethod="false"
noExtractedMethods="false"/>
<GetterSetterDefinition getterBody="0" getterName="0" setterBody="0" setterName="0"/>
</Method>
<Method priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Native value="false" invert="false"/>
<Synchronized value="false" invert="false"/>
<Overridden value="false" invert="false"/>
<Overriding value="false" invert="false"/>
<Implemented value="false" invert="false"/>
<Implementing value="false" invert="false"/>
<Initializer value="true" invert="false"/>
<ReturnTypeMatch match="false" invert="false" pattern=""/>
<MIN_PARAMS match="false" opType="0" value="0"/>
<MAX_PARAMS match="false" opType="1" value="0"/>
<Misc constructorMethod="false" getterSetter="false" canonicalMethod="false" otherMethod="false" invertMethod="false"
noExtractedMethods="false"/>
<GetterSetterDefinition getterBody="0" getterName="0" setterBody="0" setterName="0"/>
</Method>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ ---------------------\ GETTER\ /\ SETTER\ METHODS\
---------------------\n
</Comment>
<Method priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="true" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Native value="false" invert="false"/>
<Synchronized value="false" invert="false"/>
<Overridden value="false" invert="false"/>
<Overriding value="false" invert="false"/>
<Implemented value="false" invert="false"/>
<Implementing value="false" invert="false"/>
<Initializer value="false" invert="false"/>
<ReturnTypeMatch match="false" invert="false" pattern=""/>
<MIN_PARAMS match="false" opType="0" value="0"/>
<MAX_PARAMS match="false" opType="1" value="0"/>
<Misc constructorMethod="false" getterSetter="true" canonicalMethod="false" otherMethod="false" invertMethod="false"
noExtractedMethods="false"/>
<GetterSetterDefinition getterBody="0" getterName="0" setterBody="0" setterName="0"/>
</Method>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ ------------------------\ CANONICAL\ METHODS\
------------------------\n
</Comment>
<Method priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="true" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Native value="false" invert="false"/>
<Synchronized value="false" invert="false"/>
<Overridden value="false" invert="false"/>
<Overriding value="false" invert="false"/>
<Implemented value="false" invert="false"/>
<Implementing value="false" invert="false"/>
<Initializer value="false" invert="false"/>
<ReturnTypeMatch match="false" invert="false" pattern=""/>
<MIN_PARAMS match="false" opType="0" value="0"/>
<MAX_PARAMS match="false" opType="1" value="0"/>
<Misc constructorMethod="false" getterSetter="false" canonicalMethod="true" otherMethod="false" invertMethod="false"
noExtractedMethods="false"/>
<GetterSetterDefinition getterBody="0" getterName="0" setterBody="0" setterName="0"/>
</Method>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ ------------------------\ INTERFACE\ METHODS\
------------------------\n
</Comment>
<Interface alphabetizeInterfaces="true" noExtractedMethods="true" methodOrder="1" priority="1" fillString=""
useProjectWidthForFill="true" fillWidth="0">
<NameMatch match="false" invert="false" pattern=""/>
<PrecedingComment>
<Comment condition="0" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ ---------------------\ Interface\ %IF%\
---------------------\n
</Comment>
</PrecedingComment>
<TrailingComment>
<Comment condition="0" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0"/>
</TrailingComment>
</Interface>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ --------------------------\ OTHER\ METHODS\
--------------------------\n
</Comment>
<Method priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="true" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Native value="false" invert="false"/>
<Synchronized value="false" invert="false"/>
<Overridden value="false" invert="false"/>
<Overriding value="false" invert="false"/>
<Implemented value="false" invert="false"/>
<Implementing value="false" invert="false"/>
<Initializer value="false" invert="false"/>
<ReturnTypeMatch match="false" invert="false" pattern=""/>
<MIN_PARAMS match="false" opType="0" value="0"/>
<MAX_PARAMS match="false" opType="1" value="0"/>
<Misc constructorMethod="false" getterSetter="false" canonicalMethod="false" otherMethod="false" invertMethod="false"
noExtractedMethods="false"/>
<GetterSetterDefinition getterBody="0" getterName="0" setterBody="0" setterName="0"/>
</Method>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ --------------------------\ ENUMERATIONS\
--------------------------\n
</Comment>
<InnerClass priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Enum value="true" invert="false"/>
</InnerClass>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ --------------------------\ INNER\ CLASSES\
--------------------------\n
</Comment>
<InnerClass priority="1">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Enum value="false" invert="false"/>
</InnerClass>
<Comment condition="2" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0">\n//\ ---------------------------\ main()\ method\
---------------------------\n
</Comment>
<Method priority="2">
<ProtectionLevel public="false" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="true" invert="false" pattern="main"/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Native value="false" invert="false"/>
<Synchronized value="false" invert="false"/>
<Overridden value="false" invert="false"/>
<Overriding value="false" invert="false"/>
<Implemented value="false" invert="false"/>
<Implementing value="false" invert="false"/>
<Initializer value="false" invert="false"/>
<ReturnTypeMatch match="false" invert="false" pattern=""/>
<MIN_PARAMS match="false" opType="0" value="0"/>
<MAX_PARAMS match="false" opType="1" value="0"/>
<Misc constructorMethod="false" getterSetter="false" canonicalMethod="false" otherMethod="false" invertMethod="false"
noExtractedMethods="false"/>
<GetterSetterDefinition getterBody="0" getterName="0" setterBody="0" setterName="0"/>
</Method>
</Items>
<Classes>
<Class priority="1">
<ProtectionLevel public="true" private="false" protected="false" package="false" invert="false"/>
<Static value="false" invert="false"/>
<Final value="false" invert="false"/>
<NameMatch match="false" invert="false" pattern=""/>
<SortOptions byModifiers="false" byType="false" isTypeCaseInsensitive="false" byName="false" isNameCaseInsensitive="false"/>
<Abstract value="false" invert="false"/>
<Enum value="false" invert="false"/>
</Class>
</Classes>
<DefaultGetterSetterDefinition>
<GetterSetterDefinition getterBody="0" getterName="0" setterBody="0" setterName="0"/>
</DefaultGetterSetterDefinition>
<RelatedMethods moveExtractedMethods="true" belowFirstCaller="true" depthFirstOrdering="true" ordering="0" nonPrivateTreatment="2"
commentType="0" fillString="" useProjectWidthForFill="true" fillWidth="0">
<PrecedingComment>
<Comment condition="0" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0"/>
</PrecedingComment>
<TrailingComment>
<Comment condition="0" nPrecedingRulesToMatch="1" nSubsequentRulesToMatch="1" allPrecedingRules="true" allSubsequentRules="true"
fillString="" useProjectWidthForFill="true" fillWidth="0"/>
</TrailingComment>
</RelatedMethods>
<AfterClassLBrace Force="true" nBlankLines="0"/>
<AfterClassRBrace Force="true" nBlankLines="1"/>
<BeforeClassRBrace Force="true" nBlankLines="0"/>
<BeforeMethodLBrace Force="false" nBlankLines="1"/>
<AfterMethodLBrace Force="true" nBlankLines="0"/>
<AfterMethodRBrace Force="true" nBlankLines="1"/>
<BeforeMethodRBrace Force="true" nBlankLines="0"/>
<NewlinesAtEOF Force="false" nBlankLines="1"/>
</Rearranger>
</component>
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.wrq.rearranger.popup.IFilePopupEntry;
import com.wrq.rearranger.popup.RearrangerTreeNode;
import com.wrq.rearranger.settings.RearrangerSettings;
import javax.swing.tree.DefaultMutableTreeNode;
/**
* Describes the fields, methods, and inner class declarations of a class. This information is used to reorder
* these declarations within an outer class.
*/
public abstract class ClassContentsEntry
extends RangeEntry
implements IFilePopupEntry
{
public ClassContentsEntry(final PsiElement start,
final PsiElement end,
final int modifiers,
final String modifierString,
final String name,
final String type)
{
super(start, end, modifiers, modifierString, name, type);
}
public ClassContentsEntry(final PsiElement start,
final PsiElement end,
final boolean fixedHeader,
final boolean fixedTrailer)
{
super(start, end, fixedHeader, fixedTrailer);
}
public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) {
DefaultMutableTreeNode node = null;
if ((end instanceof PsiField && settings.isShowFields()) ||
(this instanceof ClassEntry))
{
node = new RearrangerTreeNode(this, name);
parent.add(node);
}
return node;
}
}
@@ -0,0 +1,576 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.util.Query;
import com.wrq.rearranger.ModifierConstants;
import com.wrq.rearranger.popup.IFilePopupEntry;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.rearrangement.GenericRearranger;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.ModifierUtils;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* Describes an entire class's range and type.
* This information is used when reordering outer classes.
*/
public class ClassEntry
extends ClassContentsEntry
implements IFilePopupEntry
{
private static final Logger LOG = Logger.getInstance("#" + ClassEntry.class.getName());
protected final List<ClassContentsEntry> contents;
private List<IRuleInstance> resultRuleInstances;
private final RearrangerSettings settings;
private final int nestingLevel;
public ClassEntry(PsiElement start,
PsiElement end,
int modifiers,
String modifierString,
String name,
int nestingLevel,
RearrangerSettings settings)
{
super(start, end, modifiers, modifierString, name, "");
contents = new ArrayList<ClassContentsEntry>();
resultRuleInstances = null;
this.settings = settings;
this.nestingLevel = nestingLevel;
}
public String getTypeIconName() {
String result = "nodes/class";
if (end.getParent() instanceof PsiClass) {
PsiClass psiClass = (PsiClass)end.getParent();
if (psiClass.isEnum()) {
result = "nodes/enum";
}
else if (psiClass.isInterface()) {
result = "nodes/interface";
}
}
return result;
}
public String[] getAdditionalIconNames() {
if (end instanceof PsiJavaToken && end.getText().equals("{")) {
PsiClass psiClass = (PsiClass)end.getParent();
if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) {
return new String[]{"nodes/c_public"};
}
if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PROTECTED)) {
return new String[]{"nodes/c_protected"};
}
if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) {
return new String[]{"nodes/c_private"};
}
return new String[]{"nodes/c_plocal"};
}
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
return new JLabel(name);
}
protected void parseRemainingClassContents(final Project project,
int startingIndex,
final PsiElement psiClass
)
{
final PsiSearchHelper psh = PsiSearchHelper.SERVICE.getInstance(project);
int lastIndex = startingIndex;
/**
* if option indicates, don't parse inner class contents; leave them unchanged.
*/
if (settings.isRearrangeInnerClasses() || nestingLevel <= 1) {
for (int i = startingIndex; i < psiClass.getChildren().length; i++) {
PsiElement child = psiClass.getChildren()[i];
if (child instanceof PsiJavaToken && child.getText().equals("{")) {
lastIndex = i + 1; // first item of a class starts immediately after the class left brace.
}
LOG.debug(psiClass.toString() + " child " + i + ":" + child.toString());
if (child instanceof PsiField ||
child instanceof PsiMethod ||
child instanceof PsiClass ||
child instanceof PsiClassInitializer)
{
MemberAttributes attributes = new MemberAttributes();
PsiElement startElement = psiClass.getChildren()[lastIndex];
ClassContentsEntry classContentsEntry = null;
if (child instanceof PsiField) {
i = parseField(child, attributes, i, (PsiClass)psiClass);
// a field declaration with multiple fields like "int x, y;" must advance child to "y;"
// to prevent splitting.
child = psiClass.getChildren()[i];
classContentsEntry = new FieldEntry(
startElement,
child,
attributes.modifiers,
attributes.modifierString,
attributes.name,
attributes.type
);
}
if (child instanceof PsiMethod) {
parseMethod(child, attributes, psh);
classContentsEntry = new MethodEntry(
startElement,
child,
attributes.modifiers,
attributes.modifierString,
attributes.name,
attributes.type,
attributes.nParameters,
attributes.interfaceName
);
}
if (child instanceof PsiClass) {
parseClassAttributes(child, attributes);
//
// if child is an enum, set the last entry past the LBrace to the final enumeration or the
// semicolon thereafter, if any.
//
PsiClass clazz = (PsiClass)child;
PsiElement clazzEnd;
int startElementIndex = 0;
if (clazz.isEnum()) {
// we want to skip all the enumeration fields, including terminating semicolon if present.
// class parsing begins after these.
startElementIndex = findLastEnumTerminator(clazz);
clazzEnd = clazz.getChildren()[startElementIndex];
startElementIndex++;
}
else {
// normal class: parse everything after the left brace.
clazzEnd = clazz.getLBrace();
startElementIndex = Arrays.asList(clazz.getChildren()).indexOf(clazzEnd) + 1;
}
ClassEntry entry = new ClassEntry(
startElement,
clazzEnd,
attributes.modifiers,
attributes.modifierString,
attributes.name,
nestingLevel + 1,
settings
);
classContentsEntry = entry;
entry.parseRemainingClassContents(
project,
startElementIndex,
child);
}
if (child instanceof PsiClassInitializer) {
parseClassInitializer(child, attributes);
classContentsEntry = new ClassInitializerEntry(startElement,
child,
attributes.modifiers,
attributes.modifierString,
attributes.name);
}
contents.add(classContentsEntry);
classContentsEntry.checkForComment();
lastIndex = i + 1; // next class includes everything since the end of the prior class.
}
}
}
if (lastIndex < psiClass.getChildren().length) {
if (lastIndex < 0) {
lastIndex = 0;
}
// create a dummy trailer entry to cover anything after the last class.
final MiscellaneousTextEntry miscellaneousTextEntry = new MiscellaneousTextEntry(
psiClass.getChildren()[lastIndex],
psiClass.getChildren()[psiClass.getChildren().length - 1],
false, true
);
contents.add(miscellaneousTextEntry);
miscellaneousTextEntry.checkForComment();
}
}
/**
* Search for the end of the enumeration's fields. It may be terminated with a semicolon, in which case we want
* to point to the next item. If no semicolon is found, we want to point to the enum's right brace.
*
* @param clazz
* @return starting element index for the portion of the enumeration class following its enum declarations.
*/
private int findLastEnumTerminator(PsiClass clazz) {
int startElementIndex = 0;
// go until we hit RBrace (non-inclusive), or semicolon (inclusive)
boolean foundLBrace = false;
for (int j = 0; j < clazz.getChildren().length; j++) {
PsiElement psiElement = clazz.getChildren()[j];
if (!foundLBrace) {
if (psiElement == clazz.getLBrace()) {
foundLBrace = true;
}
}
else {
startElementIndex = j;
if (psiElement == clazz.getRBrace()) {
break;
}
if (psiElement instanceof PsiJavaToken &&
((PsiJavaToken)psiElement).getTokenType() == JavaTokenType.SEMICOLON)
{
break;
}
}
}
return startElementIndex;
}
private int parseField(PsiElement child, MemberAttributes attributes, int i, final PsiClass psiClass) {
attributes.field = (PsiField)child;
LOG.debug("enter parseField: child=" +
(child == null ? "null" : child.toString()));
attributes.name = attributes.field.getName();
if (attributes.field.getTypeElement() == null) {
attributes.type = attributes.field.getContainingClass().getName(); // if enum, use class as type
}
else {
attributes.type = attributes.field.getTypeElement().getText();
}
attributes.modifierString = attributes.field.getModifierList().getText();
attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString);
if (attributes.field.getContainingClass().isInterface()) {
// all fields in an interface are constants, hence "public static final"
attributes.modifiers |= Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
}
if (attributes.field.getInitializer() instanceof PsiNewExpression) {
final PsiElement lc = attributes.field.getInitializer().getLastChild();
if (lc instanceof PsiAnonymousClass) {
attributes.modifiers |= ModifierConstants.INIT_TO_ANON_CLASS;
}
}
LOG.debug(
"parseField: name=" +
attributes.name +
", modifiers=" +
Integer.toHexString(attributes.modifiers)
);
/**
* handle multiple declarations here. While this field declaration does not end
* in a semicolon, skip whitespace and intervening comma; move child ahead to
* next field. This prevents declarations like "int b, a;" from being split.
*/
PsiElement myChild = child;
boolean done = false;
while (!done) {
PsiElement lastElement = myChild.getLastChild();
LOG.debug("parseField: getLastChild=" +
(lastElement == null ? "null" : lastElement.toString()));
if (lastElement == null) break;
if (lastElement instanceof PsiErrorElement) break;
if (lastElement instanceof PsiJavaToken &&
((PsiJavaToken)lastElement).getTokenType() == JavaTokenType.SEMICOLON)
{
break;
}
if (lastElement instanceof PsiComment) {
break;
}
// skip to next field
LOG.debug(
"parseField:skipping to next field, i=" +
i +
", psiClass=" + psiClass.getName()
);
LOG.debug(
"parseField: psiClass children array length=" +
psiClass.getChildren().length
);
while (++i < psiClass.getChildren().length) {
myChild = psiClass.getChildren()[i];
LOG.debug("parseField: myChild=" + myChild.toString());
if (myChild instanceof PsiField) {
done = true;
break;
}
}
}
return i;
}
private void parseMethod(PsiElement child, MemberAttributes attributes, final PsiSearchHelper psh) {
attributes.method = (PsiMethod)child;
attributes.name = attributes.method.getName();
if (attributes.method.getReturnTypeElement() == null) {
attributes.type = "null";
}
else {
attributes.type = attributes.method.getReturnTypeElement().getText();
}
attributes.modifierString = attributes.method.getModifierList().getText();
attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString);
attributes.nParameters = attributes.method.getParameterList().getParameters().length;
if (attributes.method.getContainingClass().isInterface()) {
// methods in an interface are always considered public
attributes.modifiers |= Modifier.PUBLIC;
}
// set any additional "modifier" flags.
// final Query<MethodSignatureBackedByPsiMethod> sm2 = SuperMethodsSearch.search(attributes.method,
// attributes.method.getContainingClass(), false, false);
// for (MethodSignatureBackedByPsiMethod msb : sm2) {
// System.out.println(msb.getMethod().getName());
// } // seems to be no different than method.findSuperMethods()
attributes.modifiers |= isCanonicalOrInterface(attributes.method, attributes);
final SearchScope ss = psh.getUseScope(child);
final Query<PsiMethod> query = OverridingMethodsSearch.search(attributes.method, ss, true);
final PsiMethod method = query.findFirst();
if (method != null) {
final Collection<PsiMethod> overridersCollection = query.findAll();
final PsiMethod[] overriders = overridersCollection.toArray(new PsiMethod[overridersCollection.size()]);
LOG.debug(
"method " +
attributes.method.toString() +
" is overridden; has " +
overriders.length + " overriding methods:"
);
dumpMethodNames(overriders);
if (attributes.method.getBody() == null) {
attributes.modifiers |= ModifierConstants.IMPLEMENTED;
}
else {
attributes.modifiers |= ModifierConstants.OVERRIDDEN;
}
}
// determine if this method overrides another.
final PsiMethod[] superMethods = attributes.method.findSuperMethods(false);
LOG.debug("method " + attributes.method.toString() + " has " + superMethods.length + " supermethods");
dumpMethodNames(superMethods);
if (superMethods.length > 0) {
// determine if supermethod is abstract or interface; if so, assign IMPLEMENTING attribute.
PsiMethod superMethod = superMethods[0];
boolean abztract = superMethod.getModifierList().hasModifierProperty(PsiModifier.ABSTRACT);
PsiClass superclass = superMethod.getContainingClass();
if (abztract || (
superclass != null && superclass.isInterface()))
{
attributes.modifiers |= ModifierConstants.IMPLEMENTING;
}
else {
attributes.modifiers |= ModifierConstants.OVERRIDING;
}
}
if (attributes.method.isConstructor()) {
attributes.modifiers |= ModifierConstants.CONSTRUCTOR;
}
/** getter/setter cannot be determined here because definition of what a getter/setter
* is can vary from rule to rule. Do it at the time of rule matching.
*/
else if ((attributes.modifiers & ModifierConstants.CANONICAL) == 0) {
attributes.modifiers |= ModifierConstants.OTHER_METHOD;
}
LOG.debug(
"method " +
attributes.name +
" attributes: " +
ModifierConstants.toString(attributes.modifiers)
);
}
private int isCanonicalOrInterface(PsiMethod method, MemberAttributes attributes) {
PsiElement methodParent = method.getParent();
LOG.debug("checking to see if " + method.getName() + " of " + methodParent + " is canonical");
PsiMethod[] superMethods = method.findSuperMethods();
LOG.debug("result of findSuperMethods for " + method.getName() + ": size=" + superMethods.length);
// check to see if this method is canonical (inherited from Object).
for (PsiMethod m : superMethods) {
PsiElement parent = m.getParent();
LOG.debug(
"supermethod " +
m.getName() +
" belongs to " +
parent
);
if (parent instanceof PsiClass) {
final PsiClass psiClass = ((PsiClass)parent);
if (psiClass.isInterface()) {
LOG.debug("method " + method.toString() + " implements interface");
attributes.interfaceName = psiClass.getName();
}
PsiElement superclass = psiClass.getSuperClass();
if (superclass == null) {
// m's class must be java.lang.Object; it's the only class with a null
// superclass.
LOG.debug("method " + method.toString() + " is canonical");
return ModifierConstants.CANONICAL;
}
else {
int result = isCanonicalOrInterface(m, attributes);
// int result = 0;
// if (!superclass.toString().equalsIgnoreCase("psiclass:object"))
// {
// result = isCanonicalOrInterface(m, attributes);
// }
if (result > 0) {
LOG.debug("Returning result from canonical check as " + result);
return result;
}
}
}
}
return 0;
}
private void dumpMethodNames(PsiMethod[] methods) {
for (int j = 0; j < methods.length; j++) {
LOG.debug(
j +
":" +
methods[j].toString() +
" of class " +
methods[j].getParent().toString()
);
}
}
private void parseClassAttributes(PsiElement child, MemberAttributes attributes) {
attributes.childClass = (PsiClass)child;
attributes.name = attributes.childClass.getName();
if (attributes.name == null) {
attributes.name = "";
}
attributes.modifierString = attributes.childClass.getModifierList().getText();
attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString);
attributes.type = attributes.childClass.isEnum() ? "enum" : "class";
if (attributes.childClass.isEnum()) {
attributes.modifiers |= ModifierConstants.ENUM;
}
}
private void parseClassInitializer(PsiElement child, MemberAttributes attributes) {
attributes.classInitializer = (PsiClassInitializer)child;
attributes.classInitializer.getModifierList();
attributes.name = "";
attributes.modifierString = attributes.classInitializer.getModifierList().getText();
attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString) |
ModifierConstants.INITIALIZER;
}
public void emit(Emitter emitter) {
// first emit the text up to and including the left brace.
super.emit(emitter);
// now emit all children.
emitter.emitRuleInstances(getResultRuleInstances());
}
public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) {
DefaultMutableTreeNode result = super.addToPopupTree(parent, settings);
// now add class contents, if any
if (getResultRuleInstances() != null) {
for (IRuleInstance instance : getResultRuleInstances()) {
instance.addRuleInstanceToPopupTree(result, settings);
}
}
return result;
}
/** rearranges the contents of this PsiClass according to supplied rules. */
public void rearrangeContents() {
buildMethodCallGraph();
LOG.debug("identifying setters and extracted (related) methods");
for (ClassContentsEntry contentsEntry : getContents()) {
if (contentsEntry instanceof IRelatableEntry) {
((IRelatableEntry)contentsEntry).determineSettersAndMethodCalls(settings, getContents());
}
}
LOG.debug("relating extracted methods");
for (ClassContentsEntry contentsEntry : getContents()) {
if (contentsEntry instanceof IRelatableEntry) {
((IRelatableEntry)contentsEntry).determineExtractedMethod(settings.getExtractedMethodsSettings());
}
}
/**
* remove any cycles in the related method graph.
*/
MethodEntry.eliminateCycles(getContents());
/**
* check for overloaded extracted methods; if configured to be kept together, attach subsequent
* methods to the first and remove them from consideration for other alignment.
*/
MethodEntry.handleOverloadedMethods(getContents(), settings);
final GenericRearranger classContentsRearranger =
new GenericRearranger(settings.getItemOrderAttributeList(),
contents,
nestingLevel,
settings)
{
public void rearrangeRelatedItems(List<ClassContentsEntry> entries,
List<IRuleInstance> ruleInstanceList)
{
for (IRuleInstance ruleInstance : ruleInstanceList) {
ruleInstance.rearrangeRuleItems(entries, settings);
}
}
};
resultRuleInstances = classContentsRearranger.rearrangeEntries();
}
private void buildMethodCallGraph() {
if (settings.getExtractedMethodsSettings().isMoveExtractedMethods() ||
settings.isKeepGettersSettersTogether())
{
LOG.debug("building method call & getter-setter graph");
for (ClassContentsEntry contentsEntry : getContents()) {
if (contentsEntry instanceof IRelatableEntry) {
((IRelatableEntry)contentsEntry).determineGetterSetterAndExtractedMethodStatus(settings);
}
}
}
}
// End Methods of Interface IFilePopupEntry
public final List<ClassContentsEntry> getContents() {
return contents;
}
public List<IRuleInstance> getResultRuleInstances() {
return resultRuleInstances;
}
}
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiElement;
import com.wrq.rearranger.popup.RearrangerTreeNode;
import com.wrq.rearranger.settings.RearrangerSettings;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.lang.reflect.Modifier;
/** Represents a class initializer. */
public class ClassInitializerEntry
extends ClassContentsEntry
{
private static final Logger LOG = Logger.getInstance("#" + ClassInitializerEntry.class.getName());
public ClassInitializerEntry(final PsiElement start,
final PsiElement end,
final int modifiers,
final String modifierString,
final String name)
{
super(start, end, modifiers, modifierString, name, "");
}
public String getTypeIconName() {
final String name = Modifier.isStatic(getModifiers()) ? "nodes/StaticClassInitializer" : "nodes/ClassInitializer";
return name;
}
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
return new JLabel(Modifier.isStatic(getModifiers()) ? "<static class initializer>" : "<class initializer>");
}
public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) {
LOG.debug("add class initializer to popup tree");
DefaultMutableTreeNode node = new RearrangerTreeNode(this, name);
parent.add(node);
return node;
}
}
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiModifierList;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.settings.RearrangerSettings;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
/** Represents a member field of a class. */
public class FieldEntry
extends ClassContentsEntry
{
/**
* If Keep Getters/Setters With Property is true, and if this field is a property, then a reference to the
* property's getter (primary) method is stored here. That method is removed from the list of entries considered
* for rule matching. This field is responsible for emitting that method.
*/
MethodEntry getterMethod;
public FieldEntry(final PsiElement start,
final PsiElement end,
final int modifiers,
final String modifierString,
final String name,
final String type)
{
super(start, end, modifiers, modifierString, name, type);
getterMethod = null;
}
public String getTypeIconName() {
if (end instanceof PsiField) {
PsiField f = (PsiField)end;
return ((PsiModifierList)f.getModifierList()).hasModifierProperty(PsiModifier.STATIC) ? "nodes/staticField" : "nodes/field";
}
return null;
}
public String[] getAdditionalIconNames() {
if (end instanceof PsiField) {
PsiField f = (PsiField)end;
if (f.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) return new String[]{"nodes/c_public"};
if (f.getModifierList().hasModifierProperty(PsiModifier.PROTECTED)) return new String[]{"nodes/c_protected"};
if (f.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) return new String[]{"nodes/c_private"};
return new String[]{"nodes/c_plocal"};
}
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
StringBuffer name = new StringBuffer(80);
PsiField f = (PsiField)end;
name.append(f.getName());
name.append(": ");
name.append(f.getTypeElement().getText());
if (f.getInitializer() != null && f.getInitializer().getText().indexOf('\n') < 0) {
name.append(" = ");
name.append(f.getInitializer().getText());
}
return new JLabel(name.toString());
}
public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) {
DefaultMutableTreeNode node = super.addToPopupTree(parent, settings);
if (node != null && getterMethod != null) {
getterMethod.addToPopupTree(node, settings);
for (MethodEntry me : getterMethod.correspondingGetterSetters) {
me.addToPopupTree(node, settings);
}
}
return node;
}
public void emit(Emitter emitter) {
super.emit(emitter);
/**
* emit setters/getters if they are kept with the property.
*/
if (getterMethod != null) {
getterMethod.emit(emitter);
}
}
public MethodEntry getGetterMethod() {
return getterMethod;
}
public void setGetterMethod(MethodEntry getterMethod) {
this.getterMethod = getterMethod;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.wrq.rearranger.settings.RearrangerSettings;
import javax.swing.tree.DefaultMutableTreeNode;
/**
* Created by IntelliJ IDEA.
* User: davek
* Date: Feb 18, 2004
* Time: 9:17:56 AM
* To change this template use File | Settings | File Templates.
*/
public interface IPopupTreeRangeEntry {
/**
* Gives individual entries control over their appearance, depending on settings.
*
* @param parent DefaultMutableTreeNode to which this entry will be appended as a child.
* @param settings current Rearranger settings
* @return new DefaultMutableTreeNode
*/
DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings);
}
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.RelatedMethodsSettings;
import java.util.List;
/**
* Defines methods implemented by entries which may be related to others, i.e. getters and setters,
* method entries which call other methods, and overloaded method entries.
*/
public interface IRelatableEntry {
/**
* Determine if the entry is a getter/setter or is excluded from extracted method consideration by an
* overriding rule.
*/
void determineGetterSetterAndExtractedMethodStatus(RearrangerSettings settings);
/**
* Determine corresponding setters for getters and identify related methods.
*
* @param settings current settings, containing extracted/related method options.
* @param contents contents of class, containing potentially related methods.
*/
void determineSettersAndMethodCalls(RearrangerSettings settings,
List<ClassContentsEntry> contents);
/**
* Decide if a method is an extracted method. It is an extracted method if:
* - it is called by at least one other method, and
* - it is private, or passes the "never / 1 / >1" caller test.
*/
void determineExtractedMethod(RelatedMethodsSettings settings);
/** @return true if the method is related to another. In this case, the method is exempt from rule matching. */
boolean isRelatedMethod();
/** @return true if the method is a setter and will be emitted below a corresponding getter. */
boolean isEmittableSetter();
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassInitializer;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
/** Temporary structure to accumulate attributes during parsing, before final RangeEntry is created. */
public class MemberAttributes {
String name = "";
String type = "";
String interfaceName = null;
PsiField field = null;
PsiMethod method = null;
PsiClass childClass = null;
PsiClassInitializer classInitializer = null;
int modifiers = 0;
String modifierString = "";
int nParameters = 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.intellij.psi.PsiElement;
import com.wrq.rearranger.settings.RearrangerSettings;
import javax.swing.*;
/** Corresponds to comments and whitespace that surround Java syntactic items like classes and methods. */
public class MiscellaneousTextEntry
extends ClassContentsEntry
{
public MiscellaneousTextEntry(final PsiElement start,
final PsiElement end,
final boolean fixedHeader,
final boolean fixedTrailer)
{
super(start, end, fixedHeader, fixedTrailer);
}
public String getTypeIconName() {
// do not show headers and trailers in the file structure popup.
return null;
}
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
return null;
}
public String toString() {
String result;
if (isFixedHeader()) {
result = "Header";
}
else {
result = "Trailer";
}
if (alternateValue != null) {
result += "; comments removed";
}
return result;
}
}
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.wrq.rearranger.settings.RearrangerSettings;
import java.util.List;
/**
* Dummy "outer class" which actually corresponds to the PsiFile. Since classes contain
* header text (text from the beginning of the class until the first recognized member), one or more
* members, and trailing text, we can create a dummy "class" which will parse the file. Header text
* will include the package and import statements, and outer classes will be its members.
*/
public class PsiFileEntry
extends ClassEntry
{
public PsiFileEntry(RearrangerSettings settings) {
super(null, null, 0, "", null, 0, settings);
}
/**
* Strip off leading elements which do not belong to the first class, and place them in
* a MiscellaneousText entry.
*
* @param project
* @param psiFile
* @param commentList
* @return
*/
public List<ClassContentsEntry> parseFile(Project project,
PsiElement psiFile,
List commentList)
{
int startingIndex = 0;
for (int i = 0; i < psiFile.getChildren().length; i++) {
PsiElement child = psiFile.getChildren()[i];
if (child instanceof PsiClass) {
do {
startingIndex = i;
i--;
if (i >= 0) {
child = psiFile.getChildren()[i];
}
else {
break;
}
}
while (child instanceof PsiWhiteSpace ||
child instanceof PsiComment ||
child.getText().length() == 0);
break;
}
}
MiscellaneousTextEntry miscellaneousTextEntry = null;
if (startingIndex > 0) {
miscellaneousTextEntry = new MiscellaneousTextEntry(
psiFile.getChildren()[0],
psiFile.getChildren()[startingIndex - 1],
true, false
);
}
parseRemainingClassContents(project, startingIndex, psiFile);
if (miscellaneousTextEntry != null) {
contents.add(0, miscellaneousTextEntry);
}
return contents;
}
}
@@ -0,0 +1,306 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.entry;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiElement;
import com.wrq.rearranger.popup.RearrangerTreeNode;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.CommentUtil;
import javax.swing.tree.DefaultMutableTreeNode;
import java.util.regex.Matcher;
/**
* Corresponds to Java syntactic items ("entries") like classes, fields, and methods. A range entry
* contains start and end Psi elements for each item (which could be identical), as well as modifier
* flags and special flags to mark any miscellaneous text or comments that precede or follow the item.
*/
abstract public class RangeEntry implements IPopupTreeRangeEntry {
// ------------------------------ FIELDS ------------------------------
private static final Logger LOG = Logger.getInstance("#" + RangeEntry.class.getName());
String alternateValue;
final String name;
protected final PsiElement start;
protected final PsiElement end;
private final int modifiers;
private final String modifierString;
private final boolean fixedHeader;
private final boolean fixedTrailer;
private final String type;
private IRuleInstance matchedRule;
private boolean separatorCommentPrecedes;
// --------------------------- CONSTRUCTORS ---------------------------
public RangeEntry(final PsiElement start,
final PsiElement end,
final boolean fixedHeader,
final boolean fixedTrailer)
{
this(start, end, 0, "", "", "", fixedHeader, fixedTrailer);
}
RangeEntry(final PsiElement start,
final PsiElement end,
final int modifiers,
final String modifierString,
final String name,
final String type)
{
this(start, end, modifiers, modifierString, name, type, false, false);
}
private RangeEntry(final PsiElement start,
final PsiElement end,
final int modifiers,
final String modifierString,
final String name,
final String type,
final boolean fixedHeader,
final boolean fixedTrailer)
{
this.start = start;
this.end = end;
this.modifiers = modifiers;
this.modifierString = modifierString;
this.fixedHeader = fixedHeader;
this.fixedTrailer = fixedTrailer;
this.name = name;
this.type = type;
alternateValue = null;
}
// --------------------- GETTER / SETTER METHODS ---------------------
public PsiElement getEnd() {
return end;
}
public IRuleInstance getMatchedRule() {
return matchedRule;
}
public void setMatchedRule(IRuleInstance matchedRule) {
this.matchedRule = matchedRule;
}
public int getModifiers() {
return modifiers;
}
public String getModifierString() {
return modifierString;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public PsiElement getStart() {
return start;
}
public boolean isFixedHeader() {
return fixedHeader;
}
public boolean isFixedTrailer() {
return fixedTrailer;
}
// ------------------------ CANONICAL METHODS ------------------------
public String toString() {
String result = (name == null ? "<unnamed>" : name);
if (start != null && end != null) {
result += "; range from " +
start.toString() +
" [" +
start.getTextRange().getStartOffset() +
"] to " +
end.toString() +
" [" +
end.getTextRange().getEndOffset() +
"]; modifiers=0x" +
Integer.toHexString(modifiers);
}
else {
result += "; no start/end specified";
}
if (fixedHeader) {
result = "Header: " + result;
}
if (fixedTrailer) {
result = "Trailer: " + result;
}
if (alternateValue != null) {
result += "; comments removed";
}
return result;
}
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface IPopupTreeRangeEntry ---------------------
public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) {
DefaultMutableTreeNode myNode = new RearrangerTreeNode(this, name);
parent.add(myNode);
return myNode;
}
// -------------------------- OTHER METHODS --------------------------
public void checkForComment() {
if (CommentUtil.getCommentMatchers().size() == 0) {
return;
}
createAlternateValueString();
/**
* for each separator comment specified by the user, check to see if this comment matches.
*/
for (Matcher matcher : CommentUtil.getCommentMatchers()) {
matcher.reset(alternateValue);
boolean foundMatch = matcher.find();
if (foundMatch) {
LOG.debug("found comment pattern '" +
matcher.pattern().pattern().replaceAll("\n", "#") +
"' in '" +
alternateValue.replaceAll("\n", "#") +
"'");
StringBuffer sb = new StringBuffer(alternateValue.length());
do {
boolean leadingNewlines = start.getTextRange().getStartOffset() > 0;
matcher.appendReplacement(sb,
leadingNewlines ? "\n" : "");
foundMatch = matcher.find();
}
while (foundMatch);
matcher.appendTail(sb);
alternateValue = sb.toString();
LOG.debug("RangeEntry alternateValue=" + alternateValue.replaceAll("\n", "#"));
}
}
}
protected void createAlternateValueString() {
if (alternateValue != null) {
return;
}
final StringBuffer sb = new StringBuffer(
end.getTextRange().getEndOffset() -
start.getTextRange().getStartOffset()
);
PsiElement e = start;
while (e != null && e != end) {
if (e == end.getParent()) {
e = e.getFirstChild();
}
else {
sb.append(e.getText());
e = e.getNextSibling();
}
}
if (e == end) {
sb.append(end.getText());
}
alternateValue = sb.toString();
}
public void emit(Emitter emitter) {
emitAllElements(emitter.getStringBuffer(), emitter.getDocument());
}
protected void emitAllElements(StringBuffer sb, Document document) {
if (alternateValue != null) {
String result = alternateValue;
if (separatorCommentPrecedes) {
// remove all leading blank lines. The only blank lines we want are the ones explicitly appended
// to the preceding separator comment.
LOG.debug("emitAllElements: separator comment precedes " +
name + "; original value=" +
alternateValue.replaceAll("\n", "#"));
result = alternateValue.replaceFirst("\n[ \t\n]*\n", "\n");
LOG.debug("emitAllElements: resulting value=" +
alternateValue.replaceAll("\n", "#"));
}
sb.append(result);
}
else {
PsiElement curr = start;
while (curr != null && curr != end) {
if (curr == end.getParent()) {
curr = curr.getFirstChild();
}
else {
emitElement(curr, sb, document);
curr = curr.getNextSibling();
}
}
if (curr == end) {
emitElement(end, sb, document);
}
}
}
private void emitElement(final PsiElement curr,
final StringBuffer sb,
final Document document)
{
try {
sb.append(
document.getCharsSequence().toString().toCharArray(), // for Irida (builds 3185 etc).
curr.getTextRange().getStartOffset(),
curr.getTextRange().getEndOffset() - curr.getTextRange().getStartOffset()
);
}
catch (ArrayIndexOutOfBoundsException oob) {
LOG.error("internal error attempting to append text to document");
LOG.error("document.getCharsSequence.length=" + document.getCharsSequence().length());
LOG.error("document.getCharsSequence.toString().length=" + document.getCharsSequence().toString().length());
LOG.error("document...toCharArray.length=" + document.getCharsSequence().toString().toCharArray().length);
LOG.error("current PSI element=" + curr.toString());
LOG.error("current PSI element text=" + curr.getText());
LOG.error("current PSI element text range, start offset=" + curr.getTextRange().getStartOffset());
LOG.error("current PSI element text range, end offset=" + curr.getTextRange().getEndOffset());
LOG.error("current PSI element text range, length=" + curr.getTextRange().getLength());
LOG.error(oob);
throw oob;
}
}
public void setSeparatorCommentPrecedes(boolean precedes) {
this.separatorCommentPrecedes = precedes;
LOG.debug("emitAllElements: set separator comment precedes " + name);
}
}
@@ -0,0 +1,352 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.intellij.psi.PsiFile;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.Constraints;
import com.wrq.rearranger.util.IconUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
/** Contains code to pop up a file structure dialog, showing proposed rearrangement. */
public class FileStructurePopup
implements IHasScrollPane
{
final RearrangerSettings settings;
final PopupTreeComponent treeComponent;
public FileStructurePopup(RearrangerSettings settings,
List<IRuleInstance> resultRuleInstances,
final IFilePopupEntry psiFileEntry)
{
this.settings = settings;
treeComponent = new PopupTreeComponent(settings, resultRuleInstances, psiFileEntry);
}
public FileStructurePopup(RearrangerSettings settings,
List<IRuleInstance> resultRuleInstances,
final PsiFile psiFile)
{
this.settings = settings;
IFilePopupEntry psiFileEntry = new IFilePopupEntry() {
public String getTypeIconName() {
return "ppFile";
}
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
return new JLabel(psiFile.getName());
}
};
treeComponent = new PopupTreeComponent(settings, resultRuleInstances, psiFileEntry);
}
/**
* Display a pane showing the rearrangement.
*
* @return true if rearrangement should take place
*/
public boolean displayRearrangement() {
JPanel containerPanel = getContainerPanel();
JOptionPane pane = new JOptionPane(
containerPanel,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION
);
JDialog dialog = pane.createDialog(null, "Rearrangement Results");
dialog.setResizable(true);
dialog.setVisible(true);
Object selectedValue = pane.getValue();
return ((Integer)selectedValue) == JOptionPane.OK_OPTION;
}
// Level 2 methods
private JPanel getContainerPanel() {
final JPanel containerPanel = new JPanel(new GridBagLayout());
final GridBagConstraints scrollPaneConstraints = new GridBagConstraints();
Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
final JScrollPane treeView = getScrollPane();
final JComponent showTypesBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowParameterTypes();
}
void setSetting(boolean value) {
settings.setShowParameterTypes(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowParamTypes");
}
String getToolTipText() {
return "Show parameter types";
}
int getShortcut() {
return KeyEvent.VK_T;
}
}.getIconBox();
final JComponent showNamesBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowParameterNames();
}
void setSetting(boolean value) {
settings.setShowParameterNames(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowParamNames");
}
String getToolTipText() {
return "Show parameter names";
}
int getShortcut() {
return KeyEvent.VK_N;
}
}.getIconBox();
final JComponent showFieldsBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowFields();
}
void setSetting(boolean value) {
settings.setShowFields(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowFields");
}
String getToolTipText() {
return "Show fields";
}
int getShortcut() {
return KeyEvent.VK_F;
}
}.getIconBox();
final JComponent showTypeAfterMethodBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowTypeAfterMethod();
}
void setSetting(boolean value) {
settings.setShowTypeAfterMethod(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowTypeAfterMethod");
}
String getToolTipText() {
return "Show type after method";
}
int getShortcut() {
return KeyEvent.VK_A;
}
}.getIconBox();
final JComponent showRulesBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowRules();
}
void setSetting(boolean value) {
settings.setShowRules(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowRules");
}
String getToolTipText() {
return "Show rules";
}
int getShortcut() {
return KeyEvent.VK_R;
}
}.getIconBox();
final JComponent showMatchedRulesBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowMatchedRules();
}
void setSetting(boolean value) {
settings.setShowMatchedRules(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowMatchedRules");
}
String getToolTipText() {
return "Show matched rules only";
}
int getShortcut() {
return KeyEvent.VK_M;
}
}.getIconBox();
final JComponent showCommentsBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowComments();
}
void setSetting(boolean value) {
settings.setShowComments(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowComments");
}
String getToolTipText() {
return "Show generated separator comments";
}
int getShortcut() {
return KeyEvent.VK_C;
}
}.getIconBox();
((JCheckBox)showRulesBox.getComponent(0)).addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
showMatchedRulesBox.setEnabled(((JCheckBox)showRulesBox.getComponent(0)).isSelected());
}
}
);
showMatchedRulesBox.setEnabled(((JCheckBox)showRulesBox.getComponent(0)).isSelected());
scrollPaneConstraints.insets = new Insets(3, 3, 3, 3);
scrollPaneConstraints.fill = GridBagConstraints.BOTH;
scrollPaneConstraints.gridwidth = GridBagConstraints.REMAINDER;
scrollPaneConstraints.gridheight = GridBagConstraints.REMAINDER;
scrollPaneConstraints.weightx = 1;
scrollPaneConstraints.weighty = 1;
scrollPaneConstraints.gridx = 0;
scrollPaneConstraints.gridy = 1;
constraints.insets = new Insets(5, 5, 5, 5);
containerPanel.add(showTypesBox, constraints.firstCol());
containerPanel.add(showNamesBox, constraints.nextCol());
containerPanel.add(showFieldsBox, constraints.nextCol());
containerPanel.add(showTypeAfterMethodBox, constraints.nextCol());
containerPanel.add(showCommentsBox, constraints.nextCol());
containerPanel.add(showRulesBox, constraints.nextCol());
containerPanel.add(showMatchedRulesBox, constraints.lastCol());
containerPanel.add(treeView, scrollPaneConstraints);
return containerPanel;
}
/**
* build a JTree containing classes, fields and methods, in accordance with settings.
*
* @return
*/
public JScrollPane getScrollPane() {
// Create the nodes.
JTree tree = treeComponent.createTree();
/** expand all nodes. */
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
JScrollPane treeView = new JScrollPane(tree);
treeView.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
treeView.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
Dimension d = treeView.getPreferredSize();
if (d.width < 400) d.width = 400;
if (d.height < 300) d.height = 300;
treeView.setPreferredSize(d);
return treeView;
}
public static void main(String[] args) {
final RearrangerSettings settings = new RearrangerSettings();
IFilePopupEntry pf = new IFilePopupEntry() {
public String getTypeIconName() {
return "nodes/ppFile";
}
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
return new JLabel("FileName.java");
}
};
FileStructurePopup fsp = new FileStructurePopup(settings, new ArrayList<IRuleInstance>(), pf);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
}
final JFrame frame = new JFrame("SwingApplication");
final GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1.0d;
constraints.weighty = 1.0d;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.gridx = 0;
constraints.gridy = 0;
final JPanel object = fsp.getContainerPanel();
frame.getContentPane().setLayout(new GridBagLayout());
frame.getContentPane().add(object, constraints);
//Finish setting up the frame, and show it.
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(final WindowEvent e) {
System.exit(0);
}
}
);
frame.pack();
frame.setVisible(true);
}
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.wrq.rearranger.settings.RearrangerSettings;
import javax.swing.*;
/** Interface implemented by objects which can appear as entries in the file structure popup. */
public interface IFilePopupEntry {
/** @return the name of the icon representing the popup entry's type of Java object (method, class, etc.) */
String getTypeIconName();
/**
* @return the names of the icon representing the protection level of the popup entry, and any other
* icons (overrides/overriding/implements/implmenting).
*/
String[] getAdditionalIconNames();
/** @return a JLabel containing the text of the popup tree entry. */
JLabel getPopupEntryText(RearrangerSettings settings);
}
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import javax.swing.*;
/**
* Interface implemented by popups (LiveRearrangerPopup, FileStructurePopup) to (re)create the scrollpane when
* the underlying tree changes.
*/
public interface IHasScrollPane {
public JScrollPane getScrollPane();
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import java.util.List;
public interface ILiveRearranger {
void setRearrangementOccurred(boolean rearrangementOccurred);
void setResultRuleInstances(List<IRuleInstance> resultRuleInstances);
void liveRearranger();
}
@@ -0,0 +1,229 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.Constraints;
import com.wrq.rearranger.util.IconUtil;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.*;
/**
* Contains enough information to construct a checkbox with the given icon and tooltip
* text, related to a setting.
*/
abstract class IconBox {
static final Color mouseoverColor = new Color(181, 190, 214);
static final Color selectedColor = new Color(132, 146, 189);
static final Color outlineColor = new Color(8, 36, 107);
final JPanel containerPanel;
final GridBagConstraints constraints;
final IHasScrollPane scrollPaneComponent;
protected IconBox(JPanel containerPanel,
GridBagConstraints constraints,
IHasScrollPane scrollPaneComponent)
{
this.containerPanel = containerPanel;
this.constraints = constraints;
this.scrollPaneComponent = scrollPaneComponent;
}
abstract boolean getSetting();
abstract void setSetting(boolean value);
abstract Icon getIcon();
abstract String getToolTipText();
abstract int getShortcut();
class MouseBox
extends JCheckBox
{
boolean mouseOver;
public MouseBox(Icon icon) {
super(icon);
}
}
class MyAction
extends AbstractAction
{
final MouseBox box;
public MyAction(String name, MouseBox box) {
super(name);
this.box = box;
}
public void actionPerformed(ActionEvent e) {
//To change body of implemented methods use File | Settings | File Templates.
box.getActionMap().get("pressed").actionPerformed(e);
box.getActionMap().get("released").actionPerformed(e);
}
}
public JPanel getIconBox() {
final JPanel result = new JPanel(new GridBagLayout());
final Icon icon = getIcon();
final MouseBox box = new MouseBox(icon);
box.setToolTipText(getToolTipText());
box.setSelected(getSetting());
box.setBackground(box.isSelected() ? selectedColor : null);
setOutline(result, box.isSelected());
final MyAction myAction = new MyAction("toggleButton", box);
box.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
setAction(box, (JPanel)box.getParent());
}
}
);
box.setFocusable(false);
box.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(
getShortcut(),
InputEvent.ALT_DOWN_MASK
),
"toggleButton"
);
box.getActionMap().put("toggleButton", myAction);
box.addMouseListener(
new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
box.mouseOver = true;
if (!box.isSelected()) {
box.setBackground(mouseoverColor);
setOutline(result, true);
}
}
public void mouseExited(MouseEvent e) {
box.mouseOver = false;
if (!box.isSelected()) {
box.setBackground(null);
setOutline(result, false);
}
}
}
);
result.add(box);
return result;
}
private void setAction(final MouseBox box, final JPanel result) {
setSetting(box.isSelected());
box.setBackground(box.isSelected() ? selectedColor : box.mouseOver ? mouseoverColor : null);
setOutline(result, box.mouseOver);
int lastIndex = containerPanel.getComponentCount() - 1;
containerPanel.remove(lastIndex);
final JScrollPane scrollPane = scrollPaneComponent.getScrollPane();
containerPanel.add(scrollPane, constraints, lastIndex);
scrollPane.invalidate();
containerPanel.validate();
}
/**
* draws a nearly-black outline border around the button (or removes such border).
*
* @param panel JPanel which contains the button.
* @param outline if true, draw the outline.
*/
private void setOutline(JPanel panel, boolean outline) {
Color borderColor = outline ? outlineColor : ((java.awt.Color)panel.getBackground());
Border b = BorderFactory.createLineBorder(borderColor);
panel.setBorder(b);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
}
final JFrame frame = new JFrame("IconBox test");
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.weightedLastRow();
frame.getContentPane().setLayout(new GridBagLayout());
JPanel panel = new JPanel(new GridBagLayout());
frame.getContentPane().add(panel, constraints.weightedLastCol());
constraints.fill = GridBagConstraints.NONE;
constraints.gridheight = 1;
constraints.weighty = 0;
IHasScrollPane scroll = new IHasScrollPane() {
public JScrollPane getScrollPane() {
return new JScrollPane(new JLabel("scroll pane contents"));
}
};
final RearrangerSettings settings = new RearrangerSettings();
IconBox box = new IconBox(panel, constraints, scroll) {
boolean getSetting() {
return settings.isShowComments();
}
void setSetting(boolean value) {
settings.setShowComments(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowComments");
}
String getToolTipText() {
return "Show comments (Alt+C)";
}
int getShortcut() {
return KeyEvent.VK_C;
}
};
panel.add(box.getIconBox(), constraints);
constraints.weightedLastRow();
constraints.fill = GridBagConstraints.BOTH;
JScrollPane firstPane = new JScrollPane(new JLabel("first scrollpane"));
panel.add(firstPane, constraints);
//Finish setting up the frame, and show it.
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(final WindowEvent e) {
System.exit(0);
}
}
);
frame.pack();
frame.setVisible(true);
}
}
@@ -0,0 +1,321 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiFile;
import com.wrq.rearranger.LiveRearrangerActionHandler;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.Constraints;
import com.wrq.rearranger.util.IconUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.dnd.DnDConstants;
import java.awt.event.KeyEvent;
import java.util.List;
/**
* Contains logic to display a rearrangement dialog, allow user to perform drag&drop rearrangement, and
* rearrange the code accordingly.
*/
public class LiveRearrangerDialog
implements IHasScrollPane,
ILiveRearranger
{
private static final Logger LOG = Logger.getInstance("#" + LiveRearrangerDialog.class.getName());
final RearrangerSettings settings;
PopupTreeComponent treeComponent;
List<IRuleInstance> resultRuleInstances;
final Window outerPanel;
final Document document;
final PsiFile psiFile;
IFilePopupEntry psiFileEntry;
TreeDragSource tds;
TreeDropTarget tdt;
boolean rearrangementOccurred = false;
private JPanel containerPanel;
int cursorOffset;
private PopupTree popupTree;
private void createFilePopupEntry(final PsiFile psiFile) {
psiFileEntry = new IFilePopupEntry() {
public String getTypeIconName() {
return "nodes/ppFile";
}
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
return new JLabel(psiFile.getName());
}
};
}
public LiveRearrangerDialog(RearrangerSettings settings, PsiFile psiFile, Document document,
final Window outerPanel, int cursorOffset)
{
this.settings = settings;
this.document = document;
this.psiFile = psiFile;
createFilePopupEntry(psiFile);
this.outerPanel = outerPanel;
this.cursorOffset = cursorOffset;
}
public void setRearrangementOccurred(boolean rearrangementOccurred) {
this.rearrangementOccurred = rearrangementOccurred;
}
public void setResultRuleInstances(List<IRuleInstance> resultRuleInstances) {
this.resultRuleInstances = resultRuleInstances;
treeComponent = new PopupTreeComponent(settings, resultRuleInstances, psiFileEntry);
}
/** Display a live rearrangement window. */
public void liveRearranger() {
containerPanel = getContainerPanel();
JOptionPane pane = new JOptionPane(
containerPanel,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION
);
JDialog dialog = pane.createDialog(null, "Live Rearranger");
dialog.setResizable(true);
dialog.setVisible(true);
Object selectedValue = pane.getValue();
rearrangementOccurred =
treeComponent.isRearrangementOccurred() &&
(popupTree.isExitedWithEnterKey() ||
(selectedValue != null &&
(((Integer)selectedValue) == JOptionPane.OK_OPTION)));
finish();
LOG.debug("exit liveRearranger");
}
public void finish() {
LOG.debug("entered finish() on thread " + Thread.currentThread().getName());
if (!rearrangementOccurred) {
LOG.debug("no rearrangement occurred, not rearranging document");
return;
}
LOG.debug("rearranging document");
if (document != null) {
final Emitter e = new Emitter(psiFile, resultRuleInstances, document);
e.emitRearrangedDocument();
}
LiveRearrangerActionHandler.setInProgress(false);
LOG.debug("exit finish() on thread " + Thread.currentThread().getName());
}
private JPanel getContainerPanel() {
final JPanel containerPanel = new JPanel(new GridBagLayout());
final GridBagConstraints scrollPaneConstraints = new GridBagConstraints();
scrollPaneConstraints.insets = new Insets(3, 3, 3, 3);
scrollPaneConstraints.fill = GridBagConstraints.BOTH;
scrollPaneConstraints.gridwidth = GridBagConstraints.REMAINDER;
scrollPaneConstraints.gridheight = GridBagConstraints.REMAINDER;
scrollPaneConstraints.weightx = 1;
scrollPaneConstraints.weighty = 1;
scrollPaneConstraints.gridx = 0;
scrollPaneConstraints.gridy = 1;
final JScrollPane treeView = getScrollPane();
final JComponent showTypesBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowParameterTypes();
}
void setSetting(boolean value) {
settings.setShowParameterTypes(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowParamTypes");
}
String getToolTipText() {
return "Show parameter types";
}
int getShortcut() {
return KeyEvent.VK_T;
}
}.getIconBox();
final JComponent showNamesBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowParameterNames();
}
void setSetting(boolean value) {
settings.setShowParameterNames(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowParamNames");
}
String getToolTipText() {
return "Show parameter names";
}
int getShortcut() {
return KeyEvent.VK_N;
}
}.getIconBox();
final JComponent showFieldsBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowFields();
}
void setSetting(boolean value) {
settings.setShowFields(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowFields");
}
String getToolTipText() {
return "Show fields";
}
int getShortcut() {
return KeyEvent.VK_F;
}
}.getIconBox();
final JComponent showTypeAfterMethodBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowTypeAfterMethod();
}
void setSetting(boolean value) {
settings.setShowTypeAfterMethod(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowTypeAfterMethod");
}
String getToolTipText() {
return "Show type after method";
}
int getShortcut() {
return KeyEvent.VK_A;
}
}.getIconBox();
Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.insets = new Insets(5, 5, 5, 5);
containerPanel.add(showTypesBox, constraints.firstCol());
containerPanel.add(showNamesBox, constraints.nextCol());
containerPanel.add(showFieldsBox, constraints.nextCol());
containerPanel.add(showTypeAfterMethodBox, constraints.lastCol());
containerPanel.add(treeView, scrollPaneConstraints);
return containerPanel;
}
/**
* build a JTree containing classes, fields and methods, in accordance with settings.
*
* @return
*/
public JScrollPane getScrollPane() {
// Create the nodes.
popupTree = treeComponent.createLiveRearrangerTree();
// /** only expand node where cursor is located. Inspect all rows; deepest node that covers
// * cursor location is the best to expand. (Parent node like a class contains a method where
// * the cursor is; we want to expand the method, not just the class.
// */
// int expandRow = -1;
// for (int i = 0; i < tree.getRowCount(); i++)
// {
// DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getPathForRow(i).getLastPathComponent();
// if (node.getUserObject() instanceof RangeEntry)
// {
// RangeEntry re = (RangeEntry) node.getUserObject();
// if (re.getStart().getTextRange().getStartOffset() <= cursorOffset &&
// re.getEnd().getTextRange().getEndOffset() >= cursorOffset)
// {
// logger.debug(
// "node " +
// i +
// " contained cursor (offset=" +
// cursorOffset +
// "): " + re
// );
// expandRow = i;
// }
// }
// else
// {
// logger.debug("expand node candidate not RangeEntry; node=" + node);
// }
// }
// if (expandRow >= 0)
// {
// logger.debug("expand row " + expandRow);
// tree.expandRow(expandRow);
// }
/** simply expand all nodes. */
for (int i = 0; i < popupTree.getRowCount(); i++) {
popupTree.expandRow(i);
}
JScrollPane treeView = new JScrollPane(popupTree);
treeView.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
treeView.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
treeView.getVerticalScrollBar().setFocusable(false);
treeView.getHorizontalScrollBar().setFocusable(false);
Dimension d = treeView.getPreferredSize();
if (d.width < 400) d.width = 400;
if (d.height < 300) d.height = 300;
treeView.setPreferredSize(d);
tdt = new TreeDropTarget(popupTree, this);
tds = new TreeDragSource(popupTree, DnDConstants.ACTION_MOVE, tdt);
return treeView;
}
// class RearrangerTest
// extends LightCodeInsightTestCase
// {
// private RearrangerSettings rs;
//
// protected final void setUp() throws Exception
// {
// super.setUp();
// }
//
//
//
}
@@ -0,0 +1,638 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.wrq.rearranger.LiveRearrangerActionHandler;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.IconUtil;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.awt.dnd.DnDConstants;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
/**
* Contains logic to display a rearrangement popup, allow user to perform drag&drop rearrangement, and (when
* a keystroke is seen or a mouse click outside the popup occurs) rearrange the code accordingly.
*/
public class LiveRearrangerPopup
implements IHasScrollPane, ILiveRearranger
{
private static final Logger LOG = Logger.getInstance("#" + LiveRearrangerPopup.class.getName());
final RearrangerSettings settings;
PopupTreeComponent treeComponent;
List<IRuleInstance> resultRuleInstances;
final Window outerPanel;
final Document document;
final PsiFile psiFile;
IFilePopupEntry psiFileEntry;
private WindowFocusListener windowFocusListener;
private WindowAdapter windowAdapter;
private MouseAdapter mouseAdapter;
private KeyEventDispatcher keyEventDispatcher;
private Popup popup;
// private JWindow popup;
TreeDragSource tds;
TreeDropTarget tdt;
boolean rearrangementOccurred = false;
private FocusAdapter focusAdapter;
private JPanel containerPanel;
private final Project project;
private Cursor oldCursor;
private MouseAdapter ma2;
int cursorOffset;
private Component outerPanelFocusOwner;
boolean sawKeyPressed = false;
public LiveRearrangerPopup(RearrangerSettings settings,
final IFilePopupEntry psiFileEntry,
Window outerPanel,
Document document,
Project project)
{
LOG.debug("entered LiveRearrangerPopup constructor");
this.settings = settings;
this.outerPanel = outerPanel;
this.psiFileEntry = psiFileEntry;
this.document = document;
this.psiFile = null;
this.project = project;
}
private void createFilePopupEntry(final PsiFile psiFile) {
psiFileEntry = new IFilePopupEntry() {
public String getTypeIconName() {
return "nodes/ppFile";
}
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
return new JLabel(psiFile.getName());
}
};
}
public LiveRearrangerPopup(RearrangerSettings settings, PsiFile psiFile, Document document, Project project,
final Window outerPanel, int cursorOffset)
{
this.settings = settings;
this.document = document;
this.psiFile = psiFile;
createFilePopupEntry(psiFile);
this.project = project;
this.outerPanel = outerPanel;
this.cursorOffset = cursorOffset;
try {
SwingUtilities.invokeAndWait(
new Runnable() {
public void run() {
// popup = new JWindow();
JPanel tempPanel = new JPanel(new GridBagLayout());
JLabel label = new JLabel("Live Rearranger parsing file...");
Border b = BorderFactory.createRaisedBevelBorder();
tempPanel.setBorder(b);
GridBagConstraints constraints = new GridBagConstraints();
constraints.insets = new Insets(5, 5, 5, 5);
tempPanel.add(label, constraints);
Dimension d = outerPanel.getSize();
Dimension c = tempPanel.getPreferredSize();
int x = (d.width - c.width) / 2;
int y = (d.height - c.height) / 2;
if (x < 0) x = 0;
if (y < 0) y = 0;
popup = PopupFactory.getSharedInstance().getPopup(outerPanel, tempPanel, x, y);
// popup.getContentPane().add(tempPanel);
// popup.setLocation(x, y);
LOG.debug("initial outerPanel size=" + d + ", tempPanel preferred size=" + c);
LOG.debug("Constructing initial Popup at x,y=" + x + "," + y);
// popup.pack();
// popup.setVisible(true);
// popup.requestFocusInWindow();
popup.show();
Cursor cu = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
oldCursor = outerPanel.getCursor();
LOG.debug("setCursor (WAIT)" + cu + " on " + outerPanel);
outerPanel.setCursor(cu);
}
}
);
}
catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
catch (InvocationTargetException ite) {
throw new RuntimeException(ite);
}
}
public void setRearrangementOccurred(boolean rearrangementOccurred) {
this.rearrangementOccurred = rearrangementOccurred;
}
public void setResultRuleInstances(List<IRuleInstance> resultRuleInstances) {
this.resultRuleInstances = resultRuleInstances;
treeComponent = new PopupTreeComponent(settings, resultRuleInstances, psiFileEntry);
}
/** Display a live rearrangement window. */
public void liveRearranger() {
try {
SwingUtilities.invokeAndWait(
new Runnable() {
public void run() {
containerPanel = getContainerPanel();
LOG.debug("containerPanel.isFocusable=" + containerPanel.isFocusable());
Border b = BorderFactory.createRaisedBevelBorder();
containerPanel.setBorder(b);
Dimension d = outerPanel.getSize();
Dimension c = containerPanel.getPreferredSize();
int x = (d.width - c.width) / 2;
int y = (d.height - c.height) / 2;
if (x < 0) x = 0;
if (y < 0) y = 0;
popup.hide(); // destroy initial (interim) popup
popup = PopupFactory.getSharedInstance().getPopup(outerPanel, containerPanel, x, y);
// popup = new JFrame();
// final Container contentPane = popup.getContentPane();
// contentPane.remove(0);
// contentPane.add(containerPanel);
// contentPane.validate();
// popup.setLocation(x, y);
LOG.debug("setCursor (original)" + oldCursor + " on " + outerPanel);
outerPanel.setCursor(oldCursor);
// logger.debug("set default cursor on " + popup);
// popup.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
// popup.repaint();
LOG.debug("outerPanel size=" + d + ", containerPanel preferred size=" + c);
LOG.debug("Constructing Popup at x,y=" + x + "," + y);
LiveRearrangerActionHandler.setInProgress(true);
// popup.addWindowFocusListener(windowFocusListener);
// popup.addWindowListener(windowAdapter);
// popup.addMouseListener(mouseAdapter);
// popup.addFocusListener(focusAdapter);
// contentPane.addFocusListener(focusAdapter);
outerPanel.addWindowFocusListener(
windowFocusListener = getWindowFocusListener("outerPanel")
);
outerPanel.addWindowListener(windowAdapter = getWindowAdapter("outerPanel"));
outerPanel.addMouseListener(mouseAdapter = getMouseAdapter("outerPanel"));
ma2 = getMouseAdapter("focus owner");
outerPanelFocusOwner = outerPanel.getFocusOwner();
if (outerPanelFocusOwner != null) {
outerPanelFocusOwner.addMouseListener(ma2);
}
outerPanel.addFocusListener(focusAdapter = getFocusAdapter("outerPanel"));
containerPanel.addFocusListener(getFocusAdapter("containerPanel"));
keyEventDispatcher = new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
LOG.debug(
"key event dispatcher: outerPanel isFocused=" +
outerPanel.isFocused() +
", rearrangementOccurred=" +
rearrangementOccurred +
" keyEvent=" +
e
);
if (e.getID() == KeyEvent.KEY_RELEASED &&
(rearrangementOccurred || sawKeyPressed))
{
LOG.debug("key event dispatcher: disposing popup, saw keyEvent " + e);
finish();
}
if (e.getID() == KeyEvent.KEY_PRESSED) {
sawKeyPressed = true;
}
return true;
}
};
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
keyEventDispatcher
);
// wasLightWeight = ToolTipManager.sharedInstance().isLightWeightPopupEnabled();
// ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
popup.show();
// popup.setVisible(true);
}
}
);
}
catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
catch (InvocationTargetException ite) {
throw new RuntimeException(ite);
}
LOG.debug("exit liveRearranger");
}
private MouseAdapter getMouseAdapter(final String component) {
return new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
LOG.debug(
component +
": mouse clicked at " +
e.getX() +
"," +
e.getY() +
"; window size/position is " +
outerPanel.getBounds()
);
LOG.debug("close popup and finish");
finish();
super.mouseClicked(e);
}
};
}
private FocusAdapter getFocusAdapter(final String component) {
return new FocusAdapter() {
public void focusGained(FocusEvent e) {
LOG.debug(component + ": focus gained");
}
public void focusLost(FocusEvent e) {
LOG.debug(component + ": focus lost, close popup & finish");
finish();
}
};
}
private WindowAdapter getWindowAdapter(final String component) {
return new WindowAdapter() {
public void windowLostFocus(WindowEvent e) {
LOG.debug(component + ": lost focus");
LOG.debug("close popup and finish");
finish();
}
public void windowClosing(WindowEvent e) {
LOG.debug(component + ": window closing");
}
};
}
private WindowFocusListener getWindowFocusListener(final String component) {
return new WindowFocusListener() {
public void windowGainedFocus(WindowEvent e) {
LOG.debug(component + ": gained window focus");
}
public void windowLostFocus(WindowEvent e) {
LOG.debug(component + ": lost window focus");
LOG.debug("close popup and finish");
finish();
}
};
}
public void finish() {
LOG.debug("entered finish() on thread " + Thread.currentThread().getName());
// popup.setVisible(false);
// popup.dispose();
// popup.removeWindowFocusListener(windowFocusListener);
// popup.removeWindowListener(windowAdapter);
// popup.removeMouseListener(mouseAdapter);
// popup.removeFocusListener(focusAdapter);
// popup.getContentPane().removeFocusListener(focusAdapter);
outerPanel.removeWindowFocusListener(windowFocusListener);
if (outerPanelFocusOwner != null) {
outerPanelFocusOwner.removeMouseListener(ma2);
}
outerPanel.removeWindowListener(windowAdapter);
outerPanel.removeMouseListener(mouseAdapter);
outerPanel.removeFocusListener(focusAdapter);
// containerPanel.removeFocusListener(containerPanel.getFocusListeners()[0]);
popup.hide();
// popup.dispose();
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(keyEventDispatcher);
// ToolTipManager.sharedInstance().setLightWeightPopupEnabled(wasLightWeight);
if (!rearrangementOccurred) {
LOG.debug("no rearrangement occurred, not rearranging document");
LiveRearrangerActionHandler.setInProgress(false);
return;
}
LOG.debug("rearranging document");
final Runnable task = new Runnable() {
public void run() {
if (document != null) {
final Emitter e = new Emitter(psiFile, resultRuleInstances, document);
e.emitRearrangedDocument();
}
}
};
final Application application = ApplicationManager.getApplication();
application.runWriteAction(
new Runnable() {
public void run() {
CommandProcessor.getInstance().executeCommand(project, task, "Rearrange", null);
}
}
);
LiveRearrangerActionHandler.setInProgress(false);
LOG.debug("exit finish() on thread " + Thread.currentThread().getName());
}
private JPanel getContainerPanel() {
final JPanel containerPanel = new JPanel(new GridBagLayout());
Border etched = BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Live Rearranger", TitledBorder.CENTER,
TitledBorder.TOP
);
containerPanel.setBorder(etched);
final GridBagConstraints scrollPaneConstraints = new GridBagConstraints();
scrollPaneConstraints.insets = new Insets(3, 3, 3, 3);
scrollPaneConstraints.fill = GridBagConstraints.BOTH;
scrollPaneConstraints.gridwidth = GridBagConstraints.REMAINDER;
scrollPaneConstraints.gridheight = GridBagConstraints.REMAINDER;
scrollPaneConstraints.weightx = 1;
scrollPaneConstraints.weighty = 1;
scrollPaneConstraints.gridx = 0;
scrollPaneConstraints.gridy = 1;
final JScrollPane treeView = getScrollPane();
final JComponent showTypesBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowParameterTypes();
}
void setSetting(boolean value) {
settings.setShowParameterTypes(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowParamTypes");
}
String getToolTipText() {
return "Show parameter types";
}
int getShortcut() {
return KeyEvent.VK_T;
}
}.getIconBox();
final JComponent showNamesBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowParameterNames();
}
void setSetting(boolean value) {
settings.setShowParameterNames(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowParamNames");
}
String getToolTipText() {
return "Show parameter names";
}
int getShortcut() {
return KeyEvent.VK_N;
}
}.getIconBox();
final JComponent showFieldsBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowFields();
}
void setSetting(boolean value) {
settings.setShowFields(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowFields");
}
String getToolTipText() {
return "Show fields";
}
int getShortcut() {
return KeyEvent.VK_F;
}
}.getIconBox();
final JComponent showTypeAfterMethodBox =
new IconBox(containerPanel, scrollPaneConstraints, this) {
boolean getSetting() {
return settings.isShowTypeAfterMethod();
}
void setSetting(boolean value) {
settings.setShowTypeAfterMethod(value);
}
Icon getIcon() {
return IconUtil.getIcon("ShowTypeAfterMethod");
}
String getToolTipText() {
return "Show type after method";
}
int getShortcut() {
return KeyEvent.VK_A;
}
}.getIconBox();
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.NONE;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.insets = new Insets(5, 5, 5, 5);
containerPanel.add(showTypesBox, constraints);
constraints.gridx++;
containerPanel.add(showNamesBox, constraints);
constraints.gridx++;
containerPanel.add(showFieldsBox, constraints);
constraints.gridx++;
constraints.gridwidth = GridBagConstraints.REMAINDER;
containerPanel.add(showTypeAfterMethodBox, constraints);
containerPanel.add(treeView, scrollPaneConstraints);
return containerPanel;
}
/**
* build a JTree containing classes, fields and methods, in accordance with settings.
*
* @return
*/
public JScrollPane getScrollPane() {
// Create the nodes.
PopupTree tree = treeComponent.createLiveRearrangerTree();
/** only expand node where cursor is located. Inspect all rows; deepest node that covers
* cursor location is the best to expand. (Parent node like a class contains a method where
* the cursor is; we want to expand the method, not just the class.
*/
int expandRow = -1;
for (int i = 0; i < tree.getRowCount(); i++) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getPathForRow(i).getLastPathComponent();
if (node.getUserObject() instanceof RangeEntry) {
RangeEntry re = (RangeEntry)node.getUserObject();
if (re.getStart().getTextRange().getStartOffset() <= cursorOffset &&
re.getEnd().getTextRange().getEndOffset() >= cursorOffset)
{
LOG.debug(
"node " +
i +
" contained cursor (offset=" +
cursorOffset +
"): " + re
);
expandRow = i;
}
}
else {
LOG.debug("expand node candidate not RangeEntry; node=" + node);
}
}
if (expandRow >= 0) {
LOG.debug("expand row " + expandRow);
tree.expandRow(expandRow);
}
JScrollPane treeView = new JScrollPane(tree);
treeView.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
treeView.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
Dimension d = treeView.getPreferredSize();
if (d.width < 400) d.width = 400;
if (d.height < 300) d.height = 300;
treeView.setPreferredSize(d);
tdt = new TreeDropTarget(tree, this);
tds = new TreeDragSource(tree, DnDConstants.ACTION_MOVE, tdt);
return treeView;
}
// class RearrangerTest
// extends LightCodeInsightTestCase
// {
// private RearrangerSettings rs;
//
// protected final void setUp() throws Exception
// {
// super.setUp();
// }
//
//
//
public static void main(String[] args) {
// RearrangerTest t = new RearrangerTest();
// t.testIt();
// void testIt()
// {
final RearrangerSettings settings = new RearrangerSettings();
IFilePopupEntry pf = new IFilePopupEntry() {
public String getTypeIconName() {
return "nodes/ppFile";
}
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
return new JLabel("FileName.java");
}
};
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
}
// logger.setAdditivity(false);
// logger.addAppender(new ConsoleAppender(new PatternLayout("[%7r] %6p - %30.30c - %m \n")));
// logger.setLevel(Level.DEBUG);
// logger.debug("Testing LiveRearrangerPopup");
final JFrame frame = new JFrame("SwingApplication");
// Window window = new Window(frame);
JPanel panel = new JPanel();
panel.setSize(800, 600);
frame.setSize(800, 600);
frame.getRootPane().add(panel);
// window.setSize(800, 600);
// window.getRootPane().add(panel);
final GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1.0d;
constraints.weighty = 1.0d;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.gridx = 0;
constraints.gridy = 0;
LiveRearrangerPopup lrp = new LiveRearrangerPopup(
// getProject(),
settings, pf, frame, null,
null
);
// final JPanel object = lrp.getContainerPanel();
// frame.getContentPane().setLayout(new GridBagLayout());
// frame.getContentPane().add(object, constraints);
//Finish setting up the frame, and show it.
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(final WindowEvent e) {
System.exit(0);
}
}
);
// frame.pack();
frame.setVisible(true);
lrp.liveRearranger();
}
}
//
//}
@@ -0,0 +1,283 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.intellij.openapi.diagnostic.Logger;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.dnd.Autoscroll;
import java.util.LinkedList;
/** Handles vertical autoscrolling of the tree inside the live rearranger popup/dialog. */
public class PopupTree
extends JTree
implements Autoscroll
{
private static final Logger LOG = Logger.getInstance("#" + PopupTree.class.getName());
private static final int margin = 12;
private TreeDropTarget treeDropTarget;
private boolean exitedWithEnterKey;
private final PopupTreeComponent owner;
public PopupTree(TreeNode root, PopupTreeComponent owner) {
super(root);
this.owner = owner;
}
public void setTreeDropTarget(TreeDropTarget dropTarget) {
treeDropTarget = dropTarget;
}
public boolean isExitedWithEnterKey() {
return exitedWithEnterKey;
}
public void setExitedWithEnterKey(boolean exitedWithEnterKey) {
this.exitedWithEnterKey = exitedWithEnterKey;
}
// scroll because mouse cursor is in the scroll zone.
public void autoscroll(Point p) {
// determine row. Set y value to that of current row left edge; this allows scrolling to occur
int realrow = getRowForLocation(p.x, p.y);
if (treeDropTarget != null) {
treeDropTarget.clearInsertionPoint();
// Set y value to that of current row left edge; this allows scrolling to occur even when cursor is
// to the right or left of the smallest rectangle enclosing the row.
int row = treeDropTarget.getSrcRow();
Rectangle r = getRowBounds(row);
if (realrow < 0) {
LOG.debug("autscroll: realrow < 0 for [" + p.x + "," + p.y + "], trying x=" + r.x);
p.x = r.x;
realrow = getRowForLocation(p.x, p.y);
}
}
if (realrow < 0) {
LOG.debug("autoscroll point=[" + p.x + "," + p.y + "] realrow=" + realrow);
return;
}
Rectangle outer = getBounds();
// now determine if the row is at the top or bottom of the screen.
// Make the previous or next row visible accordingly.
int newRow =
p.y + outer.y <= margin
? realrow < 1 ? 0 : realrow - 1
: realrow < getRowCount() - 1
? realrow + 1
: realrow;
// logger.setLevel(Level.DEBUG); -- following code doesn't work for horizontal scrolling; something interferes
// int newCol = p.x;
// if (this.getParent() instanceof JViewport)
// {
// JViewport parent = (JViewport) getParent();
// logger.debug(
// "autoscroll horizontal TEST: p.x=" +
// p.x +
// ", bounds.x=" +
// outer.x +
// ", viewport x=" +
// parent.getBounds().x +
// ", width=" + parent.getBounds().width);
// if (p.x + outer.x <= margin)
// {
// newCol = p.x - margin;
// logger.debug(
// "autoscroll horizontal LEFT: new x=" + newCol
// );
// logger.debug("this=" + this.toString());
// logger.debug("this.parent=" + this.getParent().toString());
// Rectangle r = parent.getViewRect();
// r.x -= margin;
// parent.scrollRectToVisible(r);
// }
// else
// {
// if (p.x + outer.x + margin >= parent.getBounds().x + parent.getBounds().width)
// {
// newCol = p.x + margin;
// logger.debug(
// "autoscroll horizontal RIGHT: new x=" + newCol
// );
//// logger.debug("this=" + this.toString());
//// logger.debug("this.parent=" + parent.toString());
// Rectangle r = parent.getViewRect();
// r.x += margin;
// parent.scrollRectToVisible(r);
// }
// }
// }
LOG.debug("autoscroll point=[" + p.x + "," + p.y + "] realrow=" + realrow + ", newRow=" + newRow);
scrollRowToVisible(newRow);
if (treeDropTarget != null) {
treeDropTarget.computeInsertionPoint();
treeDropTarget.drawInsertionPoint();
}
}
/**
* Calculate insets for the JTree, not the viewport the tree is in.
* this makes it a bit messy.
*
* @return
*/
public Insets getAutoscrollInsets() {
Rectangle outer = getBounds();
Rectangle inner = getParent().getBounds();
return new Insets(
inner.y - outer.y + margin,
inner.x - outer.x + margin,
outer.height - inner.height - inner.y + outer.y + margin,
outer.width - inner.width - inner.x + outer.x + margin
);
}
// Use this method to see the boundaries of the autoscroll active region.
// public void paintComponent(Graphics g)
// {
// super.paintComponent(g);
// Rectangle outer = getBounds();
// Rectangle inner = getParent().getBounds();
// g.setColor(Color.RED);
// g.drawRect(-outer.x + margin, -outer.y + margin,
// inner.width - 2*margin, inner.height - 2*margin);
// }
/**
* Move the tree's selection to the destination row indicated. The selection may contain multiple
* discontiguous rows, but all rows must have the same parent node.
*
* @param dstIndex child index of common parent before which selection is to be inserted. If null, insert at end of parent.
*/
public void moveSelection(int dstIndex, boolean before) {
/**
* First, remove all mutable tree nodes from the tree's model and the rule instance. Place them in a list.
* If any are removed before the destination row, decrement the dstIndex so that the insertion still
* happens in the correct place.
*/
TreePath[] paths = getSelectionPaths();
LinkedList<DefaultMutableTreeNode> nodeList = new LinkedList<DefaultMutableTreeNode>();
LinkedList<RangeEntry> ruleList = new LinkedList<RangeEntry>();
if (paths == null || paths.length == 0) {
return; // nothing selected
}
owner.setRearrangementOccurred(true);
final DefaultMutableTreeNode peerNode = (DefaultMutableTreeNode)paths[0].getLastPathComponent();
RangeEntry entry = (RangeEntry)peerNode.getUserObject();
DefaultMutableTreeNode peerParent = (DefaultMutableTreeNode)peerNode.getParent();
DefaultMutableTreeNode dstNode = (DefaultMutableTreeNode)peerParent.getChildAt(dstIndex);
if (!before && dstIndex < peerParent.getChildCount()) {
dstIndex++;
}
IRuleInstance ruleInstance = entry.getMatchedRule();
DefaultTreeModel model = (DefaultTreeModel)getModel();
for (TreePath path : paths) {
DefaultMutableTreeNode srcNode = (DefaultMutableTreeNode)path.getLastPathComponent();
DefaultMutableTreeNode srcParent = (DefaultMutableTreeNode)srcNode.getParent();
int srcRow = srcParent.getIndex(srcNode);
if (srcRow < dstIndex) {
dstIndex--;
}
nodeList.add(srcNode);
model.removeNodeFromParent(srcNode);
RangeEntry match = (RangeEntry)srcNode.getUserObject();
ruleInstance.getMatches().remove(match);
ruleList.add(match);
}
/**
* now insert all the nodes in the list at the appropriate spots in the model and rule instance.
*/
clearSelection();
TreePath visiblePath = null;
/**
* calculate the offset between the destination row in the model and its location in the ruleInstance's
* list of matching items. This is non-zero when fields exist but are not shown in the tree.
*/
int dstOffset = (ruleInstance.getMatches().indexOf(dstNode.getUserObject())) - peerParent.getIndex(dstNode);
while (!nodeList.isEmpty()) {
DefaultMutableTreeNode srcNode = nodeList.removeFirst();
model.insertNodeInto(srcNode, peerParent, dstIndex);
final TreePath treePath = new TreePath(srcNode.getPath());
addSelectionPath(treePath);
if (before) {
if (visiblePath == null) visiblePath = treePath;
}
else {
visiblePath = treePath;
}
final RangeEntry match = ruleList.removeFirst();
ruleInstance.getMatches().add(dstIndex + dstOffset, match);
dstIndex++;
}
if (visiblePath != null) {
scrollPathToVisible(visiblePath);
}
}
/**
* returns true if src and dst have common parent. Since src has been created from serialized data,
* the actual parents are different objects. So compare by name up to the root. Ignore any plain
* DefaultMutableTreeNodes in the path (these correspond to rules) -- just compare names of
* RearrangerTreeNodes.
*
* @param src RearrangerTreeNode reconstituted from serialized data
* @param dst RearrangerTreeNode next to which src is to be dropped
* @return -1 if src and dst do not have common parent; >= 0 to indicate position of src in children list
*/
int haveCommonAncestors(DefaultMutableTreeNode src, DefaultMutableTreeNode dst) {
if (src == null || dst == null) {
return -1;
}
DefaultMutableTreeNode p = (DefaultMutableTreeNode)src.getParent();
int result = p.getIndex(src);
src = (DefaultMutableTreeNode)src.getParent();
dst = (DefaultMutableTreeNode)dst.getParent();
while (src != null && dst != null) {
if (src instanceof RearrangerTreeNode) {
if (dst instanceof RearrangerTreeNode) {
RearrangerTreeNode s = (RearrangerTreeNode)src;
RearrangerTreeNode d = (RearrangerTreeNode)dst;
if (!s.name.equals(d.name)) {
return -1;
}
}
else {
return -1;
}
}
else if (dst instanceof RearrangerTreeNode) {
return -1;
}
src = (DefaultMutableTreeNode)src.getParent();
dst = (DefaultMutableTreeNode)dst.getParent();
}
return src == null && dst == null ? result : -1;
}
}
@@ -0,0 +1,361 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.intellij.openapi.diagnostic.Logger;
import com.wrq.rearranger.Rearranger;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.Constraints;
import com.wrq.rearranger.util.IconUtil;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.net.URL;
import java.util.List;
/** Builds a JTree that can be used in a file structure popup or live rearranger popup. */
public class PopupTreeComponent {
private static final Logger LOG = Logger.getInstance("#" + PopupTreeComponent.class.getName());
private final IFilePopupEntry psiFileEntry;
private final List<IRuleInstance> resultRuleInstances;
private final RearrangerSettings settings;
private boolean rearrangementOccurred;
public PopupTreeComponent(RearrangerSettings settings,
List<IRuleInstance> resultRuleInstances,
final IFilePopupEntry psiFileEntry)
{
this.settings = settings;
this.resultRuleInstances = resultRuleInstances;
this.psiFileEntry = psiFileEntry;
}
public boolean isRearrangementOccurred() {
return rearrangementOccurred;
}
public void setRearrangementOccurred(boolean rearrangementOccurred) {
this.rearrangementOccurred = rearrangementOccurred;
}
public JTree createTree() {
DefaultMutableTreeNode top = createAllNodes();
final JTree tree = new JTree(top);
tree.putClientProperty("JTree.lineStyle", "Angled");
tree.setRootVisible(true);
tree.setShowsRootHandles(true);
tree.setRowHeight(0);
tree.setCellRenderer(new JavaObjectRenderer());
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setEditable(false);
return tree;
}
public PopupTree createLiveRearrangerTree() {
DefaultMutableTreeNode top = createAllNodes();
// discard top nodes if only one child
// while (top.getChildCount() == 1) { // TODO - enable
// // remove that child, make its child(ren) top's child(ren).
// DefaultMutableTreeNode child = (DefaultMutableTreeNode) top.getChildAt(0);
// child.removeFromParent();
// for (int i = 0; i < child.getChildCount(); i++) {
// DefaultMutableTreeNode grandchild = (DefaultMutableTreeNode) child.getChildAt(i);
// top.add(grandchild);
// }
// }
final PopupTree tree = new PopupTree(top, this);
tree.putClientProperty("JTree.lineStyle", "Angled");
tree.setRootVisible(true);
tree.setShowsRootHandles(true);
tree.setRowHeight(0);
tree.setCellRenderer(new JavaObjectRenderer());
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
tree.setEditable(false);
tree.getSelectionModel().addTreeSelectionListener(
new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
LOG.debug("selection changed as follows (" + e.getPaths().length + " path(s)):");
TreePath lastPathAdded = null;
int i = 0;
for (TreePath path : e.getPaths()) {
if (e.isAddedPath(path)) {
lastPathAdded = path;
}
LOG.debug(
"path " +
i +
(e.isAddedPath(path) ? " added:" : " removed:") +
path
);
i++;
}
if (lastPathAdded == null) {
// nothing added, so all selected paths still have same parent.
return;
}
/**
* ensure that all selection rows have the same parent. If not, take the last added
* path, and remove any rows with a different parent. (So simply start with the last
* added path and remove any rows with a different parent.)
*/
DefaultMutableTreeNode lastNodeAdded = null;
lastNodeAdded = (DefaultMutableTreeNode)lastPathAdded.getLastPathComponent();
boolean haveSameParent = true;
for (TreePath path : tree.getSelectionPaths()) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
if (lastNodeAdded == null) {
lastNodeAdded = node;
}
if (node != lastNodeAdded) {
if (tree.haveCommonAncestors(lastNodeAdded, node) < 0) {
// parents not identical, so remove node from selection.
haveSameParent = false;
break;
}
}
}
if (!haveSameParent) {
// to avoid reentry into this listener, temporarily remove it
tree.getSelectionModel().removeTreeSelectionListener(this);
tree.clearSelection();
tree.addSelectionPath(lastPathAdded);
tree.getSelectionModel().addTreeSelectionListener(this);
}
}
}
);
AbstractAction moveUpAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
LOG.debug("moveUpAction, " + tree.getSelectionPaths().length + " paths in selection");
if (tree.getSelectionPaths().length == 0) {
return;
}
/**
* find first selection row.
*/
int selectionRow = Integer.MAX_VALUE;
for (TreePath path : tree.getSelectionPaths()) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
int nodeIndex = node.getParent().getIndex(node);
if (selectionRow > nodeIndex) {
selectionRow = nodeIndex;
}
}
if (selectionRow > 0) {
selectionRow--;
}
tree.moveSelection(selectionRow, true);
}
};
AbstractAction moveDownAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
LOG.debug("moveDownAction, " + tree.getSelectionPaths().length + " paths in selection");
if (tree.getSelectionPaths().length == 0) {
return;
}
/**
* find last selection row.
*/
int selectionRow = -1;
for (TreePath path : tree.getSelectionPaths()) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
final DefaultMutableTreeNode parent = ((DefaultMutableTreeNode)node.getParent());
int nodeIndex = parent.getIndex(node);
if (selectionRow < nodeIndex) {
selectionRow = nodeIndex;
}
}
selectionRow++;
tree.moveSelection(selectionRow, false);
}
};
AbstractAction enterKeyAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
LOG.debug("exit with enter key");
tree.setExitedWithEnterKey(true);
for (Container p = tree.getParent(); p != null; p = p.getParent()) {
if (p instanceof JDialog) {
p.setVisible(false);
}
}
}
};
tree.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
"enterKeyAction"
);
tree.getActionMap().put("enterKeyAction", enterKeyAction);
tree.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(
KeyEvent.VK_UP,
InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK
),
"moveUpAction"
);
tree.getActionMap().put("moveUpAction", moveUpAction);
tree.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(
KeyEvent.VK_DOWN,
InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK
),
"moveDownAction"
);
tree.getActionMap().put("moveDownAction", moveDownAction);
tree.setSelectionPath(tree.getPathForRow(0));
return tree;
}
public DefaultMutableTreeNode createAllNodes() {
DefaultMutableTreeNode top = new RearrangerTreeNode(psiFileEntry, "root");
createNodes(top);
return top;
}
private void createNodes(DefaultMutableTreeNode top) {
for (IRuleInstance ruleInstance : resultRuleInstances) {
ruleInstance.addRuleInstanceToPopupTree(top, settings);
}
}
class JavaObjectRenderer
extends DefaultTreeCellRenderer
{
Icon findIcon(String iconName) {
if (iconName == null) {
return null;
}
URL iconURL = this.getClass().getClassLoader().getResource(iconName + ".png");
if (iconURL == null) {
return IconUtil.getIcon(iconName);
}
else {
return new ImageIcon(iconURL, Rearranger.COMPONENT_NAME);
}
}
public Component getTreeCellRendererComponent(final JTree tree,
final Object value,
final boolean sel,
final boolean expanded,
final boolean leaf,
final int row,
final boolean hasFocus)
{
Object userObject = null;
if (value instanceof DefaultMutableTreeNode) {
userObject = ((DefaultMutableTreeNode)value).getUserObject();
}
// obtain a component that will render the appropriate item.
if (userObject instanceof IFilePopupEntry) {
IFilePopupEntry entry = (IFilePopupEntry)userObject;
final String iconTypeName = entry.getTypeIconName();
final String[] iconNames = entry.getAdditionalIconNames();
final JLabel textLabel = entry.getPopupEntryText(settings);
JPanel panel = new JPanel(new GridBagLayout()) {
public void paint(Graphics g) {
// System.out.println("paint " + textLabel.getText() + ", sel=" + sel +
// ", hasFocus=" + hasFocus +
// ", selected=" + selected +
// ", bg=" + getBackground().toString().replaceFirst(".*\\[", "[") +
// ", bg sel=" + getBackgroundSelectionColor().toString().replaceFirst(".*\\[", "[") +
// ", border=" + getBorderSelectionColor().toString().replaceFirst(".*\\[", "[")
// );
if (sel && !hasFocus) {
Color bgColor = getBackground();
setBackground(Color.WHITE);
super.paint(g);
setBackground(bgColor);
Color bsColor = getBorderSelectionColor();
if (bsColor != null) {
g.setColor(bsColor);
if (getComponentOrientation().isLeftToRight()) {
g.drawRect(
0, 0, getWidth() - 1,
getHeight() - 1
);
}
else {
g.drawRect(
0, 0, getWidth() - 1,
getHeight() - 1
);
}
}
}
else {
super.paint(g);
}
}
};
Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.weightedLastRow();
Icon typeIcon = findIcon(iconTypeName == null ? "fileTypes/unknown" : iconTypeName);
panel.setBackground(Color.WHITE);
if (sel) {
// Color fg = textLabel.getForeground();
// Color bg = textLabel.getBackground();
// textLabel.setForeground(bg);
// textLabel.setBackground(new Color(181, 190, 214));
// Color fg = panel.getForeground();
// Color bg = panel.getBackground();
// panel.setForeground(bg);
panel.setBackground(new Color(181, 190, 214));
}
else {
textLabel.setBackground(Color.WHITE);
}
if (typeIcon != null) {
JLabel typeLabel = new JLabel(typeIcon);
panel.add(typeLabel, constraints.nextCol());
}
if (iconNames != null) {
for (String iconName : iconNames) {
Icon addlIcon = findIcon(iconName);
JLabel plLabel = new JLabel(addlIcon);
panel.add(plLabel, constraints.nextCol());
}
}
constraints.insets = new Insets(0, 3, 0, 0);
panel.add(textLabel, constraints.lastCol());
panel.repaint();
return panel;
}
LOG.debug("getTreeCellRendererComponent: userObject not IFilePopupEntry;" + userObject);
return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
}
}
}
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import javax.swing.tree.DefaultMutableTreeNode;
public class RearrangerTreeNode
extends DefaultMutableTreeNode
{
String name;
public RearrangerTreeNode(Object userObject, String name) {
super(userObject);
this.name = name;
}
}
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import javax.swing.tree.TreePath;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
public class TransferableTreeNode
implements Transferable
{
public static DataFlavor treePathFlavor = new DataFlavor(TreePath.class, "Tree Path Flavor");
DataFlavor[] flavors = {treePathFlavor};
TreePath[] paths;
public TransferableTreeNode(TreePath[] paths) {
this.paths = paths;
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return (flavor.getRepresentationClass() == TreePath.class);
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (isDataFlavorSupported(flavor)) {
return paths;
}
else {
throw new UnsupportedFlavorException(flavor);
}
}
}
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.intellij.openapi.diagnostic.Logger;
import javax.swing.*;
import java.awt.*;
import java.awt.dnd.*;
/** Contains logic to start a drag from the popup file structure tree. */
public class TreeDragSource
implements DragSourceListener,
DragGestureListener
{
private static final Logger LOG = Logger.getInstance("#" + TreeDragSource.class.getName());
DragSource source;
DragGestureRecognizer recognizer;
TransferableTreeNode transferable;
JTree sourceTree;
TreeDropTarget tdt;
public TreeDragSource(JTree sourceTree, int actions, TreeDropTarget tdt) {
LOG.debug("construct TreeDragSource, actions=" + actions);
this.sourceTree = sourceTree;
this.tdt = tdt;
source = DragSource.getDefaultDragSource();
recognizer = source.createDefaultDragGestureRecognizer(
sourceTree, actions, this);
}
public void dragEnter(DragSourceDragEvent dsde) {
LOG.debug("src dragEnter, calling dragOver");
dragOver(dsde);
}
public void dragOver(DragSourceDragEvent dsde) {
// logger.debug("src dragOver; drop action=" + dsde.getDropAction() +
// ", target actions=" + dsde.getTargetActions());
// dsde.getDragSourceContext().setCursor(dsde.getDropAction() > 0
// ? DragSource.DefaultMoveDrop
// : DragSource.DefaultMoveNoDrop);
}
public void dropActionChanged(DragSourceDragEvent dsde) {
LOG.debug("src dropActionChanged: action=" + dsde.getDropAction());
}
public void dragDropEnd(DragSourceDropEvent dsde) {
LOG.debug("src dragDropEnd, success=" + dsde.getDropSuccess());
}
public void dragExit(DragSourceEvent dse) {
// logger.debug("src dragExit");
}
public void dragGestureRecognized(DragGestureEvent dge) {
LOG.debug("src dragGestureRecognized, action=" + dge.getDragAction() +
", n paths in selection=" + sourceTree.getSelectionPaths().length);
final Point point = dge.getDragOrigin();
// TreePath path = sourceTree.getSelectionPath();
// if (path == null ||
// path.getPathCount() <= 1)
// {
// // can't move the root node or an empty selection
// System.out.println("can't drag root node or empty selection");
// return;
// }
// Make a version of the node that we can use for DnD.
tdt.setSrcRow(sourceTree.getClosestRowForLocation(point.x, point.y));
transferable = new TransferableTreeNode(sourceTree.getSelectionPaths());
dge.startDrag(null, transferable, this);
}
}
@@ -0,0 +1,273 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.popup;
import com.intellij.openapi.diagnostic.Logger;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.io.IOException;
/** Handles drop actions associated with manual rearrangement. */
public class TreeDropTarget
implements DropTargetListener
{
private static final Logger LOG = Logger.getInstance("#" + TreeDropTarget.class.getName());
private static final Color xorBackgroundColor = new Color(255 - 8, 255 - 36, 255 - 107);
DropTarget target;
PopupTree targetTree;
ILiveRearranger lrp;
/** Cached information about the location of the last insertion row to be drawn. */
private transient Rectangle lastRowRect;
/** cached value of last row to be drawn. */
private int lastRow;
/**
* Cached information about whether insertion was possible at the last
* insertion point.
*/
private transient boolean canInsert;
/** true if rectangle has been drawn. */
private boolean rectangleDrawn;
/** row being dragged. */
private int srcRow;
public TreeDropTarget(PopupTree tree,
ILiveRearranger lrp)
{
this.lrp = lrp;
this.targetTree = tree;
target = new DropTarget(targetTree, DnDConstants.ACTION_MOVE, this);
this.lastRowRect = new Rectangle();
this.canInsert = false;
rectangleDrawn = false;
srcRow = -1;
tree.setTreeDropTarget(this);
}
public void dragEnter(DropTargetDragEvent dtde) {
// logger.debug("tgt dragEnter calling dragOver logic");
dragOver(dtde);
}
public int getSrcRow() {
return srcRow;
}
public void setSrcRow(int srcRow) {
this.srcRow = srcRow;
}
public void dragOver(DropTargetDragEvent dtde) {
// logger.debug("target dragOver: src drop actions=" + dtde.getSourceActions() +
// ", src drop action=" + dtde.getDropAction());
clearInsertionPoint();
Point pt = dtde.getLocation();
lastRow = targetTree.getClosestRowForLocation(pt.x, pt.y);
computeInsertionPoint(lastRow);
TreePath path = targetTree.getClosestPathForLocation(pt.x, pt.y);
final DefaultMutableTreeNode tgtNode;
tgtNode = (DefaultMutableTreeNode)path.getLastPathComponent();
// logger.debug("tgt dragOver, closest node=" + tgtNode);
// compare selected node(s) to see if it has same parent as tgtNode.
final DefaultMutableTreeNode srcNode;
final TreePath srcPath = targetTree.getSelectionPath();
if (srcPath != null) {
srcNode = (DefaultMutableTreeNode)srcPath.getLastPathComponent();
// logger.debug("tgt dragOver, selected node=" + srcNode);
if (srcNode.getParent() == tgtNode.getParent() &&
srcNode != tgtNode)
{
// logger.debug("tgt dragOver: accept drag");
canInsert = true;
drawInsertionPoint();
dtde.acceptDrag(DnDConstants.ACTION_MOVE);
return;
}
}
// logger.debug("tgt dragOver: reject drag");
canInsert = false;
dtde.rejectDrag();
}
public void dropActionChanged(DropTargetDragEvent dtde) {
// logger.debug("tgt:dropActionChanged, action=" + dtde.getDropAction());
}
public void drop(DropTargetDropEvent dtde) {
clearInsertionPoint();
canInsert = false;
// figure out where the drop occurred.
Point pt = dtde.getLocation();
TreePath path = targetTree.getClosestPathForLocation(pt.x, pt.y);
Transferable t = dtde.getTransferable();
DataFlavor[] flavors = t.getTransferDataFlavors();
for (DataFlavor flavor : flavors) {
if (t.isDataFlavorSupported(flavor)) {
DefaultMutableTreeNode dstNode = (DefaultMutableTreeNode)path.getLastPathComponent();
Transferable tx = dtde.getTransferable();
TreePath[] tr = null;
try {
Object o = tx.getTransferData(TransferableTreeNode.treePathFlavor);
tr = (TreePath[])o;
}
catch (UnsupportedFlavorException e) {
e.printStackTrace();
dtde.rejectDrop();
return;
}
catch (IOException e) {
e.printStackTrace();
dtde.rejectDrop();
return;
}
if (tr == null) {
dtde.rejectDrop();
return;
}
final DefaultMutableTreeNode srcNode = (DefaultMutableTreeNode)tr[0].getLastPathComponent();
int srcIndex = targetTree.haveCommonAncestors(srcNode, dstNode);
if (srcIndex < 0) {
LOG.debug(
"reject drop onto " +
dstNode +
"; parent of " +
srcNode + " is different"
);
dtde.rejectDrop();
return;
}
else {
DefaultMutableTreeNode parent = (DefaultMutableTreeNode)dstNode.getParent();
DefaultMutableTreeNode srcInCurrentTree = (DefaultMutableTreeNode)parent.getChildAt(srcIndex);
int dstRow = parent.getIndex(dstNode);
boolean before = true;
if (srcIndex < dstRow) {
LOG.debug(
"drop: move " +
srcIndex +
":" +
srcInCurrentTree +
" after " + dstRow + ":" + dstNode
);
before = false;
}
else if (srcIndex == dstRow) {
LOG.debug("reject drop: item onto itself");
dtde.rejectDrop();
return;
}
else {
LOG.debug(
"drop: move " +
srcIndex +
":" +
srcInCurrentTree +
" before " + dstRow + ":" + dstNode
);
}
targetTree.moveSelection(dstRow, before);
lrp.setRearrangementOccurred(true);
dtde.acceptDrop(dtde.getDropAction());
dtde.dropComplete(true);
return;
}
}
}
dtde.rejectDrop();
}
public void dragExit(DropTargetEvent dte) {
LOG.debug("tgt dragExit");
clearInsertionPoint();
canInsert = false;
}
public void clearInsertionPoint() {
if (rectangleDrawn) {
// Erase the old insertion point by drawing over it.
drawInsertionPoint();
}
}
/**
* Draw or erase the current insertion point indicator. This draws in XOR
* mode, so drawing the indicator once will display it and drawing it again
* in the same location will erase it.
*/
public void drawInsertionPoint() {
if (canInsert) {
Graphics g = this.targetTree.getGraphics();
g.setXORMode(xorBackgroundColor);
g.drawRect(
this.lastRowRect.x, this.lastRowRect.y,
this.lastRowRect.width, this.lastRowRect.height
);
rectangleDrawn = !rectangleDrawn;
}
}
public void computeInsertionPoint() {
computeInsertionPoint(lastRow);
}
/**
* Given a particular point over the associated tree component, determine
* the corresponding insertion point in the tree for dropped data. The tree
* path that the insertion will be relative to can be found using the
* <code>JTree</code> method <code>getClosestPathForLocation</code>. The
* insertion itself will either be before, after, or in the node at the end
* of the path. This method also calculates the rectangle which can be used
* to draw the appropriate indicator for the insertion point.
*
* @param row the row number of the tree corresponding to the drop target.
*/
public void computeInsertionPoint(int row) {
JTree tree = targetTree;
Rectangle rowBounds = tree.getRowBounds(row);
if (row < srcRow) {
// Insertion point is immediately before the node.
this.lastRowRect.setBounds(rowBounds.x, rowBounds.y, rowBounds.width, 0);
}
else if (row > srcRow) {
// Insertion point is immediately after the node.
this.lastRowRect.setBounds(
rowBounds.x, rowBounds.y + rowBounds.height - 1,
rowBounds.width, 0
);
}
else {
// Insertion point is on the node - dropped data will be appended to the
// nodes child list. Draw nothing in this case.
this.lastRowRect.setBounds(rowBounds.x, rowBounds.y, 0, 0);
}
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.rearrangement;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiFile;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import java.util.List;
/** Emits a new document from the rearranged entries. */
public final class Emitter {
private final PsiFile psiFile;
private final List<IRuleInstance> resultRuleInstances;
private final Document document;
private StringBuffer stringBuffer;
public Emitter(final PsiFile psiFile, final List<IRuleInstance> resultRuleInstances, final Document document) {
this.psiFile = psiFile;
this.resultRuleInstances = resultRuleInstances;
this.document = document;
stringBuffer = new StringBuffer(psiFile.getText().length() + 100); // room for inserted blank lines
}
public Document getDocument() {
return document;
}
public StringBuffer getStringBuffer() {
return stringBuffer;
}
public void emitRearrangedDocument() {
emitRuleInstances(resultRuleInstances);
document.replaceString(
psiFile.getTextRange().getStartOffset(),
psiFile.getTextRange().getEndOffset(),
stringBuffer.toString()
);
}
public void emitRuleInstances(List<IRuleInstance> resultRuleInstances) {
if (resultRuleInstances == null) {
return;
}
for (IRuleInstance ruleInstance : resultRuleInstances) {
ruleInstance.emit(this);
}
}
}
@@ -0,0 +1,202 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.rearrangement;
import com.intellij.openapi.diagnostic.Logger;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.entry.ClassEntry;
import com.wrq.rearranger.entry.IRelatableEntry;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.ruleinstance.CommentRuleInstance;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.*;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/** Template for generic rearrangement of items in a class or in a Java file. */
public abstract class GenericRearranger {
private static final Logger LOG = Logger.getInstance("#" + GenericRearranger.class.getName());
private final List<AttributeGroup> rules;
private final List<ClassContentsEntry> entries;
private final List<IRuleInstance> resultRuleInstances;
private final int nestingLevel;
private final RearrangerSettings settings;
@SuppressWarnings({"AssignmentToCollectionOrArrayFieldFromParameter"})
protected GenericRearranger(final List<AttributeGroup> rules,
final List<ClassContentsEntry> outerClasses,
final int nestingLevel,
final RearrangerSettings settings)
{
this.rules = rules;
entries = outerClasses;
this.nestingLevel = nestingLevel;
this.settings = settings;
resultRuleInstances = new ArrayList<IRuleInstance>(rules.size() + 4);
}
/**
* Rearranges the RangeEntry objects contained in entries according to rules specified by the user.
* Inserts comments as directed.
*
* @return rearranged list of RangeEntry and CommentRuleInstance objects.
*/
public final List<IRuleInstance> rearrangeEntries() {
final List<IRuleInstance> prioritizedRuleInstances = new ArrayList<IRuleInstance>();
buildRuleInstanceLists(prioritizedRuleInstances);
/**
* recursively reorder contents of every nested ClassEntry.
*/
for (ClassContentsEntry entry : entries) {
if (entry instanceof ClassEntry) {
((ClassEntry)entry).rearrangeContents();
}
}
matchPrioritizedRules(prioritizedRuleInstances);
/**
* Move related methods together. Extracted methods and setters (emitted with getters)
* were not moved by the rearrangement code ("MatchPrioritizedRules()") just above.
*/
rearrangeRelatedItems(entries, resultRuleInstances);
/**
* Now go back and determine which comments are going to be emitted, based on their criteria and the
* state of the immediately surrounding rules. Ignore inner classes if no rearrangement of inner
* classes is taking place.
*/
if (nestingLevel <= 1 || settings.isRearrangeInnerClasses()) {
determineEmittedComments();
}
return resultRuleInstances;
}
/** For each comment rule instance, test its "emit" condition and set its emit flag appropriately. */
private void determineEmittedComments() {
for (int i = 0; i < resultRuleInstances.size(); i++) {
if (resultRuleInstances.get(i) instanceof CommentRuleInstance) {
final CommentRuleInstance ce = (CommentRuleInstance)resultRuleInstances.get(i);
ce.determineEmit(resultRuleInstances, i);
if (ce.isEmit()) {
// set the "separator comment preceding" flag on the next matching RangeEntry.
for (int j = i + 1; j < resultRuleInstances.size(); j++) {
IRuleInstance instance = resultRuleInstances.get(j);
if (instance.hasMatches()) {
RangeEntry entry = (instance.getMatches().get(0));
entry.setSeparatorCommentPrecedes(true);
break;
}
}
}
}
}
}
/**
* For each rule (in prioritized order), test all remaining entries to identify those that match.
* Exclude any extracted (i.e. related) methods and any setter methods that will be emitted with
* a corresponding getter. If an entry matches the rule, add it to the list of entries matching the
* rule and remove it from the list of remaining entries.
*
* @param prioritizedRules prioritized list of rules
*/
@SuppressWarnings({"StringContatenationInLoop"})
private void matchPrioritizedRules(List<IRuleInstance> prioritizedRules) {
for (IRuleInstance ruleInstance : prioritizedRules) {
final IRule rule = ruleInstance.getRule();
final ListIterator entryIterator = entries.listIterator();
while (entryIterator.hasNext()) {
final RangeEntry entry = (RangeEntry)entryIterator.next();
if (entry instanceof IRelatableEntry) {
// if this is an extracted (i.e. related) method, or
// if this is a setter that will be emitted under the corresponding getter,
// don't test it for match against the rule.
final IRelatableEntry relatableEntry = ((IRelatableEntry)entry);
if (relatableEntry.isRelatedMethod() || relatableEntry.isEmittableSetter()) {
continue;
}
}
if (rule.isMatch(entry)) {
LOG.debug("rule:" + rule.toString() + "; entry matched:" + entry.getEnd().toString());
ruleInstance.addEntry(entry);
entry.setMatchedRule(ruleInstance);
entryIterator.remove();
}
}
}
}
/**
* Build two rule instance lists, one in order of emission ("resultRuleInstances") and one
* in order of matching ("prioritizedRuleInstances").
*
* @param prioritizedRuleInstances
*/
private void buildRuleInstanceLists(final List<IRuleInstance> prioritizedRuleInstances) {
/**
* add a HeaderTrailerRuleInstance to pick up any headers that might exist.
*/
IRuleInstance hri = new HeaderRule().createRuleInstance();
resultRuleInstances.add(hri);
prioritizedRuleInstances.add(hri);
for (IRule rule : rules) {
IRuleInstance instance = rule.createRuleInstance();
resultRuleInstances.add(instance);
/**
* now insert the rule instance into the prioritized list; highest priority first; stable insertion.
*/
boolean inserted = false;
for (int i = prioritizedRuleInstances.size() - 1; i >= 0; i--) {
IRuleInstance entry = (prioritizedRuleInstances.get(i));
if (rule.getPriority() <= entry.getRule().getPriority()) {
prioritizedRuleInstances.add(i + 1, instance);
inserted = true;
break;
}
}
if (!inserted) {
prioritizedRuleInstances.add(0, instance);
}
}
// now add a default rule to pick up all unmatched items.
IRuleInstance defaultRuleInstance = new DefaultRule().createRuleInstance();
resultRuleInstances.add(defaultRuleInstance);
prioritizedRuleInstances.add(defaultRuleInstance);
// finally, add a TrailerRuleInstance to pick up any leftover text.
IRuleInstance tri = new TrailerRule().createRuleInstance();
resultRuleInstances.add(tri);
prioritizedRuleInstances.add(tri);
}
/**
* Move any related items (e.g., extracted methods) remaining in 'entries' into the correct position in
* rearrangedEntries.
*
* @param entries
* @param rearrangedEntries
*/
public abstract void rearrangeRelatedItems(List<ClassContentsEntry> entries,
List<IRuleInstance> rearrangedEntries);
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.rearrangement;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.RearrangerSettings;
import java.util.ArrayList;
import java.util.List;
/** Moves (rearranges) classes and class members according to rules specified by the user. */
public final class Mover {
private final List<ClassContentsEntry> outerClasses;
private final RearrangerSettings settings;
public Mover(final List<ClassContentsEntry> outerClasses,
final RearrangerSettings settings)
{
this.outerClasses = new ArrayList<ClassContentsEntry>(outerClasses);
this.settings = settings;
}
public List<IRuleInstance> rearrangeOuterClasses() {
final GenericRearranger outerClassRearranger = new GenericRearranger(
settings.getClassOrderAttributeList(),
outerClasses,
0,
settings)
{
/**
* There are no items related to outer classes -- outer classes are completely disjoint
* and independent. Hence this routine does nothing.
* @param entries
@param rearrangedEntries
*/
public void rearrangeRelatedItems(List<ClassContentsEntry> entries,
List<IRuleInstance> rearrangedEntries)
{
}
};
return outerClassRearranger.rearrangeEntries();
}
}
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.rearrangement;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.entry.ClassEntry;
import com.wrq.rearranger.entry.PsiFileEntry;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.settings.RearrangerSettings;
import java.util.List;
/** Creates a list of entries for classes and class members by parsing the Java file. */
public final class Parser {
private static final Logger LOG = Logger.getInstance("#" + Parser.class.getName());
private final Project project;
private final RearrangerSettings settings;
private final PsiFile psiFile;
public Parser(final Project project,
final RearrangerSettings settings,
final PsiFile psiFile)
{
this.project = project;
this.settings = settings;
this.psiFile = psiFile;
}
public List<ClassContentsEntry> parseOuterLevel() {
/**
* Parse the top level contents of the PsiFile here.
*/
PsiFileEntry fileEntry = new PsiFileEntry(settings);
return fileEntry.parseFile(project, psiFile, settings.getClassOrderAttributeList());
}
private void dumpOuterClasses(final List<? extends ClassEntry> outerClasses) {
LOG.debug("Outer class entries:");
for (ClassEntry classEntry : outerClasses) {
LOG.debug(classEntry.toString());
if (classEntry.getContents() == null) {
// this is a header or trailer, and isn't really a class.
continue;
}
LOG.debug(" === class contents:");
for (RangeEntry rangeEntry : classEntry.getContents()) {
LOG.debug(rangeEntry.toString());
}
LOG.debug(" === end class contents:");
}
}
}
@@ -0,0 +1,685 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.rearrangement;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.wrq.rearranger.settings.ForceBlankLineSetting;
import com.wrq.rearranger.settings.RearrangerSettings;
import javax.swing.*;
import java.util.HashMap;
import java.util.Map;
/** Responsible for adjusting the number of blank lines at strategic places in the source file. */
public class Spacer {
private static final Logger LOG = Logger.getInstance("#" + Spacer.class.getName());
private final Project project;
private final PsiFile psiFile;
private final Document document;
private final PsiElementFactory factory;
private final RearrangerSettings settings;
private final char[] newlineChars;
private boolean changesMade;
private StringBuffer sb;
private Map<PsiWhiteSpace, VirtualElement> virtualElements = new HashMap<PsiWhiteSpace, VirtualElement>();
public Spacer(Project project, PsiFile psiFile, Document document, RearrangerSettings settings) {
this.project = project;
this.psiFile = psiFile;
this.document = document;
this.settings = settings;
changesMade = false;
factory = JavaPsiFacade.getInstance(project).getElementFactory();
int size = 0;
size += settings.getAfterClassLBrace().getnBlankLines() + 1;
size += settings.getBeforeMethodLBrace().getnBlankLines() + 1;
size += settings.getAfterMethodLBrace().getnBlankLines() + 1;
size += settings.getBeforeMethodRBrace().getnBlankLines() + 1;
size += settings.getAfterMethodRBrace().getnBlankLines() + 1;
size += settings.getBeforeClassRBrace().getnBlankLines() + 1;
size += settings.getAfterClassRBrace().getnBlankLines() + 1;
LOG.debug("constructor allocating " + size + " newline chars for max insertion");
newlineChars = new char[size];
while (size > 0) {
newlineChars[--size] = '\n';
}
LOG.debug(settings.getAfterClassLBrace().toString());
LOG.debug(settings.getBeforeMethodLBrace().toString());
LOG.debug(settings.getAfterMethodLBrace().toString());
LOG.debug(settings.getBeforeMethodRBrace().toString());
LOG.debug(settings.getAfterMethodRBrace().toString());
LOG.debug(settings.getBeforeClassRBrace().toString());
LOG.debug(settings.getAfterClassRBrace().toString());
final int ROOM_FOR_EXPANSION = 100;
int maxSize = document.getTextLength() + ROOM_FOR_EXPANSION;
sb = new StringBuffer(maxSize);
}
private class AbortRespacing extends RuntimeException {
}
private class BadPsiElement extends Exception {
BadPsiElement(String string) {
super(string);
}
}
private void handleBadPsiElementException(BadPsiElement bpe, String desc, PsiElement element)
throws AbortRespacing
{
JOptionPane.showMessageDialog(null,
"Spacing could not be performed due to a syntax error:\n" +
desc + element.getText(), "Spacing Error", JOptionPane.ERROR_MESSAGE);
throw new AbortRespacing();
}
public boolean respace() {
sb.append(document.getText());
JavaElementVisitor visitor = new JavaRecursiveElementVisitor() {
private int bias = 0;
public void visitReferenceExpression(PsiReferenceExpression referenceExpression) {
}
public void visitFile(PsiFile psiFile) {
super.visitFile(psiFile);
if (settings.getNewlinesAtEOF().isForce()) {
// remove all newlines at end of file, then append as many as are declared in configuration.
while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '\n') {
sb.setLength(sb.length() - 1);
}
for (int count = 0; count < settings.getNewlinesAtEOF().getnBlankLines(); count++) {
sb.append('\n');
}
}
}
public void visitAnonymousClass(PsiAnonymousClass psiAnonymousClass) {
super.visitAnonymousClass(psiAnonymousClass);
}
public void visitClass(PsiClass psiClass) {
if (psiClass instanceof PsiTypeParameter) {
return;
}
boolean anonymous = psiClass.getName() == null;
int oldbias = bias;
try {
bias += adjustSpacing(
psiClass.getLBrace(),
psiClass.getRBrace(),
settings.getAfterClassLBrace(),
bias
);
}
catch (BadPsiElement badPsiElement) {
handleBadPsiElementException(badPsiElement,
"class " + psiClass.getName() + " missing left brace. Body follows:",
psiClass);
}
log(settings.getAfterClassLBrace(), psiClass.getName(), oldbias, bias);
super.visitClass(psiClass);
oldbias = bias;
try {
bias += adjustSpacing(
psiClass.getRBrace(),
psiClass.getLBrace(),
settings.getBeforeClassRBrace(),
bias
);
}
catch (BadPsiElement badPsiElement) {
handleBadPsiElementException(badPsiElement,
"class " + psiClass.getName() + " missing right brace. Body follows:",
psiClass);
}
log(settings.getBeforeClassRBrace(), psiClass.getName(), oldbias, bias);
if (anonymous) {
return;
}
/**
* if this is the last class in a file, don't adjust spacing after right brace.
* The setting for number of newline characters at end of file overrides it.
*/
boolean lastClass = false;
if (psiClass.getParent() instanceof PsiJavaFile) {
lastClass = isLastMeaningfulElement(psiClass.getParent(), psiClass);
}
if (!lastClass) {
oldbias = bias;
try {
bias += adjustSpacing(
psiClass.getRBrace(),
psiClass.getLBrace(),
settings.getAfterClassRBrace(),
bias
);
}
catch (BadPsiElement badPsiElement) {
handleBadPsiElementException(badPsiElement,
"class " + psiClass.getName() + " missing left brace. Body follows:",
psiClass);
}
log(settings.getAfterClassRBrace(), psiClass.getName(), oldbias, bias);
}
else {
LOG.debug(
"class " +
psiClass.getName() +
" is last in file, no 'after right brace' adjustment"
);
}
}
public void visitMethod(PsiMethod psiMethod) {
int oldbias;
/**
* if method has no body, make no spacing adjustments - there are no braces. It must be an interface
* or abstract method declaration.
*/
if (psiMethod.getBody() == null) {
LOG.debug("skipping interface or abstract method " + psiMethod.getName());
super.visitMethod(psiMethod);
return;
}
/**
* if method has an empty body, do only the spacing before the opening brace and after the closing
* brace.
*/
boolean methodIsEmpty = true;
{
PsiElement element = psiMethod.getBody().getLBrace().getNextSibling();
while (element != null) {
if (!(element instanceof PsiWhiteSpace) &&
element != psiMethod.getBody().getRBrace())
{
methodIsEmpty = false;
break;
}
element = element.getNextSibling();
}
}
if (!methodIsEmpty) {
oldbias = bias;
try {
bias += adjustSpacing(
psiMethod.getBody().getLBrace(),
psiMethod.getBody().getRBrace(),
settings.getBeforeMethodLBrace(),
bias
);
bias += adjustSpacing(
psiMethod.getBody().getLBrace(),
psiMethod.getBody().getRBrace(),
settings.getAfterMethodLBrace(),
bias
);
}
catch (BadPsiElement badPsiElement) {
handleBadPsiElementException(badPsiElement,
"body of method " + psiMethod.getName() + " missing left brace. Body follows:",
psiMethod);
}
log(settings.getAfterMethodLBrace(), psiMethod.getName(), oldbias, bias);
super.visitMethod(psiMethod);
oldbias = bias;
try {
bias += adjustSpacing(
psiMethod.getBody().getRBrace(),
psiMethod.getBody().getLBrace(),
settings.getBeforeMethodRBrace(),
bias
);
}
catch (BadPsiElement badPsiElement) {
handleBadPsiElementException(badPsiElement,
"body of method " + psiMethod.getName() + " missing right brace. Body follows:",
psiMethod);
}
log(settings.getBeforeMethodRBrace(), psiMethod.getName(), oldbias, bias);
}
else {
LOG.debug("method " + psiMethod.getName() + " is empty, no internal spacing changes");
}
/**
* if this is the last method in a class, don't adjust spacing after right brace.
* The class setting for number of spaces before closing right brace overrides it.
* Normally this would make no difference, as the 2nd would cancel out the first;
* but in the case where the method ends with "}});" (anonymous inner class as
* parameter), an inserted blank line actually causes two newline characters to be
* inserted; but the class rule only removes one of those.
*/
boolean lastMethod = false;
PsiClass owner = psiMethod.getContainingClass();
if (owner == psiMethod.getParent()) {
lastMethod = isLastMeaningfulElement(owner, psiMethod);
}
if (!lastMethod) {
oldbias = bias;
try {
bias += adjustSpacing(
psiMethod.getBody().getRBrace(),
psiMethod.getBody().getLBrace(),
settings.getAfterMethodRBrace(),
bias
);
}
catch (BadPsiElement badPsiElement) {
handleBadPsiElementException(badPsiElement,
"body of method " + psiMethod.getName() + " missing right brace. Body follows:",
psiMethod);
}
log(settings.getAfterMethodRBrace(), psiMethod.getName(), oldbias, bias);
}
else {
LOG.debug(
"method " +
psiMethod.getName() +
" is last in class, no 'after right brace' adjustment"
);
}
}
public void visitCodeBlock(PsiCodeBlock psiCodeBlock) {
int oldbias;
if (!(psiCodeBlock.getParent() instanceof PsiMethod) &&
settings.isRemoveBlanksInsideCodeBlocks())
{
oldbias = bias;
try {
bias += adjustSpacing(psiCodeBlock.getLBrace(),
psiCodeBlock.getRBrace(), false, 0, bias);
}
catch (BadPsiElement badPsiElement) {
handleBadPsiElementException(badPsiElement,
"code block missing left brace. Content follows:\n", psiCodeBlock);
}
log("code block left brace", oldbias, bias);
}
super.visitCodeBlock(psiCodeBlock);
if (!(psiCodeBlock.getParent() instanceof PsiMethod) &&
settings.isRemoveBlanksInsideCodeBlocks())
{
oldbias = bias;
try {
bias += adjustSpacing(psiCodeBlock.getRBrace(), psiCodeBlock.getLBrace(), true, 0, bias);
}
catch (BadPsiElement badPsiElement) {
handleBadPsiElementException(badPsiElement,
"code block missing right brace. Content follows:\n", psiCodeBlock);
}
log("code block right brace", oldbias, bias);
}
}
};
try {
psiFile.accept(visitor);
}
catch (AbortRespacing ar) {
return false;
}
if (changesMade) {
LOG.debug(
"changes made to document; old length=" +
document.getTextLength() + ", new=" + sb.length()
);
LOG.debug("old document is:\n" + document.getText());
LOG.debug("new document is:\n" + sb.toString());
document.replaceString(0, document.getTextLength(), sb.toString());
}
return changesMade;
}
/**
* Determines if the psiElement (method or class) is last syntactic item in the owner class.
* If so, we don't want to change spacing after right brace of psiElement; this spacing is
* overridden by the parent class's spacing before right brace.
*
* @param owner class element to which psiElement belongs.
* @param psiElement method or inner class to be tested.
* @return true if the psiElement is the last syntactic item (i.e., not including comments and whitespace)
* of the owner.
*/
private boolean isLastMeaningfulElement(PsiElement owner, PsiElement psiElement) {
boolean lastMethod;
// class is immediate parent
PsiElement[] elements = owner.getChildren();
boolean sawThisMethod = false;
boolean sawSomethingElseLater = false;
for (PsiElement element : elements) {
if (!sawThisMethod && element == psiElement) {
sawThisMethod = true;
}
else if (sawThisMethod &&
!(element instanceof PsiWhiteSpace) &&
!(element instanceof PsiJavaToken &&
element.getText().equals("}")))
// ((PsiJavaToken) elements[i]).getTokenType() == PsiJavaToken.RBRACE))
{
sawSomethingElseLater = true;
break;
}
}
lastMethod = sawThisMethod && !sawSomethingElseLater;
return lastMethod;
}
private void log(ForceBlankLineSetting fbls, String name, int oldbias, int bias) {
if (oldbias != bias) {
LOG.debug(
fbls.getObjectName() +
" " +
name +
(fbls.isBefore() ? " before" : " after") +
(fbls.isOpenBrace() ? " left brace:" : " right brace:") +
(oldbias < bias ? " inserted " + (bias - oldbias)
: " removed " + (oldbias - bias)) + " newlines"
);
}
}
private void log(String name, int oldbias, int bias) {
if (oldbias != bias) {
LOG.debug(
name +
(oldbias < bias ? " inserted " + (bias - oldbias)
: " removed " + (oldbias - bias)) + " newlines"
);
}
}
private int adjustSpacing(PsiElement brace, PsiElement matchingBrace, ForceBlankLineSetting fbls, int bias)
throws BadPsiElement
{
if (fbls.isForce()) {
return adjustSpacing(brace, matchingBrace, fbls.isBefore(), fbls.getnBlankLines(), bias);
}
else {
return 0;
}
}
/**
* When whiteSpace is changed based on contents of a PsiWhiteSpace element, we need to keep track of that
* so that if a subsequent adjustment in spacing is based on that same element, we use the new whitespace value.
*/
private class VirtualElement {
private String textValue;
private final int textOffset;
VirtualElement(PsiWhiteSpace whiteSpace, int bias) {
textValue = whiteSpace.getText();
textOffset = whiteSpace.getTextOffset() + bias;
virtualElements.put(whiteSpace, this);
}
String getText() {
return textValue;
}
public void setTextValue(String textValue) {
this.textValue = textValue;
}
public int getTextOffset() {
return textOffset;
}
}
/**
* Determine the number of blank lines actually occurring before or after the brace. If this is not
* the desired number, alter the whitespace before or after the brace to contain the desired number
* of blank lines.
*
* @param brace
* @param before
* @param nBlankLines
* @param bias
* @return bias adjustment corresponding to number of newlines inserted or deleted
*/
private int adjustSpacing(PsiElement brace, PsiElement matchingBrace, boolean before, int nBlankLines, int bias)
throws BadPsiElement
{
int result = 0;
if (brace == null) {
throw new BadPsiElement(
"adjustSpacing: illegal syntax (mismatched braces); PsiElement for brace is null"
);
}
/*
* ensure that character at offset indicated by brace element is in fact a brace.
*/
int offset = brace.getTextRange().getStartOffset() + bias;
int direction = before ? -1 : +1;
int count = 0;
{
char braceChar = sb.charAt(offset);
if (braceChar != '{' && braceChar != '}') {
int L = offset - 50;
int R = offset + 50;
if (L < 0) {
L = 0;
}
if (R > sb.length()) {
R = sb.length();
}
String context = sb.toString().substring(L, R);
throw new RuntimeException(
"adjustSpacing: char at offset " +
offset +
" is not a brace, ='" +
braceChar + "'" + "; context is " + context
);
}
}
/*
* Locate the whitespace that precedes or follows this brace and which contains newline characters.
* Intervening text, such as comments and other syntactic items, could be skipped.
*/
PsiElement whiteSpace = brace;
do {
whiteSpace = getNextElement(whiteSpace, before);
if (whiteSpace == matchingBrace) {
/**
* Don't parse past the matching brace. This could occur if a class or method body is empty and
* the left and right braces are on the same line with no intervening whitespace.
*/
return result;
}
}
while (whiteSpace != null &&
(!(whiteSpace instanceof PsiWhiteSpace) ||
whiteSpace.getText().indexOf('\n') < 0));
VirtualElement virtualWhiteSpace = null;
if (whiteSpace != null) {
virtualWhiteSpace = (virtualElements.get(whiteSpace));
if (virtualWhiteSpace == null) {
virtualWhiteSpace = new VirtualElement((PsiWhiteSpace)whiteSpace, bias);
}
else {
LOG.debug("reusing virtualWhiteSpace, offset=" + virtualWhiteSpace.textOffset);
}
/*
* now count the number of newlines.
*/
String s = virtualWhiteSpace.getText();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '\n') {
count++;
}
}
}
/**
* first count the number of existing blank lines.
*/
if (offset + direction >= sb.length()) {
LOG.debug("at EOF, don't append any extra blank lines");
// we're at end of file. Don't append any extra blank lines.
nBlankLines = 0;
}
/**
* Count of one means there was a single newline character next to the brace.
* This can be counted as the one that belongs on the brace's line. So the real number
* of consecutive newline characters desired is nBlankLines + 1.
*/
int desiredNewlineChars = nBlankLines + 1;
if (desiredNewlineChars == 1 && count == 0 && before) {
// no blank lines to precede this text; in fact, there's prior text and no newline character at all.
// this is acceptable.
desiredNewlineChars = 0;
}
{
PsiElement element = brace.getParent();
if (element instanceof PsiCodeBlock &&
element.getParent() instanceof PsiMethod)
{
element = element.getParent();
}
LOG.debug(
"adjustSpacing: " +
(before ? "before " : "after ") +
element.toString() +
" " +
brace.getText() +
", desire " + desiredNewlineChars + " newlines, have " + count
);
}
if (desiredNewlineChars == count) {
return 0;
}
/*
* determine end index of whitespace to be replaced.
* keep trailing spaces/tabs.
*/
int endIndex;
// if (whiteSpace != null) // todo - try modifying the PSI tree
// {
// try
// {
// StringBuilder sbr = new StringBuilder(whiteSpace.getText());
// if (desiredNewlineChars > count) sbr.append(newlineChars, 0, desiredNewlineChars - count);
// else sbr.setLength(sbr.length() + desiredNewlineChars - count);
// PsiElement codeblk = factory.createCodeBlockFromText(sbr.toString(), element);
// whiteSpace.replace(codeblk.getFirstChild());
// }
// catch (IncorrectOperationException e)
// {
// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
// }
// }
if (virtualWhiteSpace != null) {
String s = virtualWhiteSpace.getText();
for (endIndex = s.length() - 1; endIndex >= 0; endIndex--) {
if (s.charAt(endIndex) != ' ' &&
s.charAt(endIndex) != '\t')
{
break;
}
} // now endIndex points to the last newline character in the whitespace.
offset = virtualWhiteSpace.getTextOffset();
endIndex += offset + 1;
}
else {
offset = endIndex = sb.length();
}
try {
changesMade = true;
LOG.debug(
"sb.replace(" +
offset +
"," +
endIndex + ") with " + desiredNewlineChars + " newline characters"
);
sb.replace(offset, endIndex, new String(newlineChars, 0, desiredNewlineChars));
result = desiredNewlineChars - (endIndex - offset);
// now update virtualWhiteSpace accordingly.
if (virtualWhiteSpace != null) {
offset -= virtualWhiteSpace.getTextOffset();
endIndex -= virtualWhiteSpace.getTextOffset();
StringBuffer vsb = new StringBuffer(virtualWhiteSpace.getText());
vsb.replace(offset, endIndex, new String(newlineChars, 0, desiredNewlineChars));
virtualWhiteSpace.setTextValue(vsb.toString());
}
}
catch (StringIndexOutOfBoundsException si) {
throw new RuntimeException(
"sb.length()=" +
sb.length() +
", offset=" +
offset +
", before=" +
before +
", count=" +
count +
", desiredNewlineChars=" +
desiredNewlineChars +
", charAt offset=" + (offset < sb.length() ? "" + sb.charAt(offset) : "OOB"), si
);
}
return result;
}
/**
* Returns the leaf psiElement before or after the given element.
*
* @param element original element.
* @param before if true, return prior leaf element; else return next left element.
* @return adjacent leaf element.
*/
private PsiElement getNextElement(PsiElement element, boolean before) {
PsiElement result;
while (true) {
result = before ? element.getPrevSibling() : element.getNextSibling();
if (result == null) {
// first/last sibling; go to parent's previous/next item.
result = element.getParent();
if (result instanceof PsiFile) {
// don't go beyond this document!
result = null;
}
// if we started at the first/last leaf node, we run out of parents; there is no previous/next leaf element.
if (result == null) {
break;
}
else {
element = result;
}
}
else {
break;
}
}
while (result != null && result.getChildren().length != 0) {
// previous/next sibling is parent of others; find last/first leaf node.
result = result.getChildren()[before ? result.getChildren().length - 1 : 0];
}
return result;
}
}
@@ -0,0 +1,187 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.popup.IFilePopupEntry;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.settings.CommentRule;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.IRule;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/** Used to store a generated comment, and to determine if it should be emitted. */
public abstract class CommentRuleInstance
implements IRuleInstance,
IFilePopupEntry
{
protected final CommentRule commentRule;
protected boolean emit;
public CommentRuleInstance(final CommentRule commentRule) {
this.commentRule = commentRule;
emit = false;
}
public boolean isEmit() {
return emit;
}
public void setEmit(final boolean emit) {
this.emit = emit;
}
public IRule getRule() {
return commentRule;
}
/** Determine if this comment, in this instance, should be emitted. */
public abstract void determineEmit(List<IRuleInstance> resultRuleInstances, int startIndex);
public boolean hasMatches() {
return false; // a generated comment never matches any object
}
public void emit(Emitter emitter) {
StringBuffer sb = emitter.getStringBuffer();
if (emit) {
// emit a comment. Precede with a newline unless this is the first line of the file.
if (sb.length() > 0) {
sb.append('\n');
sb.append(commentRule.getExpandedCommentText());
}
else {
sb.append(commentRule.getExpandedCommentText());
sb.append('\n');
}
}
}
public void addEntry(RangeEntry entry) // adds entry to list of matching entries, in correct order
{
// comment rules don't match anything in the existing file; they conditionally generate comments.
// So this method will never be called.
throw new RuntimeException("cannot add entry to comment rule instance");
}
public List<RangeEntry> getMatches() {
return new ArrayList<RangeEntry>();
}
public void rearrangeRuleItems(List<ClassContentsEntry> entries,
RearrangerSettings settings)
{
}
public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) {
/**
* if we are supposed to show comment rules, create a node for the rule and put its contents below.
* Otherwise, just add comments.
*/
if (!settings.isShowComments()) return;
DefaultMutableTreeNode top = node;
if (settings.isShowRules()) {
// if "show matched rules only" is set, only display if comment will be emitted
if ((!settings.isShowMatchedRules()) || isEmit()) {
top = new DefaultMutableTreeNode(this);
node.add(top);
}
}
/**
* append the comment if generated and if showComments is set.
*/
if (isEmit()) {
commentRule.addToPopupTree(top, settings);
}
}
public String getTypeIconName() {
return null;
}
@Nullable
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
JLabel label = new JLabel(commentRule.toString());
Font font = label.getFont().deriveFont(Font.ITALIC);
label.setFont(font);
return label;
}
public String toString() {
return "instance of:" + commentRule.toString();
}
/**
* beginning at the index of ruleStatistics (which is a comment entry), find nRules in the direction indicated,
* and test to see if all or any of them had entries that matched.
*
* @param nRules number of rules to consider for matching algorithm.
* @param direction 1 = subsequent, -1 = previous.
* @param startIndex comment entry index, sandwiched between rules.
* @param ANDing if true, all rules must be matched; if false, any rule that matches returns a result of true.
* @return true if the match condition is met.
*/
@SuppressWarnings({"MethodParameterNamingConvention"})
protected boolean match(final List<IRuleInstance> resultRuleInstances,
final int nRules,
final int direction,
final int startIndex,
final boolean ANDing)
{
int index = startIndex + direction;
int nRulesSeen = 0;
while (index >= 0 &&
index < resultRuleInstances.size() &&
nRulesSeen < nRules)
{
if (!(resultRuleInstances.get(index) instanceof CommentRuleInstance)) {
// this is a rule entry, not a comment.
nRulesSeen++;
final IRuleInstance ruleInstance = resultRuleInstances.get(index);
if (ruleInstance.hasMatches()) {
if (!ANDing) {
return true; // OR condition (any matching rule) met
}
}
else {
if (ANDing) {
return false; // AND condition not met
}
}
}
index += direction;
}
return ANDing;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.settings.CommentRule;
/** Creates appropriate subtype of CommentRuleInstance from a CommentRule. */
@SuppressWarnings({"UtilityClass"})
public class CommentRuleInstanceFactory {
private CommentRuleInstanceFactory() {
}
@SuppressWarnings({"MethodWithMultipleReturnPoints"})
public static CommentRuleInstance buildCommentRuleInstance(CommentRule rule) {
switch (rule.getEmitCondition()) {
case CommentRule.EMIT_ALWAYS:
return new EmitAlwaysCommentRuleInstance(rule);
case CommentRule.EMIT_IF_ITEMS_MATCH_SURROUNDING_RULES:
return new SurroundingCommentRuleInstance(rule);
case CommentRule.EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE:
return new SubsequentCommentRuleInstance(rule);
case CommentRule.EMIT_IF_ITEMS_MATCH_PRECEDING_RULE:
return new PrecedingCommentRuleInstance(rule);
default:
throw new IllegalStateException("unknown emit condition type=" + rule.getEmitCondition());
}
}
}
@@ -0,0 +1,160 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.intellij.openapi.diagnostic.Logger;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.entry.IPopupTreeRangeEntry;
import com.wrq.rearranger.entry.MethodEntry;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.popup.IFilePopupEntry;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.atomicAttributes.SortOptions;
import com.wrq.rearranger.settings.attributeGroups.CommonAttributes;
import com.wrq.rearranger.settings.attributeGroups.IRule;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/** Handles basic Rule functions. */
public abstract class CommonRuleInstance
implements IRuleInstance,
IFilePopupEntry
{
private static final Logger LOG = Logger.getInstance("#" + CommonRuleInstance.class.getName());
protected final IRule rule;
protected final List<RangeEntry> matchedItems;
public CommonRuleInstance(IRule rule) {
this.rule = rule;
matchedItems = new ArrayList<RangeEntry>();
}
public IRule getRule() {
return rule;
}
/**
* adds entry to list of matching entries, in correct order (order encountered, or alphabetically)
*
* @param entry
*/
public void addEntry(RangeEntry entry) {
if (rule instanceof CommonAttributes) {
SortOptions sortOptions = ((CommonAttributes)rule).getSortAttr();
insertionSort(entry, sortOptions);
}
else {
matchedItems.add(entry);
}
}
public List<RangeEntry> getMatches() {
return matchedItems;
}
private void insertionSort(final RangeEntry newEntry, final SortOptions sortOptions) {
boolean inserted = false;
final String s = sortOptions.generateSortString(newEntry);
LOG.debug("insertionSort: new entry=" + s);
int index = 0;
while (index < matchedItems.size()) {
final RangeEntry re = matchedItems.get(index);
final String res = sortOptions.generateSortString(re);
LOG.debug("insertionSort: compare to " + res);
if (s.compareTo(res) < 0) {
LOG.debug("insertionSort: insert at " + index);
matchedItems.add(index, newEntry);
inserted = true;
break;
}
index++;
}
if (!inserted) {
LOG.debug("insertionSort: add " + s + " to end");
matchedItems.add(newEntry);
}
}
public boolean hasMatches() {
return matchedItems.size() > 0;
}
public void emit(Emitter emitter) {
for (RangeEntry rangeEntry : matchedItems) {
rangeEntry.emit(emitter);
}
}
public void rearrangeRuleItems(List<ClassContentsEntry> entries,
RearrangerSettings settings)
{
MethodEntry.rearrangeRelatedItems(
entries,
this,
settings.getExtractedMethodsSettings()
);
}
public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) {
/**
* if we are supposed to show rules, create a node for the rule and put its contents below.
* Otherwise, delegate to each of the matches.
*/
DefaultMutableTreeNode top = node;
if (settings.isShowRules() &&
(!settings.isShowMatchedRules() || hasMatches()))
{
top = new DefaultMutableTreeNode(this);
node.add(top);
}
/**
* append each of the matches to the top level.
*/
for (IPopupTreeRangeEntry entry : getMatches()) {
entry.addToPopupTree(top, settings);
}
}
public String getTypeIconName() {
return "general/templateGroup";
}
public String[] getAdditionalIconNames() {
return null;
}
public JLabel getPopupEntryText(RearrangerSettings settings) {
JLabel label = new JLabel(toString());
Font font = label.getFont().deriveFont(Font.ITALIC);
label.setFont(font);
return label;
}
public String toString() {
return getRule().toString();
}
}
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.settings.attributeGroups.IRule;
/** Collects any remaining RangeEntries after all explicit rule matching is done. */
public class DefaultRuleInstance extends CommonRuleInstance {
public DefaultRuleInstance(IRule defaultRule) {
super(defaultRule);
}
public String toString() {
return getRule().toString();
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.settings.CommentRule;
import java.util.List;
/** Used to store a generated comment which is always emitted. */
public class EmitAlwaysCommentRuleInstance
extends CommentRuleInstance
{
public EmitAlwaysCommentRuleInstance(final CommentRule commentRule) {
super(commentRule);
}
/**
* Determine if this comment, in this instance, should be emitted.
* For an "Emit Always" type of comment, it should always be emitted.
*/
public void determineEmit(List<IRuleInstance> resultRuleInstances, int startIndex) {
setEmit(true);
}
}
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.IRule;
import javax.swing.tree.DefaultMutableTreeNode;
import java.util.ArrayList;
import java.util.List;
/** Instance to pick up header text. */
public class HeaderTrailerRuleInstance
implements IRuleInstance
{
private final IRule rule;
private RangeEntry entry;
public HeaderTrailerRuleInstance(IRule rule) {
this.rule = rule;
}
public boolean hasMatches() {
return false; // comments are never emitted based on whether header text is emitted, so false is fine.
}
public List<RangeEntry> getMatches() {
List<RangeEntry> list = null;
if (entry != null) {
list = new ArrayList<RangeEntry>();
list.add(entry);
}
return list;
}
public IRule getRule() {
return rule;
}
public void addEntry(RangeEntry entry) {
this.entry = entry; // a header only has one entry
}
public void emit(Emitter emitter) {
if (entry != null) {
entry.emit(emitter);
}
}
public void rearrangeRuleItems(List<ClassContentsEntry> entries,
RearrangerSettings settings)
{
return;
}
public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) {
return; // don't show header/trailer junk in popup tree
}
}
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.IRule;
import javax.swing.tree.DefaultMutableTreeNode;
import java.util.List;
/**
* One RuleInstance exists for every execution of every rule. An execution of a rule is the process by which
* items are matched to a rule.
*/
public interface IRuleInstance {
/** @return true if one or more items matched the rule in this instance. */
boolean hasMatches();
/** @return list of items matching the rule in this instance. */
List<RangeEntry> getMatches();
/**
* Causes the text representation of this item to be emitted to a buffer, and from there into the final Document.
*
* @param emitter Emitter target object with buffer and Document.
*/
void emit(Emitter emitter);
/** @return the rule associated with this instance. */
IRule getRule();
/**
* Adds an item to the list of items matching the rule in this instance. Order is preserved.
*
* @param entry matching item
*/
void addEntry(RangeEntry entry);
/**
* Perform any rearranging based on rule or item relationships indicated by the settings.
*
* @param entries list of items (fields, methods, etc.)
* @param settings
*/
void rearrangeRuleItems(List<ClassContentsEntry> entries, RearrangerSettings settings);
/** add the contents of this rule to the file structure popup tree. */
void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings);
}
@@ -0,0 +1,146 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.entry.MethodEntry;
import com.wrq.rearranger.popup.IFilePopupEntry;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.settings.CommentRule;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.InterfaceAttributes;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/** Corresponds to a single interface with one or more implementing methods. */
public class InterfaceInstance
implements IFilePopupEntry
{
// ------------------------------------------------------- FIELDS ------------------------------------------------------
private String interfaceName;
public String getInterfaceName() {
return interfaceName;
}
private List<MethodEntry> methods;
private InterfaceAttributes rule;
// ---------------------------------------------------- CONSTRUCTORS ---------------------------------------------------
public InterfaceInstance(String interfaceName, InterfaceAttributes rule) {
this.interfaceName = interfaceName;
methods = new ArrayList<MethodEntry>();
this.rule = rule;
}
// ---------------------------------------------- GETTER / SETTER METHODS ----------------------------------------------
public String[] getAdditionalIconNames() {
return null;
}
public String getTypeIconName() {
return null;
}
// ------------------------------------------------- INTERFACE METHODS -------------------------------------------------
// --------------------------------------------- Interface IFilePopupEntry ---------------------------------------------
public JLabel getPopupEntryText(RearrangerSettings settings) {
JLabel label = new JLabel("methods of interface " + interfaceName);
Font font = label.getFont().deriveFont(Font.ITALIC);
label.setFont(font);
return label;
}
// --------------------------------------------------- OTHER METHODS ---------------------------------------------------
/**
* add the method to the list of methods, in the order specified by the configuration settings (alphabetical,
* in order declared in the interface, or in order encountered).
*
* @param entry method to add.
*/
void addMethod(MethodEntry entry) {
switch (rule.getMethodOrder()) {
case InterfaceAttributes.METHOD_ORDER_ALPHABETICAL:
entry.insertAlphabetically(methods);
break;
case InterfaceAttributes.METHOD_ORDER_ENCOUNTERED:
methods.add(entry);
break;
case InterfaceAttributes.METHOD_ORDER_INTERFACE_ORDER:
entry.insertInterfaceOrder(methods);
break;
}
}
public void addToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) {
/**
* if we are supposed to show rules, create a node for the rule and put its contents below.
* Otherwise, delegate to each of the matches.
*/
DefaultMutableTreeNode top = node;
if (settings.isShowRules()) {
top = new DefaultMutableTreeNode(this);
node.add(top);
}
/**
* append each of the matches to the top level.
*/
for (MethodEntry entry : methods) {
entry.addToPopupTree(top, settings);
}
}
void emit(Emitter emitter) {
StringBuffer sb = emitter.getStringBuffer();
String commentString = expandComment(rule.getPrecedingComment());
if (commentString.length() > 0) {
sb.append("\n");
sb.append(commentString);
}
for (MethodEntry rangeEntry : methods) {
rangeEntry.emit(emitter);
}
commentString = expandComment(rule.getTrailingComment());
if (commentString.length() > 0) {
sb.append("\n");
sb.append(commentString);
}
}
private String expandComment(CommentRule comment) {
if (comment == null || comment.getCommentText() == null) return "";
comment.setCommentFillString(rule.getCommentFillString());
String result = comment.getCommentText().replaceAll("%IF%", interfaceName);
result = rule.getCommentFillString().getExpandedCommentText(result);
return result;
}
}
@@ -0,0 +1,136 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.entry.ClassContentsEntry;
import com.wrq.rearranger.entry.MethodEntry;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.rearrangement.Emitter;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.settings.attributeGroups.IRule;
import com.wrq.rearranger.settings.attributeGroups.InterfaceAttributes;
import javax.swing.tree.DefaultMutableTreeNode;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/** Handles interface rule processing. */
public class InterfaceRuleInstance
extends CommonRuleInstance
{
// ------------------------------ FIELDS ------------------------------
List<InterfaceInstance> interfaceInstances;
// --------------------------- CONSTRUCTORS ---------------------------
public InterfaceRuleInstance(IRule rule) {
super(rule);
interfaceInstances = new ArrayList<InterfaceInstance>();
}
// -------------------------- OTHER METHODS --------------------------
/**
* override the supermethod because we never want to alphabetize methods based on the "alphabetize" flag; that
* flag controls whether interfaces are alphabetized or not. Just add the methods to the list in order encountered.
*
* @param entry
*/
public void addEntry(RangeEntry entry) {
matchedItems.add((MethodEntry)entry);
}
public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) {
/**
* if we are supposed to show rules, create a node for the rule and put its contents below.
* Otherwise, delegate to each of the matches.
*/
DefaultMutableTreeNode top = node;
if (settings.isShowRules()) {
top = new DefaultMutableTreeNode(this);
node.add(top);
}
/**
* An InterfaceRuleInstance has a list of InterfaceInstances, which in turn list the methods which matched
* the name of the interface. Build the tree accordingly.
*/
for (InterfaceInstance instance : interfaceInstances) {
instance.addToPopupTree(top, settings);
}
}
public void emit(Emitter emitter) {
for (Object interfaceInstance : interfaceInstances) {
InterfaceInstance instance = (InterfaceInstance)interfaceInstance;
instance.emit(emitter);
}
}
public void rearrangeRuleItems(List<ClassContentsEntry> entries,
RearrangerSettings settings)
{
/**
* create a list of interface instances, one for each interface specified by any of the matched methods.
* Alphabetize this list if specified.
*/
for (RangeEntry re : matchedItems) {
MethodEntry me = (MethodEntry)re;
InterfaceInstance instance = null;
for (InterfaceInstance interfaceInstance : interfaceInstances) {
if (interfaceInstance.getInterfaceName().equals(me.getInterfaceName())) {
instance = interfaceInstance;
}
}
if (instance == null) {
final InterfaceAttributes interfaceRule = (InterfaceAttributes)getRule();
instance = new InterfaceInstance(me.getInterfaceName(), interfaceRule);
if (interfaceRule.isAlphabetize()) {
boolean inserted = false;
String s = instance.getInterfaceName();
ListIterator<InterfaceInstance> lii = interfaceInstances.listIterator();
while (lii.hasNext()) {
InterfaceInstance entry = (lii.next());
final String ename = entry.getInterfaceName();
if (s.compareTo(ename) < 0) {
interfaceInstances.add(lii.nextIndex() - 1, instance);
inserted = true;
break;
}
}
if (!inserted) {
interfaceInstances.add(instance);
}
}
else {
interfaceInstances.add(instance);
}
}
instance.addMethod(me);
}
MethodEntry.rearrangeRelatedItems(entries,
this,
settings.getExtractedMethodsSettings());
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.settings.CommentRule;
import java.util.List;
/** Used to store a generated comment which is emitted based on whether it matches preceding rules. */
public class PrecedingCommentRuleInstance
extends CommentRuleInstance
{
public PrecedingCommentRuleInstance(final CommentRule commentRule) {
super(commentRule);
}
/** Determine if this comment, in this instance, should be emitted. */
public void determineEmit(List<IRuleInstance> resultRuleInstances, int startIndex) {
if (match(
resultRuleInstances,
commentRule.getnPrecedingRulesToMatch(),
-1,
startIndex,
commentRule.isAllPrecedingRules()))
{
setEmit(true);
}
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.settings.CommentRule;
import java.util.List;
/** Used to store a generated comment which is emitted based on whether it matches subsequent rules. */
public class SubsequentCommentRuleInstance
extends CommentRuleInstance
{
public SubsequentCommentRuleInstance(final CommentRule commentRule) {
super(commentRule);
}
/** Determine if this comment, in this instance, should be emitted. */
public void determineEmit(List<IRuleInstance> resultRuleInstances, int startIndex) {
if (match(
resultRuleInstances,
commentRule.getnSubsequentRulesToMatch(),
+1,
startIndex,
commentRule.isAllSubsequentRules()
))
{
setEmit(true);
}
}
}
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.ruleinstance;
import com.wrq.rearranger.settings.CommentRule;
import java.util.List;
/** Used to store a generated comment which is emitted based on whether it matches surrounding rules. */
public class SurroundingCommentRuleInstance
extends CommentRuleInstance
{
public SurroundingCommentRuleInstance(final CommentRule commentRule) {
super(commentRule);
}
/** Determine if this comment, in this instance, should be emitted. */
public void determineEmit(List<IRuleInstance> resultRuleInstances, int startIndex) {
if (match(
resultRuleInstances,
commentRule.getnPrecedingRulesToMatch(),
-1,
startIndex,
commentRule.isAllPrecedingRules()
) &&
match(
resultRuleInstances,
commentRule.getnSubsequentRulesToMatch(),
+1,
startIndex,
commentRule.isAllSubsequentRules()
))
{
setEmit(true);
}
}
}
@@ -0,0 +1,196 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings;
import com.wrq.rearranger.RearrangerActionHandler;
import com.wrq.rearranger.configuration.IntTextField;
import com.wrq.rearranger.settings.attributeGroups.RegexUtil;
import com.wrq.rearranger.util.CommentUtil;
import com.wrq.rearranger.util.Constraints;
import org.jdom.Attribute;
import org.jdom.Element;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/** Implements routines for handling comment fill string expansion. */
public class CommentFillString {
private String fillString; // replicate in place of %FS%
private boolean useProjectWidthForFill;
private int fillWidth;
public CommentFillString() {
fillString = "";
useProjectWidthForFill = true;
fillWidth = 0;
}
public final String getExpandedCommentText(String commentText) {
int width = useProjectWidthForFill ? RearrangerActionHandler.getRightMargin() : fillWidth;
int tabSize = RearrangerActionHandler.getTabSize();
return CommentUtil.expandFill(commentText, width, tabSize, fillString);
}
public String getFillString() {
return fillString;
}
public void setFillString(String fillString) {
this.fillString = fillString;
}
public boolean isUseProjectWidthForFill() {
return useProjectWidthForFill;
}
public void setUseProjectWidthForFill(boolean useProjectWidthForFill) {
this.useProjectWidthForFill = useProjectWidthForFill;
}
public int getFillWidth() {
return fillWidth;
}
public void setFillWidth(int fillWidth) {
this.fillWidth = fillWidth;
}
public final boolean equals(final Object object) {
if (!(object instanceof CommentFillString)) return false;
final CommentFillString c = (CommentFillString)object;
return fillString.equals(c.fillString) &&
useProjectWidthForFill == c.useProjectWidthForFill &&
fillWidth == c.fillWidth;
}
public final CommentFillString deepCopy() {
final CommentFillString comment = new CommentFillString();
comment.fillString = fillString;
comment.useProjectWidthForFill = useProjectWidthForFill;
comment.fillWidth = fillWidth;
return comment;
}
public static CommentFillString readExternal(final Element item) {
final CommentFillString result = new CommentFillString();
Attribute fillAttr = RearrangerSettings.getAttribute(item, "fillString");
if (fillAttr == null) {
result.fillString = "";
}
else {
String fill = fillAttr.getValue();
result.fillString = CommentRule.unescape(fill);
}
result.useProjectWidthForFill = RearrangerSettings.getBooleanAttribute(item, "useProjectWidthForFill", true);
result.fillWidth = RearrangerSettings.getIntAttribute(item, "fillWidth", 0);
return result;
}
public final void writeExternal(final Element me) {
me.setAttribute("fillString", CommentRule.escape(fillString));
me.setAttribute("useProjectWidthForFill", "" + useProjectWidthForFill);
me.setAttribute("fillWidth", "" + fillWidth);
}
public final JPanel getCommentFillStringPanel() {
final JPanel cfsPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(4, 4, 4, 0);
constraints.newRow();
final JLabel fillStringLabel = new JLabel("Fill string:");
fillStringLabel.setToolTipText("Occurrences of %FS% in the comment separator text will be replaced with equal \n" +
"amounts of the fill string, replicated to make the comment end at the specified column");
cfsPanel.add(fillStringLabel, constraints.firstCol());
final JTextField fillString = new JTextField(this.fillString);
cfsPanel.add(fillString, constraints.weightedLastCol());
constraints.newRow();
final JCheckBox useProjectWidthBox = new JCheckBox("Use project right margin as fill width");
useProjectWidthBox.setSelected(useProjectWidthForFill);
cfsPanel.add(useProjectWidthBox, constraints.weightedLastCol());
constraints.lastRow();
constraints.insets = new Insets(4, 15, 4, 4);
final JLabel fillWidthLabel = new JLabel("Fill width:");
cfsPanel.add(fillWidthLabel, constraints.firstCol());
final IntTextField fillWidthField = new IntTextField(
new IntTextField.IGetSet() {
public int get() {
return fillWidth;
}
public void set(int value) {
fillWidth = value;
}
},
0,
999
);
cfsPanel.add(fillWidthField, constraints.nextCol());
cfsPanel.add(new JLabel(), constraints.weightedLastCol());
fillWidthLabel.setEnabled(!useProjectWidthForFill);
fillWidthField.setEnabled(!useProjectWidthForFill);
fillString.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
setFillString(fillString.getText());
}
public void removeUpdate(DocumentEvent e) {
setFillString(fillString.getText());
}
public void changedUpdate(DocumentEvent e) {
setFillString(fillString.getText());
}
});
useProjectWidthBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
useProjectWidthForFill = useProjectWidthBox.isSelected();
fillWidthLabel.setEnabled(!useProjectWidthForFill);
fillWidthField.setEnabled(!useProjectWidthForFill);
}
});
return cfsPanel;
}
/** Returns a regular expression that will match the fill string. */
public String getFillStringPattern() {
String fs = fillString;
if (fs.length() == 0) fs = " ";
final int length = fs.length();
StringBuffer sb = new StringBuffer(length * (length + 1) / 2 + length * 3);
sb.append('(');
sb.append(RegexUtil.escape(fs));
sb.append(")*");
if (length > 1) {
sb.append('(');
for (int i = length - 1; i > 0; i--) {
sb.append(RegexUtil.escape(fs.substring(0, i)));
sb.append(i <= 1 ? ")?" : "|");
}
}
return sb.toString();
}
}
@@ -0,0 +1,613 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings;
import com.wrq.rearranger.entry.IPopupTreeRangeEntry;
import com.wrq.rearranger.entry.RangeEntry;
import com.wrq.rearranger.popup.IFilePopupEntry;
import com.wrq.rearranger.popup.RearrangerTreeNode;
import com.wrq.rearranger.ruleinstance.CommentRuleInstanceFactory;
import com.wrq.rearranger.ruleinstance.IRuleInstance;
import com.wrq.rearranger.settings.attributeGroups.AttributeGroup;
import com.wrq.rearranger.settings.attributeGroups.RegexUtil;
import com.wrq.rearranger.util.Constraints;
import org.jdom.Attribute;
import org.jdom.Element;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
/** Handles insertion of comment separators between sections of the rearranged file. */
public final class CommentRule
implements AttributeGroup,
IPopupTreeRangeEntry,
IFilePopupEntry
{
// ------------------------------------------------------- FIELDS ------------------------------------------------------
public static final int EMIT_ALWAYS = 0;
public static final int EMIT_IF_ITEMS_MATCH_PRECEDING_RULE = 1;
public static final int EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE = 2;
public static final int EMIT_IF_ITEMS_MATCH_SURROUNDING_RULES = 3;
private String commentText;
public final String getCommentText() {
return commentText;
}
public final void setCommentText(final String commentText) {
StringBuffer sb = new StringBuffer(commentText);
while (sb.length() > 0 &&
Character.isWhitespace(sb.charAt(sb.length() - 1)) &&
sb.charAt(sb.length() - 1) != '\n')
{
sb.setLength(sb.length() - 1);
}
this.commentText = sb.toString();
}
private int emitCondition;
public final int getEmitCondition() {
return emitCondition;
}
public final void setEmitCondition(final int emitCondition) {
this.emitCondition = emitCondition;
}
private int nPrecedingRulesToMatch; // default 1
private int nSubsequentRulesToMatch; // default 1
private boolean allPrecedingRules; // if false, ANY preceding rules
public final boolean isAllPrecedingRules() {
return allPrecedingRules;
}
public final void setAllPrecedingRules(final boolean allPrecedingRules) {
this.allPrecedingRules = allPrecedingRules;
}
private boolean allSubsequentRules; // if false, ANY subsequent rules
public final boolean isAllSubsequentRules() {
return allSubsequentRules;
}
public final void setAllSubsequentRules(final boolean allSubsequentRules) {
this.allSubsequentRules = allSubsequentRules;
}
private CommentFillString commentFillString;
public CommentFillString getCommentFillString() {
return commentFillString;
}
public void setCommentFillString(CommentFillString commentFillString) {
this.commentFillString = commentFillString;
}
// --------------------------------------------------- STATIC METHODS --------------------------------------------------
public static CommentRule readExternal(final Element item) {
final CommentRule result = new CommentRule();
final Attribute attr = RearrangerSettings.getAttribute(item, "commentText");
// backward compatibility. Comment text was formerly saved as an attribute.
// Newline characters were lost this way. Now comment text is saved as element text.
// If there's no text but there is an attribute, load the old format. It will be
// saved as element text next time IDEA is exited.
// Turns out that IDEA strips newlines in the element text. Maybe it's due to document
// formatting options. In any case, we have to escape newline characters.
String text = item.getText();
if (text == null || text.length() == 0) {
result.commentText = (attr == null ? "" : ((java.lang.String)attr.getValue()));
}
else {
result.commentText = unescape(text);
}
result.emitCondition = RearrangerSettings.getIntAttribute(item, "condition", 0);
result.nPrecedingRulesToMatch = RearrangerSettings.getIntAttribute(item, "nPrecedingRulesToMatch", 1);
result.nSubsequentRulesToMatch = RearrangerSettings.getIntAttribute(item, "nSubsequentRulesToMatch", 1);
result.allPrecedingRules = RearrangerSettings.getBooleanAttribute(item, "allPrecedingRules", true);
result.allSubsequentRules = RearrangerSettings.getBooleanAttribute(item, "allSubsequentRules", true);
result.commentFillString = CommentFillString.readExternal(item);
return result;
}
public static String unescape(String text) {
StringBuffer s = new StringBuffer(text);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '\\' && (i + 1 < s.length())) {
switch (s.charAt(i + 1)) {
case 'n':
s.setCharAt(i, '\n');
s.deleteCharAt(i + 1);
break;
case '\\':
s.deleteCharAt(i + 1);
break;
case 't':
s.setCharAt(i, '\t');
s.deleteCharAt(i + 1);
break;
case ' ':
s.deleteCharAt(i);
break;
}
}
}
return s.toString();
}
public static String escape(String s) {
StringBuffer sb = new StringBuffer(s);
// for reasons given in readExternal(), escape certain characters in the comment text.
for (int i = 0; i < sb.length(); i++) {
switch (sb.charAt(i)) {
case '\\':
case ' ':
sb.insert(i, '\\');
i++;
break;
case '\n':
sb.replace(i, i + 1, "\\n");
i++;
break;
case '\t':
sb.replace(i, i + 1, "\\t");
i++;
break;
}
}
return sb.toString();
}
// ---------------------------------------------------- CONSTRUCTORS ---------------------------------------------------
public CommentRule() {
commentText = "";
emitCondition = EMIT_ALWAYS;
nPrecedingRulesToMatch = 1;
nSubsequentRulesToMatch = 1;
allPrecedingRules = true;
allSubsequentRules = true;
commentFillString = new CommentFillString();
}
// ---------------------------------------------- GETTER / SETTER METHODS ----------------------------------------------
public String[] getAdditionalIconNames() {
return null;
}
public int getCommentCount() {
return (commentText != null && commentText.length() > 0) ? 1 : 0;
}
public final JPanel getCommentPanel() {
final JPanel commentPanel = new JPanel(new GridBagLayout());
final Border border = BorderFactory.createEtchedBorder();
commentPanel.setBorder(border);
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(4, 4, 4, 0);
final JLabel emitLabel = new JLabel("Emit comment:");
final JRadioButton alwaysButton = new JRadioButton("Always"),
whenButton = new JRadioButton("When");
final ButtonGroup group = new ButtonGroup();
group.add(alwaysButton);
group.add(whenButton);
if (emitCondition == 0) {
alwaysButton.setSelected(true);
}
else {
whenButton.setSelected(true);
}
commentPanel.add(emitLabel, constraints.weightedLastCol());
constraints.newRow();
constraints.insets = new Insets(0, 14, 0, 0);
commentPanel.add(alwaysButton, constraints.weightedLastCol());
constraints.newRow();
commentPanel.add(whenButton, constraints.weightedLastCol());
constraints.insets = new Insets(0, 24, 0, 4);
constraints.newRow();
final JPanel anyAllPreviousPanel = new AnyAllPanel(true);
commentPanel.add(anyAllPreviousPanel, constraints.weightedLastCol());
constraints.newRow();
constraints.insets = new Insets(0, 24, 10, 4);
final JPanel anyAllSubsequentPanel = new AnyAllPanel(false);
commentPanel.add(anyAllSubsequentPanel, constraints.weightedLastCol());
anyAllPreviousPanel.setEnabled(emitCondition > 0);
anyAllSubsequentPanel.setEnabled(emitCondition > 0);
final JLabel commentLabel = new JLabel("Comment separator text:");
constraints.insets = new Insets(4, 4, 4, 4);
constraints.newRow();
commentPanel.add(commentLabel, constraints.weightedLastCol());
final JTextArea commentArea = new JTextArea(4, 40);
commentArea.setText(getCommentText());
constraints.weightedNewRow();
final JScrollPane scrollPane = new JScrollPane(commentArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
commentPanel.add(scrollPane, constraints.weightedLastCol());
constraints.newRow();
final JPanel cfsPanel = commentFillString.getCommentFillStringPanel();
final JLabel fillStringLabel = new JLabel("Fill string:");
fillStringLabel.setToolTipText("Occurrences of %FS% in the comment separator text will be replaced with equal \n" +
"amounts of the fill string, replicated to make the comment end at the specified column");
commentPanel.add(cfsPanel, constraints.weightedLastCol());
alwaysButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (alwaysButton.isSelected()) {
emitCondition = EMIT_ALWAYS;
anyAllPreviousPanel.setEnabled(false);
anyAllSubsequentPanel.setEnabled(false);
}
}
});
whenButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (whenButton.isSelected()) {
anyAllPreviousPanel.setEnabled(true);
anyAllSubsequentPanel.setEnabled(true);
}
}
});
commentArea.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(final DocumentEvent e) {
setCommentText(commentArea.getText());
}
public void insertUpdate(final DocumentEvent e) {
setCommentText(commentArea.getText());
}
public void removeUpdate(final DocumentEvent e) {
setCommentText(commentArea.getText());
}
});
return commentPanel;
}
public String getDescriptiveString() {
final StringBuffer sb = new StringBuffer(commentText.trim());
if (sb.length() > 60) {
// attempt to shorten by removing duplicate (well, quadruplicate) characters.
for (int i = 0; i < sb.length() - 4; i++) {
if (sb.charAt(i) == sb.charAt(i + 1) &&
sb.charAt(i + 1) == sb.charAt(i + 2) &&
sb.charAt(i + 2) == sb.charAt(i + 3))
{
// we have at least 4 characters in a row. Shorten the entire sequence to
// a length of 4 characters and append the length.
int j = 0;
while (i + 4 < sb.length() && sb.charAt(i) == sb.charAt(i + 4)) {
j++;
sb.deleteCharAt(i + 4);
}
if (j > 3) {
sb.insert(i + 4, "<" + j + ">");
}
else {
// compression is quite small, so just output the actual characters.
while (j-- > 0) {
sb.insert(i + 4, sb.charAt(i));
}
}
}
}
}
if (sb.length() > 60) {
sb.delete(60, sb.length());
sb.append("...");
}
String condition = "";
switch (emitCondition) {
case EMIT_ALWAYS:
break;
case EMIT_IF_ITEMS_MATCH_PRECEDING_RULE:
condition = " when " + precedingRuleString();
break;
case EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE:
condition = " when " + subsequentRuleString();
break;
case EMIT_IF_ITEMS_MATCH_SURROUNDING_RULES:
condition = " when " + precedingRuleString() + ", and " + subsequentRuleString();
}
return ("Comment (" + sb.toString() + ")" + condition);
}
private String precedingRuleString() {
return (nPrecedingRulesToMatch == 1) ? "preceding rule is matched" :
(allPrecedingRules ? "all" : "any") +
" of preceding " + (nPrecedingRulesToMatch) + " rules are matched";
}
private String subsequentRuleString() {
return (nSubsequentRulesToMatch == 1) ? "subsequent rule is matched" :
(allSubsequentRules ? "all" : "any") +
" of subsequent " + (nSubsequentRulesToMatch) + " rules are matched";
}
public final String getExpandedCommentText() {
return commentFillString.getExpandedCommentText(commentText);
}
private String getName() {
return commentText.trim();
}
public int getPriority() {
return -1; // Comments never match anything, so any priority will do.
}
public void setPriority(int priority) {
// does nothing
}
public String getTypeIconName() {
return "nodes/J2eeParameter";
}
public final boolean isAlphabetize() {
throw new UnsupportedOperationException("CommentRule.isAlphabetize() not implemented");
}
public final void setnPrecedingRulesToMatch(final int nPrecedingRulesToMatch) {
this.nPrecedingRulesToMatch = nPrecedingRulesToMatch;
}
public final void setnSubsequentRulesToMatch(final int nSubsequentRulesToMatch) {
this.nSubsequentRulesToMatch = nSubsequentRulesToMatch;
}
// ------------------------------------------------- CANONICAL METHODS -------------------------------------------------
public final boolean equals(final Object object) {
if (!(object instanceof CommentRule)) return false;
final CommentRule c = (CommentRule)object;
return commentText.equals(c.commentText) &&
emitCondition == c.emitCondition &&
nPrecedingRulesToMatch == c.nPrecedingRulesToMatch &&
nSubsequentRulesToMatch == c.nSubsequentRulesToMatch &&
allPrecedingRules == c.allPrecedingRules &&
allSubsequentRules == c.allSubsequentRules &&
commentFillString.equals(c.commentFillString);
}
public final String toString() {
return getDescriptiveString();
}
// ================================================= INTERFACE METHODS =================================================
// ---------------------------------------------- Interface AttributeGroup ---------------------------------------------
public final /*CommentRule*/AttributeGroup deepCopy() {
final CommentRule comment = new CommentRule();
comment.commentText = commentText;
comment.emitCondition = emitCondition;
comment.nPrecedingRulesToMatch = nPrecedingRulesToMatch;
comment.nSubsequentRulesToMatch = nSubsequentRulesToMatch;
comment.allPrecedingRules = allPrecedingRules;
comment.allSubsequentRules = allSubsequentRules;
comment.commentFillString = commentFillString.deepCopy();
return comment;
}
public final void writeExternal(final Element parent) {
final Element me = new Element("Comment");
me.setText(escape(commentText));
me.setAttribute("condition", "" + emitCondition);
me.setAttribute("nPrecedingRulesToMatch", "" + nPrecedingRulesToMatch);
me.setAttribute("nSubsequentRulesToMatch", "" + nSubsequentRulesToMatch);
me.setAttribute("allPrecedingRules", "" + allPrecedingRules);
me.setAttribute("allSubsequentRules", "" + allSubsequentRules);
commentFillString.writeExternal(me);
parent.getChildren().add(me);
}
// --------------------------------------------- Interface IFilePopupEntry ---------------------------------------------
public JLabel getPopupEntryText(RearrangerSettings settings) {
String s = commentText.trim();
if (commentFillString != null && commentFillString.getFillString().length() > 0) {
s = commentFillString.getExpandedCommentText(s);
}
return new JLabel(s);
}
// ------------------------------------------- Interface IPopupTreeRangeEntry ------------------------------------------
public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) {
DefaultMutableTreeNode myNode = new RearrangerTreeNode(this, getName());
parent.add(myNode);
return myNode;
}
// -------------------------------------------------- Interface IRule --------------------------------------------------
public IRuleInstance createRuleInstance() {
return CommentRuleInstanceFactory.buildCommentRuleInstance(this);
}
public boolean isMatch(RangeEntry rangeEntry) {
return false; // comment rules match no entries -- they're just placeholders to generate comments.
}
public boolean commentsMatchGlobalPattern(String pattern) {
return commentText.matches(pattern);
}
public List<String> getOffendingPatterns(String pattern) {
List<String> result = new ArrayList<String>(1);
result.add(commentText);
return result;
}
public void addCommentPatternsToList(List<String> list) {
if (commentText != null && commentText.length() > 0) {
String esc = RegexUtil.escape(commentText);
String fsp = commentFillString.getFillStringPattern();
esc = esc.replaceAll("%FS%", fsp);
list.add(esc);
}
}
// --------------------------------------------------- OTHER METHODS ---------------------------------------------------
public int getnPrecedingRulesToMatch() {
return nPrecedingRulesToMatch;
}
public final int getnSubsequentRulesToMatch() {
return nSubsequentRulesToMatch;
}
// --------------------------------------------------- INNER CLASSES ---------------------------------------------------
final class AnyAllPanel extends JPanel {
final JCheckBox anyAllCheckbox;
final JComboBox anyAllComboBox;
final JLabel anyAllLabel;
final JFormattedTextField anyAllPrevNumber;
final JLabel rulesLabel;
/**
* Return a JPanel that allows user to specify checkbox (enable rule), Any/All combo box, "of the "
* "preceding"/"subsequent", text field for integer >= 1, "rules"
*
* @param preceding true if handling "preceding" rules, otherwise "subsequent" rules
*/
AnyAllPanel(final boolean preceding) {
super(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST);
constraints.lastRow();
constraints.fill = GridBagConstraints.BOTH;
anyAllCheckbox = new JCheckBox("items match");
anyAllCheckbox.setSelected((emitCondition & (preceding ? 1 : 2)) > 0);
anyAllComboBox = new JComboBox(new String[]{"any", "all"});
anyAllComboBox.setSelectedIndex(preceding ? (allPrecedingRules ? 1 : 0)
: (allSubsequentRules ? 1 : 0));
Dimension d = anyAllComboBox.getPreferredSize();
d.width += 3; // make room for "any", if "all" is narrower and is first selection.
anyAllComboBox.setPreferredSize(d);
anyAllLabel = new JLabel();
anyAllLabel.setText("of the subsequent"); // calculate max size
d = anyAllLabel.getPreferredSize();
anyAllLabel.setText(preceding ? "of the preceding" : "of the subsequent");
anyAllLabel.setMinimumSize(d);
anyAllLabel.setPreferredSize(d);
final NumberFormat integerInstance = NumberFormat.getIntegerInstance();
integerInstance.setMaximumIntegerDigits(2);
integerInstance.setMinimumIntegerDigits(1);
anyAllPrevNumber = new JFormattedTextField(integerInstance);
anyAllPrevNumber.setValue(new Integer("88"));
d = anyAllPrevNumber.getPreferredSize();
d.width += 3;
anyAllPrevNumber.setPreferredSize(d);
anyAllPrevNumber.setValue(preceding ? nPrecedingRulesToMatch : nSubsequentRulesToMatch);
anyAllPrevNumber.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
rulesLabel = new JLabel("rules");
constraints.insets = new Insets(0, 10, 0, 0);
add(anyAllCheckbox, constraints.nextCol());
constraints.insets = new Insets(0, 0, 0, 0);
add(anyAllComboBox, constraints.nextCol());
constraints.insets = new Insets(0, 4, 0, 0);
add(anyAllLabel, constraints.nextCol());
constraints.insets = new Insets(0, 4, 0, 0);
add(anyAllPrevNumber, constraints.nextCol());
add(rulesLabel, constraints.weightedLastCol());
anyAllComboBox.setEnabled(anyAllCheckbox.isSelected());
anyAllLabel.setEnabled(anyAllCheckbox.isSelected());
anyAllPrevNumber.setEnabled(anyAllCheckbox.isSelected());
rulesLabel.setEnabled(anyAllCheckbox.isSelected());
anyAllCheckbox.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (anyAllCheckbox.isSelected()) {
emitCondition |= (preceding ? 1 : 2);
}
else {
emitCondition &= (preceding ? ~1 : ~2);
}
anyAllComboBox.setEnabled(anyAllCheckbox.isSelected());
anyAllLabel.setEnabled(anyAllCheckbox.isSelected());
anyAllPrevNumber.setEnabled(anyAllCheckbox.isSelected());
rulesLabel.setEnabled(anyAllCheckbox.isSelected());
}
});
anyAllComboBox.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final int s = anyAllComboBox.getSelectedIndex();
if (preceding) {
allPrecedingRules = (s == 1);
}
else {
allSubsequentRules = (s == 1);
}
}
});
anyAllPrevNumber.addPropertyChangeListener("value", new PropertyChangeListener() {
public void propertyChange(final PropertyChangeEvent evt) {
int n = ((Number)anyAllPrevNumber.getValue()).intValue();
if (n <= 0) {
n = 1;
anyAllPrevNumber.setValue(n);
}
if (preceding) {
nPrecedingRulesToMatch = n;
}
else {
nSubsequentRulesToMatch = n;
}
}
});
}
public final void setEnabled(final boolean enable) {
anyAllCheckbox.setEnabled(enable);
anyAllComboBox.setEnabled(anyAllCheckbox.isSelected() && enable);
anyAllLabel.setEnabled(anyAllCheckbox.isSelected() && enable);
anyAllPrevNumber.setEnabled(anyAllCheckbox.isSelected() && enable);
rulesLabel.setEnabled(anyAllCheckbox.isSelected() && enable);
}
}
}
@@ -0,0 +1,131 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings;
import org.jdom.Element;
/** Contains a single "force N blank lines before/after" some brace. */
public class ForceBlankLineSetting {
public static final int CLASS_OBJECT = 0;
public static final int METHOD_OBJECT = 1;
public static final int EOF_OBJECT = 2;
boolean force;
int nBlankLines;
final boolean before; // false => after
final boolean openBrace; // false => close brace
final int object;
final String name;
public ForceBlankLineSetting(boolean before, boolean openBrace, int object, String name) {
this.before = before;
this.openBrace = openBrace;
this.object = object;
this.name = name;
}
public boolean isForce() {
return force;
}
public void setForce(boolean force) {
this.force = force;
}
public int getnBlankLines() {
return nBlankLines;
}
public void setnBlankLines(int nBlankLines) {
this.nBlankLines = nBlankLines;
}
public boolean isBefore() {
return before;
}
public boolean isOpenBrace() {
return openBrace;
}
public int getObject() {
return object;
}
public boolean equals(final Object obj) {
if (!(obj instanceof ForceBlankLineSetting)) return false;
final ForceBlankLineSetting fbls = (ForceBlankLineSetting)obj;
if (fbls.force != force) return false;
if (fbls.nBlankLines != nBlankLines) return false;
if (fbls.before != before) return false;
if (fbls.openBrace != openBrace) return false;
if (fbls.object != object) return false;
return true;
}
public final ForceBlankLineSetting deepCopy() {
final ForceBlankLineSetting result = new ForceBlankLineSetting(before, openBrace, object, name);
result.force = force;
result.nBlankLines = nBlankLines;
return result;
}
/**
* Read the contents of this object from the JDOM element.
*
* @param entry JDOM element which contains setting values as attributes.
*/
public static ForceBlankLineSetting readExternal(final Element entry,
boolean before,
boolean openBrace,
int object,
String name)
{
ForceBlankLineSetting fbls;
Element fblsElement = entry.getChild(name);
boolean force = RearrangerSettings.getBooleanAttribute(fblsElement, "Force", false);
int nBlankLines = RearrangerSettings.getIntAttribute(fblsElement, "nBlankLines", 1);
fbls = new ForceBlankLineSetting(before, openBrace, object, name);
fbls.setForce(force);
fbls.setnBlankLines(nBlankLines);
return fbls;
}
public final void writeExternal(final Element entry) {
final Element fblsElement = new Element(name);
entry.getChildren().add(fblsElement);
fblsElement.setAttribute("Force", Boolean.valueOf(force).toString());
fblsElement.setAttribute("nBlankLines", "" + nBlankLines);
}
public String toString() {
return name + ": " + (before ? "before " : "after ") +
getObjectName() +
(openBrace ? " open brace" : " close brace") +
(force ? ", force " + nBlankLines + " lines" : ", leave intact");
}
public String getObjectName() {
return (object == CLASS_OBJECT ? "class" : "method");
}
}
@@ -0,0 +1,386 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings;
import com.wrq.rearranger.configuration.*;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* Contains settings pertinent to a single related-by-name method setting. A primary field is
* specified
*/
public class PrimaryMethodSetting
implements IListManagerObject
{
/** Description for a single related-by-name method setting. */
String description;
/**
* Regular expression which method name must match. If the method is to be matched to a field, there must be
* at least one capture group (parenthesized subexpression) which will be treated as the field.
* In the case of a traditional getter method, this pattern is "get(\w+)".
*/
String methodNamePattern;
/**
* The number of the capture group in methodNamePattern which corresponds to the field name. If the
* methodNamePattern is "get(\w+)", then the fieldCaptureGroupNumber is 1.
*/
int fieldCaptureGroupNumber;
/** number of parameters the primary method must have. In the case of a traditional getter method, this is zero. */
int numParameters;
/**
* regular expression pattern of the type which primary method must return.
* In the case of a traditional getter method, this is the field type. One substitution is available:
* <pre>
* %FT% field type
* </pre>
*/
String methodTypePattern;
/**
* regular expression pattern of the attributes of the method.
* In the case of a traditional getter method, this is ".*public.*" (i.e., any public method).
*/
String methodAttributePattern;
/**
* pattern of method body (excluding comments and newline characters). Substitutions are available as follows:
* <pre>
* %FN% field name
* %FT% field type (if field is valid field, else empty string)
* %MT% method return type
* %P1% parameter 1 name (%P2%, %P3% etc for additional parameters)
* %T1% parameter 1 type name
* </pre>
*/
String body;
/** list of secondary method configurations, e.g. for "set" and "is". */
ArrayList<SecondaryMethodSetting> secondaryMethodList = new ArrayList<SecondaryMethodSetting>();
public PrimaryMethodSetting() {
methodNamePattern = "get(\\w+)";
fieldCaptureGroupNumber = 1;
numParameters = 0;
methodTypePattern = "%FT%";
methodAttributePattern = ".*public.*";
body = "{\\s*return\\s*%fn%;\\s*}";
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getMethodNamePattern() {
return methodNamePattern;
}
public void setMethodNamePattern(String methodNamePattern) {
this.methodNamePattern = methodNamePattern;
}
public int getFieldCaptureGroupNumber() {
return fieldCaptureGroupNumber;
}
public void setFieldCaptureGroupNumber(int fieldCaptureGroupNumber) {
this.fieldCaptureGroupNumber = fieldCaptureGroupNumber;
}
public int getNumParameters() {
return numParameters;
}
public void setNumParameters(int numParameters) {
this.numParameters = numParameters;
}
public String getMethodTypePattern() {
return methodTypePattern;
}
public void setMethodTypePattern(String methodTypePattern) {
this.methodTypePattern = methodTypePattern;
}
public String getMethodAttributePattern() {
return methodAttributePattern;
}
public void setMethodAttributePattern(String methodAttributePattern) {
this.methodAttributePattern = methodAttributePattern;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public ArrayList<SecondaryMethodSetting> getSecondaryMethodList() {
return secondaryMethodList;
}
public String toString() {
return description;
}
public boolean equals(Object obj) {
if (!(obj instanceof PrimaryMethodSetting)) return false;
PrimaryMethodSetting pms = (PrimaryMethodSetting)obj;
if (!pms.description.equals(description)) return false;
if (!pms.methodNamePattern.equals(methodNamePattern)) return false;
if (pms.fieldCaptureGroupNumber != fieldCaptureGroupNumber) return false;
if (pms.numParameters != numParameters) return false;
if (!pms.methodTypePattern.equals(methodTypePattern)) return false;
if (!pms.methodAttributePattern.equals(methodAttributePattern)) return false;
if (!pms.body.equals(body)) return false;
return true;
}
public JPanel getPanel() {
IListManagerObjectFactory lmof = new IListManagerObjectFactory() {
public IListManagerObject create(String name) {
SecondaryMethodSetting sms = new SecondaryMethodSetting();
sms.setDescription(name);
return sms;
}
public List/*<? extends IListManagerObject>*/ getObjectList() {
return secondaryMethodList;
}
};
ListManager Lmgr = new ListManager(lmof, "Description:");
JPanel pmsPanel = new JPanel(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.NONE;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0.0d;
constraints.weighty = 0.0d;
constraints.gridy = constraints.gridx = 0;
constraints.insets = new Insets(3, 3, 3, 3);
pmsPanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
"Primary (\"Getter\") Method Criteria"));
constraints.gridwidth = 1;
constraints.gridy++;
JLabel methodNamePatternLabel = new JLabel("Method name:");
methodNamePatternLabel.setToolTipText(
"Regular expression which method name must match. " +
"If the method is to be matched to a field, there must be\n" +
" at least one capture group (parenthesized subexpression) which will be treated as the field.\n" +
" In the case of a traditional getter method, this pattern is \"get(\\w+)\".");
pmsPanel.add(methodNamePatternLabel, constraints);
constraints.gridx++;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = .5;
StringTextField primaryPrefixText = new StringTextField() {
public void setValue(String value) {
setMethodNamePattern(value);
}
public String getValue() {
return getMethodNamePattern();
}
};
pmsPanel.add(primaryPrefixText, constraints);
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0;
constraints.gridx++;
JLabel fieldCaptureGroupLabel = new JLabel("Field capture group:");
fieldCaptureGroupLabel.setToolTipText(
"The number of the capture group in methodNamePattern which corresponds to the field name. If the\n" +
" methodNamePattern is \"get(\\w+)\", then the fieldCaptureGroupNumber is 1."
);
pmsPanel.add(fieldCaptureGroupLabel, constraints);
IntTextField itf = new IntTextField(
new IntTextField.IGetSet() {
public void set(int value) {
fieldCaptureGroupNumber = value;
}
public int get() {
return fieldCaptureGroupNumber;
}
},
null, null
);
constraints.gridx++;
pmsPanel.add(itf, constraints);
constraints.gridx++;
JLabel nParamLabel = new JLabel("Number of parameters:");
nParamLabel.setToolTipText(
"number of parameters the primary method must have.\n" +
"In the case of a traditional getter method, this is zero.");
pmsPanel.add(nParamLabel, constraints);
constraints.gridx++;
IntTextField nParamText = new IntTextField(
new IntTextField.IGetSet() {
public void set(int value) {
numParameters = value;
}
public int get() {
return numParameters;
}
}, null, null);
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridwidth = GridBagConstraints.REMAINDER;
pmsPanel.add(nParamText, constraints);
constraints.gridx = 0;
constraints.gridy++;
constraints.gridwidth = 1;
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
JLabel returnTypeLabel = new JLabel("Return type:");
returnTypeLabel.setToolTipText(
"regular expression pattern of the type which primary method must return.\n" +
" In the case of a traditional getter method, this is the field type. One substitution is available:\n" +
" * %FT% field type");
pmsPanel.add(returnTypeLabel, constraints);
constraints.gridx++;
constraints.weightx = .5;
constraints.fill = GridBagConstraints.HORIZONTAL;
StringTextField returnTypeField = new StringTextField() {
public void setValue(String value) {
methodTypePattern = value;
}
public String getValue() {
return methodTypePattern;
}
};
pmsPanel.add(returnTypeField, constraints);
constraints.fill = GridBagConstraints.NONE;
constraints.gridx++;
constraints.weightx = 0;
JLabel methodAttributeLabel = new JLabel("Method attributes:");
methodAttributeLabel.setToolTipText("Protection level or other attributes for the method.\n" +
"In the case of a getter method, this is usually \".*public.*\".");
pmsPanel.add(methodAttributeLabel, constraints);
StringTextField methodAttributeField = new StringTextField() {
public void setValue(String value) {
methodAttributePattern = value;
}
public String getValue() {
return methodAttributePattern;
}
};
constraints.gridx++;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = .5;
constraints.fill = GridBagConstraints.HORIZONTAL;
pmsPanel.add(methodAttributeField, constraints);
constraints.gridx++;
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.gridy++;
constraints.gridx = 0;
JLabel bodyLabel = new JLabel("Body:");
bodyLabel.setToolTipText("regular expression pattern of method body (excluding comments and newline characters).\n" +
"Substitutions are available as follows:\n" +
" %FN% field name\n" +
" %FT% field type (if field is valid field, else empty string)\n" +
" %MT% method return type\n" +
" %P1% parameter 1 name (%P2%, %P3% etc for additional parameters)\n" +
" %T1% parameter 1 type name");
constraints.gridwidth = 1;
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
pmsPanel.add(bodyLabel, constraints);
constraints.gridx++;
StringTextArea bodyField = new StringTextArea() {
public void setValue(String value) {
body = value;
}
public String getValue() {
return body;
}
};
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = 1;
constraints.weighty = .35;
constraints.fill = GridBagConstraints.BOTH;
JScrollPane sp = new JScrollPane(bodyField);
pmsPanel.add(sp, constraints);
constraints.gridx = 0;
constraints.gridy++;
constraints.gridheight = GridBagConstraints.REMAINDER;
constraints.fill = GridBagConstraints.NONE;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1;
constraints.weighty = .65;
final JPanel pane = Lmgr.getPane();
pane.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Related Methods"));
pmsPanel.add(pane, constraints);
return pmsPanel;
}
public IListManagerObject deepcopy() {
PrimaryMethodSetting pms = new PrimaryMethodSetting();
pms.description = getDescription();
pms.methodNamePattern = getMethodNamePattern();
pms.fieldCaptureGroupNumber = getFieldCaptureGroupNumber();
pms.numParameters = getNumParameters();
pms.methodTypePattern = getMethodTypePattern();
pms.methodAttributePattern = getMethodAttributePattern();
pms.body = getBody();
pms.secondaryMethodList = new ArrayList<SecondaryMethodSetting>();
for (SecondaryMethodSetting sms : secondaryMethodList) {
pms.secondaryMethodList.add((SecondaryMethodSetting)sms.deepcopy());
}
return pms;
}
public static void main(String[] args) {
PrimaryMethodSetting ms = new PrimaryMethodSetting();
final JDialog frame = new JDialog((Frame)null, "SwingApplication");
final GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1.0d;
constraints.weighty = 1.0d;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.gridx = 0;
constraints.gridy = 0;
frame.getContentPane().setLayout(new GridBagLayout());
frame.getContentPane().add(ms.getPanel(), constraints);
//Finish setting up the frame, and show it.
frame.pack();
frame.setResizable(true);
frame.setModal(true);
frame.setVisible(true);
}
}
@@ -0,0 +1,683 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings;
import com.intellij.openapi.diagnostic.Logger;
import com.wrq.rearranger.Rearranger;
import com.wrq.rearranger.settings.attributeGroups.AttributeGroup;
import com.wrq.rearranger.settings.attributeGroups.ClassAttributes;
import com.wrq.rearranger.settings.attributeGroups.GetterSetterDefinition;
import com.wrq.rearranger.settings.attributeGroups.ItemAttributes;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
/**
* Holds two lists of rearrangement settings, one for the outer level classes, the other for class members. Each
* list contains objects of type CommonAttributes.
*/
public final class RearrangerSettings {
// ------------------------------ FIELDS ------------------------------
// BEGINNING OF FIELDS
private static final Logger logger = Logger.getInstance("#" + RearrangerSettings.class.getName());
public static final int OVERLOADED_ORDER_RETAIN_ORIGINAL = 0;
public static final int OVERLOADED_ORDER_ASCENDING_PARAMETERS = 1;
public static final int OVERLOADED_ORDER_DESCENDING_PARAMETERS = 2;
private final List<AttributeGroup> itemOrderAttributeList;
private final List<AttributeGroup> classOrderAttributeList;
private RelatedMethodsSettings relatedMethodsSettings;
private boolean keepGettersSettersTogether;
private boolean keepGettersSettersWithProperty;
private boolean keepOverloadedMethodsTogether;
private String globalCommentPattern;
private boolean askBeforeRearranging;
private boolean rearrangeInnerClasses;
private boolean showParameterTypes;
private boolean showParameterNames;
private boolean showFields;
private boolean showTypeAfterMethod;
private boolean showRules;
private boolean showMatchedRules;
private boolean showComments;
private ForceBlankLineSetting afterClassLBrace;
private ForceBlankLineSetting afterClassRBrace;
private ForceBlankLineSetting beforeClassRBrace;
private ForceBlankLineSetting beforeMethodLBrace;
private ForceBlankLineSetting afterMethodLBrace;
private ForceBlankLineSetting afterMethodRBrace;
private ForceBlankLineSetting beforeMethodRBrace;
private boolean removeBlanksInsideCodeBlocks;
private ForceBlankLineSetting newlinesAtEOF;
private int overloadedOrder;
private GetterSetterDefinition defaultGSDefinition;
private List<PrimaryMethodSetting> primaryMethodList;
// -------------------------- STATIC METHODS --------------------------
static public int getIntAttribute(final Element me, final String attr) {
return getIntAttribute(me, attr, 0);
}
static public boolean getBooleanAttribute(final Element me, final String attr) {
return getBooleanAttribute(me, attr, false);
}
public static RearrangerSettings getDefaultSettings() {
logger.debug("enter loadDefaultSettings");
URL settingsURL = Rearranger.class.getClassLoader().getResource("com/wrq/rearranger/defaultConfiguration.xml");
logger.debug("settings URL=" + settingsURL.getFile());
try {
InputStream is = settingsURL.openStream();
return getSettingsFromStream(is);
}
catch (IOException e) {
logger.debug("getDefaultSettings:" + e);
return null;
}
}
public static RearrangerSettings getSettingsFromStream(InputStream is) {
Document document = null;
try {
SAXBuilder builder = new SAXBuilder();
document = builder.build(is);
}
catch (JDOMException jde) {
logger.debug("JDOM exception building document:" + jde);
return null;
}
catch (IOException e) {
logger.debug("I/O exception building document:" + e);
return null;
}
finally {
if (is != null) {
try {
is.close();
}
catch (IOException e) {
}
}
}
Element app = document.getRootElement();
Element component = null;
if (app.getName().equals("application")) {
ListIterator li = app.getChildren().listIterator();
while (li.hasNext())
// for (Element child : (List)((java.util.List)app.getChildren()))
{
Element child = (Element)li.next();
if (child.getName().equals("component") &&
child.getAttribute("name") != null &&
child.getAttribute("name").getValue().equals(Rearranger.COMPONENT_NAME))
{
component = child;
break;
}
}
}
else {
if (app.getName().equals("component") &&
app.getAttribute("name") != null &&
app.getAttribute("name").getValue().equals(Rearranger.COMPONENT_NAME))
{
component = app;
}
}
if (component != null) {
Element rearranger = component.getChild(Rearranger.COMPONENT_NAME);
if (rearranger != null) {
RearrangerSettings rs = new RearrangerSettings();
rs.readExternal(rearranger);
return rs;
}
}
return null;
}
// Level 1 methods
/** @param entry JDOM element named "Rearranger" which contains setting values as attributes. */
public final void readExternal(final Element entry) {
final Element items = entry.getChild("Items");
final Element classes = entry.getChild("Classes");
final List itemList = items.getChildren();
final List classList = classes.getChildren();
ListIterator li;
li = itemList.listIterator();
while (li.hasNext())
// for (Element element : itemList)
{
Element element = (Element)li.next();
itemOrderAttributeList.add(((com.wrq.rearranger.settings.attributeGroups.AttributeGroup)ItemAttributes.readExternal(element)));
}
li = classList.listIterator();
// for (Element element : classList)
while (li.hasNext()) {
Element element = (Element)li.next();
classOrderAttributeList.add(((com.wrq.rearranger.settings.attributeGroups.AttributeGroup)ClassAttributes.readExternal(element)));
}
final Element gsd = entry.getChild("DefaultGetterSetterDefinition");
defaultGSDefinition = GetterSetterDefinition.readExternal(gsd);
final Element relatedItems = entry.getChild("RelatedMethods");
relatedMethodsSettings = RelatedMethodsSettings.readExternal(relatedItems);
keepGettersSettersTogether = getBooleanAttribute(entry, "KeepGettersSettersTogether", true);
keepGettersSettersWithProperty = getBooleanAttribute(entry, "KeepGettersSettersWithProperty", false);
keepOverloadedMethodsTogether = getBooleanAttribute(entry, "KeepOverloadedMethodsTogether", true);
final Attribute attr = RearrangerSettings.getAttribute(entry, "globalCommentPattern");
askBeforeRearranging = getBooleanAttribute(entry, "ConfirmBeforeRearranging", false);
rearrangeInnerClasses = getBooleanAttribute(entry, "RearrangeInnerClasses", false);
globalCommentPattern = (attr == null ? "" : ((java.lang.String)attr.getValue()));
overloadedOrder = getIntAttribute(entry, "overloadedOrder", OVERLOADED_ORDER_RETAIN_ORIGINAL);
showParameterTypes = getBooleanAttribute(entry, "ShowParameterTypes", true);
showParameterNames = getBooleanAttribute(entry, "ShowParameterNames", true);
showFields = getBooleanAttribute(entry, "ShowFields", true);
showRules = getBooleanAttribute(entry, "ShowRules", false);
showMatchedRules = getBooleanAttribute(entry, "ShowMatchedRules", false);
showComments = getBooleanAttribute(entry, "ShowComments", false);
showTypeAfterMethod = getBooleanAttribute(entry, "ShowTypeAfterMethod", true);
removeBlanksInsideCodeBlocks = getBooleanAttribute(entry, "RemoveBlanksInsideCodeBlocks", false);
afterClassLBrace = ForceBlankLineSetting.readExternal(entry, false, true, ForceBlankLineSetting.CLASS_OBJECT, "AfterClassLBrace");
afterClassRBrace = ForceBlankLineSetting.readExternal(entry, false, false, ForceBlankLineSetting.CLASS_OBJECT, "AfterClassRBrace");
beforeClassRBrace = ForceBlankLineSetting.readExternal(entry, true, false, ForceBlankLineSetting.CLASS_OBJECT, "BeforeClassRBrace");
beforeMethodLBrace = ForceBlankLineSetting.readExternal(entry, true, true, ForceBlankLineSetting.METHOD_OBJECT, "BeforeMethodLBrace");
afterMethodLBrace = ForceBlankLineSetting.readExternal(entry, false, true, ForceBlankLineSetting.METHOD_OBJECT, "AfterMethodLBrace");
afterMethodRBrace = ForceBlankLineSetting.readExternal(entry, false, false, ForceBlankLineSetting.METHOD_OBJECT, "AfterMethodRBrace");
beforeMethodRBrace = ForceBlankLineSetting.readExternal(entry, true, false, ForceBlankLineSetting.METHOD_OBJECT, "BeforeMethodRBrace");
newlinesAtEOF = ForceBlankLineSetting.readExternal(entry, false, false, ForceBlankLineSetting.EOF_OBJECT, "NewlinesAtEOF");
}
// Level 2 methods
static public Attribute getAttribute(Element element, String attributeName) {
if (element == null) return null;
return element.getAttribute(attributeName);
}
static public int getIntAttribute(final Element item, final String attributeName, int defaultValue) {
if (item == null) return defaultValue;
final Attribute a = item.getAttribute(attributeName);
if (a == null) return defaultValue;
final String r = a.getValue();
if (r == null) return defaultValue;
if (r.length() == 0) return defaultValue;
return Integer.parseInt(r);
}
static public boolean getBooleanAttribute(final Element me, final String attr, boolean defaultValue) {
if (me == null) return defaultValue;
final Attribute a = me.getAttribute(attr);
if (a == null) return defaultValue;
final String r = a.getValue();
if (r == null) return defaultValue;
return (r.equalsIgnoreCase("true"));
}
public static RearrangerSettings getSettingsFromFile(File f) {
try {
return getSettingsFromStream(new FileInputStream(f));
}
catch (FileNotFoundException e) {
logger.debug("getSettingsFromFile:" + e);
}
return null;
}
// --------------------------- CONSTRUCTORS ---------------------------
// END OF ALL FIELDS
public RearrangerSettings() {
itemOrderAttributeList = new ArrayList<AttributeGroup>();
classOrderAttributeList = new ArrayList<AttributeGroup>();
relatedMethodsSettings = new RelatedMethodsSettings();
keepGettersSettersTogether = false;
keepGettersSettersWithProperty = false;
keepOverloadedMethodsTogether = false;
globalCommentPattern = "";
overloadedOrder = OVERLOADED_ORDER_RETAIN_ORIGINAL;
askBeforeRearranging = false;
rearrangeInnerClasses = false;
showParameterTypes = true;
showParameterNames = false;
showFields = true;
showTypeAfterMethod = true;
showRules = false;
showMatchedRules = false;
showComments = false;
removeBlanksInsideCodeBlocks = false;
afterClassLBrace = new ForceBlankLineSetting(false, true, ForceBlankLineSetting.CLASS_OBJECT, "AfterClassLBrace");
afterClassRBrace = new ForceBlankLineSetting(false, false, ForceBlankLineSetting.CLASS_OBJECT, "AfterClassRBrace");
beforeClassRBrace = new ForceBlankLineSetting(true, false, ForceBlankLineSetting.CLASS_OBJECT, "BeforeClassRBrace");
beforeMethodLBrace = new ForceBlankLineSetting(true, true, ForceBlankLineSetting.METHOD_OBJECT, "BeforeMethodLBrace");
afterMethodLBrace = new ForceBlankLineSetting(false, true, ForceBlankLineSetting.METHOD_OBJECT, "AfterMethodLBrace");
beforeMethodRBrace = new ForceBlankLineSetting(true, false, ForceBlankLineSetting.METHOD_OBJECT, "BeforeMethodRBrace");
afterMethodRBrace = new ForceBlankLineSetting(false, false, ForceBlankLineSetting.METHOD_OBJECT, "AfterMethodRBrace");
newlinesAtEOF = new ForceBlankLineSetting(false, false, ForceBlankLineSetting.EOF_OBJECT, "NewlinesAtEOF");
defaultGSDefinition = new GetterSetterDefinition();
primaryMethodList = new LinkedList<PrimaryMethodSetting>();
}
// --------------------- GETTER / SETTER METHODS ---------------------
public ForceBlankLineSetting getAfterClassLBrace() {
return afterClassLBrace;
}
public ForceBlankLineSetting getAfterClassRBrace() {
return afterClassRBrace;
}
public ForceBlankLineSetting getBeforeMethodLBrace() {
return beforeMethodLBrace;
}
public ForceBlankLineSetting getAfterMethodLBrace() {
return afterMethodLBrace;
}
public ForceBlankLineSetting getAfterMethodRBrace() {
return afterMethodRBrace;
}
public ForceBlankLineSetting getBeforeClassRBrace() {
return beforeClassRBrace;
}
public ForceBlankLineSetting getBeforeMethodRBrace() {
return beforeMethodRBrace;
}
public final List<AttributeGroup> getClassOrderAttributeList() {
return classOrderAttributeList;
}
public GetterSetterDefinition getDefaultGSDefinition() {
return defaultGSDefinition;
}
// Level 1 methods
public String getGlobalCommentPattern() {
return globalCommentPattern;
}
// Level 2 methods
public void setGlobalCommentPattern(String globalCommentPattern) {
this.globalCommentPattern = globalCommentPattern;
}
// end of Level 2 methods
// end of Level 1 methods
public final List<AttributeGroup> getItemOrderAttributeList() {
return itemOrderAttributeList;
}
public ForceBlankLineSetting getNewlinesAtEOF() {
return newlinesAtEOF;
}
// Level 1 methods
public int getOverloadedOrder() {
return overloadedOrder;
}
// Level 2 methods
public void setOverloadedOrder(int overloadedOrder) {
this.overloadedOrder = overloadedOrder;
}
// end of Level 2 methods
// end of Level 1 methods
public RelatedMethodsSettings getExtractedMethodsSettings() {
return relatedMethodsSettings;
}
// Level 1 methods
public boolean isAskBeforeRearranging() {
return askBeforeRearranging;
}
// Level 2 methods
public void setAskBeforeRearranging(boolean askBeforeRearranging) {
this.askBeforeRearranging = askBeforeRearranging;
}
public boolean isKeepGettersSettersTogether() {
return keepGettersSettersTogether;
}
// Level 2 methods
public void setKeepGettersSettersTogether(boolean keepGettersSettersTogether) {
this.keepGettersSettersTogether = keepGettersSettersTogether;
}
public boolean isKeepGettersSettersWithProperty() {
return keepGettersSettersWithProperty;
}
public void setKeepGettersSettersWithProperty(boolean keepGettersSettersWithProperty) {
this.keepGettersSettersWithProperty = keepGettersSettersWithProperty;
}
// end of Level 2 methods
// end of Level 1 methods
// Level 1 methods
public boolean isKeepOverloadedMethodsTogether() {
return keepOverloadedMethodsTogether;
}
// Level 2 methods
public void setKeepOverloadedMethodsTogether(boolean keepOverloadedMethodsTogether) {
this.keepOverloadedMethodsTogether = keepOverloadedMethodsTogether;
}
// end of Level 2 methods
// end of Level 1 methods
// Level 1 methods
public boolean isRearrangeInnerClasses() {
return rearrangeInnerClasses;
}
public void setRearrangeInnerClasses(boolean rearrangeInnerClasses) {
this.rearrangeInnerClasses = rearrangeInnerClasses;
}
// end of Level 2 methods
// end of Level 1 methods
// Level 1 methods
public boolean isRemoveBlanksInsideCodeBlocks() {
return removeBlanksInsideCodeBlocks;
}
// Level 2 methods
public void setRemoveBlanksInsideCodeBlocks(boolean removeBlanksInsideCodeBlocks) {
this.removeBlanksInsideCodeBlocks = removeBlanksInsideCodeBlocks;
}
public boolean isShowComments() {
return showComments;
}
public void setShowComments(boolean showComments) {
this.showComments = showComments;
}
// end of Level 2 methods
// end of Level 1 methods
// Level 1 methods
public boolean isShowFields() {
return showFields;
}
// Level 2 methods
public void setShowFields(boolean showFields) {
this.showFields = showFields;
}
public boolean isShowMatchedRules() {
return showMatchedRules;
}
public void setShowMatchedRules(boolean showMatchedRules) {
this.showMatchedRules = showMatchedRules;
}
public boolean isShowParameterNames() {
return showParameterNames;
}
// Level 2 methods
public void setShowParameterNames(boolean showParameterNames) {
this.showParameterNames = showParameterNames;
}
// end of Level 2 methods
// end of Level 1 methods
// Level 1 methods
public boolean isShowParameterTypes() {
return showParameterTypes;
}
// Level 2 methods
public void setShowParameterTypes(boolean showParameterTypes) {
this.showParameterTypes = showParameterTypes;
}
// end of Level 2 methods
// end of Level 1 methods
// Level 1 methods
public boolean isShowRules() {
return showRules;
}
public void setShowRules(boolean showRules) {
this.showRules = showRules;
}
// end of Level 2 methods
// end of Level 1 methods
public boolean isShowTypeAfterMethod() {
return showTypeAfterMethod;
}
public void setShowTypeAfterMethod(boolean showTypeAfterMethod) {
this.showTypeAfterMethod = showTypeAfterMethod;
}
// ------------------------ CANONICAL METHODS ------------------------
public boolean equals(final Object object) {
if (!(object instanceof RearrangerSettings)) return false;
final RearrangerSettings rs = (RearrangerSettings)object;
if (rs.getClassOrderAttributeList().size() != getClassOrderAttributeList().size()) return false;
if (rs.getItemOrderAttributeList().size() != getItemOrderAttributeList().size()) return false;
for (int i = 0; i < getClassOrderAttributeList().size(); i++) {
if (!getClassOrderAttributeList().get(i).equals(rs.getClassOrderAttributeList().get(i))) return false;
}
for (int i = 0; i < getItemOrderAttributeList().size(); i++) {
if (!getItemOrderAttributeList().get(i).equals(rs.getItemOrderAttributeList().get(i))) return false;
}
if (!rs.getExtractedMethodsSettings().equals(getExtractedMethodsSettings())) return false;
if (rs.isKeepGettersSettersTogether() != isKeepGettersSettersTogether()) return false;
if (rs.isKeepGettersSettersWithProperty() != isKeepGettersSettersWithProperty()) return false;
if (rs.isKeepOverloadedMethodsTogether() != isKeepOverloadedMethodsTogether()) return false;
if (rs.overloadedOrder != overloadedOrder) return false;
if (!rs.globalCommentPattern.equals(globalCommentPattern)) return false;
if (rs.askBeforeRearranging != askBeforeRearranging) return false;
if (rs.rearrangeInnerClasses != rearrangeInnerClasses) return false;
if (rs.showParameterTypes != showParameterTypes) return false;
if (rs.showParameterNames != showParameterNames) return false;
if (rs.showFields != showFields) return false;
if (rs.showTypeAfterMethod != showTypeAfterMethod) return false;
if (rs.showRules != showRules) return false;
if (rs.showMatchedRules != showMatchedRules) return false;
if (rs.showComments != showComments) return false;
if (rs.removeBlanksInsideCodeBlocks != removeBlanksInsideCodeBlocks) return false;
if (!rs.afterClassLBrace.equals(afterClassLBrace)) return false;
if (!rs.afterClassRBrace.equals(afterClassRBrace)) return false;
if (!rs.beforeClassRBrace.equals(beforeClassRBrace)) return false;
if (!rs.beforeMethodLBrace.equals(beforeMethodLBrace)) return false;
if (!rs.afterMethodLBrace.equals(afterMethodLBrace)) return false;
if (!rs.afterMethodRBrace.equals(afterMethodRBrace)) return false;
if (!rs.beforeMethodRBrace.equals(beforeMethodRBrace)) return false;
if (!rs.newlinesAtEOF.equals(newlinesAtEOF)) return false;
if (!rs.defaultGSDefinition.equals(defaultGSDefinition)) return false;
if (primaryMethodList.size() != rs.primaryMethodList.size()) return false;
for (int i = 0; i < primaryMethodList.size(); i++) {
PrimaryMethodSetting pms = primaryMethodList.get(i);
PrimaryMethodSetting rspms = rs.primaryMethodList.get(i);
if (!rspms.equals(pms)) return false;
}
return true;
}
// -------------------------- OTHER METHODS --------------------------
public final void addClass(final AttributeGroup ca, final int index) {
if (classOrderAttributeList.size() < index) {
classOrderAttributeList.add(ca);
}
else {
classOrderAttributeList.add(index, ca);
}
}
public final void addItem(final AttributeGroup ia, final int index) {
if (itemOrderAttributeList.size() < index) {
itemOrderAttributeList.add(ia);
}
else {
itemOrderAttributeList.add(index, ia);
}
}
public final RearrangerSettings deepCopy() {
final RearrangerSettings result = new RearrangerSettings();
for (AttributeGroup itemAttributes : itemOrderAttributeList) {
result.itemOrderAttributeList.add(itemAttributes.deepCopy());
}
for (AttributeGroup classAttributes : classOrderAttributeList) {
result.classOrderAttributeList.add(classAttributes.deepCopy());
}
result.relatedMethodsSettings = relatedMethodsSettings.deepCopy();
result.keepGettersSettersTogether = keepGettersSettersTogether;
result.keepGettersSettersWithProperty = keepGettersSettersWithProperty;
result.keepOverloadedMethodsTogether = keepOverloadedMethodsTogether;
result.globalCommentPattern = globalCommentPattern;
result.overloadedOrder = overloadedOrder;
result.askBeforeRearranging = askBeforeRearranging;
result.rearrangeInnerClasses = rearrangeInnerClasses;
result.showParameterNames = showParameterNames;
result.showParameterTypes = showParameterTypes;
result.showFields = showFields;
result.showTypeAfterMethod = showTypeAfterMethod;
result.showRules = showRules;
result.showMatchedRules = showMatchedRules;
result.showComments = showComments;
result.removeBlanksInsideCodeBlocks = removeBlanksInsideCodeBlocks;
result.afterClassLBrace = afterClassLBrace.deepCopy();
result.afterClassRBrace = afterClassRBrace.deepCopy();
result.beforeClassRBrace = beforeClassRBrace.deepCopy();
result.beforeMethodLBrace = beforeMethodLBrace.deepCopy();
result.afterMethodLBrace = afterMethodLBrace.deepCopy();
result.afterMethodRBrace = afterMethodRBrace.deepCopy();
result.beforeMethodRBrace = beforeMethodRBrace.deepCopy();
result.newlinesAtEOF = newlinesAtEOF.deepCopy();
result.defaultGSDefinition = defaultGSDefinition.deepCopy();
return result;
}
public void writeSettingsToFile(File f) {
Element component = new Element("component");
component.setAttribute("name", Rearranger.COMPONENT_NAME);
Element r = new Element(Rearranger.COMPONENT_NAME);
component.getChildren().add(r);
writeExternal(r);
Format format = Format.getPrettyFormat();
XMLOutputter outputter = new XMLOutputter(format);
try {
final FileOutputStream fileOutputStream = new FileOutputStream(f);
outputter.output(component, fileOutputStream);
fileOutputStream.close();
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
// end of Level 2 methods
// end of Level 1 methods
public final void writeExternal(final Element entry) {
final Element items = new Element("Items");
final Element classes = new Element("Classes");
entry.getChildren().add(items);
entry.getChildren().add(classes);
for (AttributeGroup item : itemOrderAttributeList) {
item.writeExternal(items);
}
for (AttributeGroup attributes : classOrderAttributeList) {
attributes.writeExternal(classes);
}
final Element gsd = new Element("DefaultGetterSetterDefinition");
entry.getChildren().add(gsd);
defaultGSDefinition.writeExternal(gsd);
final Element relatedItems = new Element("RelatedMethods");
entry.getChildren().add(relatedItems);
entry.setAttribute("KeepGettersSettersTogether", Boolean.valueOf(keepGettersSettersTogether).toString());
entry.setAttribute("KeepGettersSettersWithProperty", Boolean.valueOf(keepGettersSettersWithProperty).toString());
entry.setAttribute("KeepOverloadedMethodsTogether", Boolean.valueOf(keepOverloadedMethodsTogether).toString());
entry.setAttribute("ConfirmBeforeRearranging", Boolean.valueOf(askBeforeRearranging).toString());
entry.setAttribute("RearrangeInnerClasses", Boolean.valueOf(rearrangeInnerClasses).toString());
entry.setAttribute("globalCommentPattern", globalCommentPattern);
entry.setAttribute("overloadedOrder", "" + overloadedOrder);
entry.setAttribute("ShowParameterTypes", Boolean.valueOf(showParameterTypes).toString());
entry.setAttribute("ShowParameterNames", Boolean.valueOf(showParameterNames).toString());
entry.setAttribute("ShowFields", Boolean.valueOf(showFields).toString());
entry.setAttribute("ShowTypeAfterMethod", Boolean.valueOf(showTypeAfterMethod).toString());
entry.setAttribute("ShowRules", Boolean.valueOf(showRules).toString());
entry.setAttribute("ShowMatchedRules", Boolean.valueOf(showMatchedRules).toString());
entry.setAttribute("ShowComments", Boolean.valueOf(showComments).toString());
entry.setAttribute("RemoveBlanksInsideCodeBlocks", Boolean.valueOf(removeBlanksInsideCodeBlocks).toString());
relatedMethodsSettings.writeExternal(relatedItems);
afterClassLBrace.writeExternal(entry);
afterClassRBrace.writeExternal(entry);
beforeClassRBrace.writeExternal(entry);
beforeMethodLBrace.writeExternal(entry);
afterMethodLBrace.writeExternal(entry);
afterMethodRBrace.writeExternal(entry);
beforeMethodRBrace.writeExternal(entry);
newlinesAtEOF.writeExternal(entry);
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings;
import java.util.ArrayList;
/** Contains settings pertaining to methods related by name, e.g. getter/setters. */
public class RelatedByNameMethodsSettings {
ArrayList<PrimaryMethodSetting> methodList;
public RelatedByNameMethodsSettings() {
methodList = new ArrayList<PrimaryMethodSetting>();
}
public ArrayList<PrimaryMethodSetting>/*<IListManagerObject>*/ getMethodList() {
return methodList;
}
public void addMethod(PrimaryMethodSetting pms) {
methodList.add(pms);
}
public void removeMethod(PrimaryMethodSetting pms) {
methodList.remove(pms);
}
}
@@ -0,0 +1,247 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings;
import com.wrq.rearranger.settings.attributeGroups.RegexUtil;
import org.jdom.Element;
import java.util.List;
/** Contains settings regarding placement of related methods. */
public class RelatedMethodsSettings {
private boolean moveExtractedMethods;
private boolean belowFirstCaller; // false means below last caller
private boolean depthFirstOrdering; // false means breadth first ordering
public static final int INVOCATION_ORDER = 0;
public static final int RETAIN_ORIGINAL_ORDER = 1;
public static final int ALPHABETICAL_ORDER = 2;
private int ordering;
public static final int NON_PRIVATE_EXTRACTED_NEVER = 0;
public static final int NON_PRIVATE_EXTRACTED_ONE_CALLER = 1;
public static final int NON_PRIVATE_EXTRACTED_ANY_CALLERS = 2;
private int nonPrivateTreatment;
public static final int COMMENT_TYPE_TOP_LEVEL = 0;
public static final int COMMENT_TYPE_EACH_LEVEL = 1;
public static final int COMMENT_TYPE_EACH_METHOD = 2;
public static final int COMMENT_TYPE_NEW_FAMILY = 3;
private int commentType;
private CommentRule precedingComment;
private CommentRule trailingComment;
private CommentFillString commentFillString;
private RelatedByNameMethodsSettings rbnms;
public RelatedByNameMethodsSettings getRbnms() {
return rbnms;
}
public RelatedMethodsSettings() {
belowFirstCaller = true;
depthFirstOrdering = true;
ordering = INVOCATION_ORDER;
nonPrivateTreatment = NON_PRIVATE_EXTRACTED_ANY_CALLERS;
commentType = COMMENT_TYPE_TOP_LEVEL;
precedingComment = new CommentRule();
trailingComment = new CommentRule();
rbnms = new RelatedByNameMethodsSettings();
commentFillString = new CommentFillString();
}
public boolean isMoveExtractedMethods() {
return moveExtractedMethods;
}
public void setMoveExtractedMethods(boolean moveExtractedMethods) {
this.moveExtractedMethods = moveExtractedMethods;
}
public boolean isBelowFirstCaller() {
return belowFirstCaller;
}
public void setBelowFirstCaller(boolean belowFirstCaller) {
this.belowFirstCaller = belowFirstCaller;
}
public boolean isDepthFirstOrdering() {
return depthFirstOrdering;
}
public void setDepthFirstOrdering(boolean depthFirstOrdering) {
this.depthFirstOrdering = depthFirstOrdering;
}
public int getOrdering() {
return ordering;
}
public void setOrdering(int ordering) {
this.ordering = ordering;
}
public int getNonPrivateTreatment() {
return nonPrivateTreatment;
}
public void setNonPrivateTreatment(int nonPrivateTreatment) {
this.nonPrivateTreatment = nonPrivateTreatment;
}
public int getCommentType() {
return commentType;
}
public void setCommentType(int commentType) {
this.commentType = commentType;
}
public CommentRule getPrecedingComment() {
return precedingComment;
}
public void setPrecedingComment(CommentRule precedingComment) {
this.precedingComment = precedingComment;
}
public CommentRule getTrailingComment() {
return trailingComment;
}
public void setTrailingComment(CommentRule trailingComment) {
this.trailingComment = trailingComment;
}
public CommentFillString getCommentFillString() {
return commentFillString;
}
public boolean equals(Object object) {
if (object instanceof RelatedMethodsSettings) {
RelatedMethodsSettings rms = (RelatedMethodsSettings)object;
return (rms.moveExtractedMethods == moveExtractedMethods &&
rms.belowFirstCaller == belowFirstCaller &&
rms.depthFirstOrdering == depthFirstOrdering &&
rms.ordering == ordering &&
rms.nonPrivateTreatment == nonPrivateTreatment &&
rms.commentType == commentType &&
rms.precedingComment.equals(precedingComment) &&
rms.trailingComment.equals(trailingComment) &&
rms.commentFillString.equals(commentFillString));
}
return false;
}
public RelatedMethodsSettings deepCopy() {
RelatedMethodsSettings result = new RelatedMethodsSettings();
result.moveExtractedMethods = moveExtractedMethods;
result.belowFirstCaller = belowFirstCaller;
result.depthFirstOrdering = depthFirstOrdering;
result.ordering = ordering;
result.nonPrivateTreatment = nonPrivateTreatment;
result.commentType = commentType;
result.precedingComment = (CommentRule)precedingComment.deepCopy();
result.trailingComment = (CommentRule)trailingComment.deepCopy();
result.commentFillString = commentFillString.deepCopy();
return result;
}
public String toString() {
return "moveExtractedMethods=" + moveExtractedMethods +
", belowFirstCaller=" + belowFirstCaller +
", depthFirstOrdering=" + depthFirstOrdering +
", ordering=" + ordering +
", non-private treatment=" + nonPrivateTreatment +
", comment type=" + commentType;
}
public void loadAttributes(final Element me) {
moveExtractedMethods = RearrangerSettings.getBooleanAttribute(me, "moveExtractedMethods");
belowFirstCaller = RearrangerSettings.getBooleanAttribute(me, "belowFirstCaller", true);
depthFirstOrdering = RearrangerSettings.getBooleanAttribute(me, "depthFirstOrdering", true);
ordering = RearrangerSettings.getIntAttribute(me,
"ordering",
INVOCATION_ORDER);
nonPrivateTreatment = RearrangerSettings.getIntAttribute(me,
"nonPrivateTreatment",
NON_PRIVATE_EXTRACTED_ANY_CALLERS);
commentType = RearrangerSettings.getIntAttribute(me,
"commentType",
COMMENT_TYPE_TOP_LEVEL);
Element prc = me.getChild("PrecedingComment");
if (prc != null) prc = prc.getChild("Comment");
precedingComment = CommentRule.readExternal(prc);
Element trc = me.getChild("TrailingComment");
if (trc != null) trc = trc.getChild("Comment");
trailingComment = CommentRule.readExternal(trc);
commentFillString = CommentFillString.readExternal(me);
}
public static RelatedMethodsSettings readExternal(final Element item) {
final RelatedMethodsSettings result = new RelatedMethodsSettings();
result.loadAttributes(item);
return result;
}
public final void writeExternal(final Element me) {
me.setAttribute("moveExtractedMethods", Boolean.valueOf(moveExtractedMethods).toString());
me.setAttribute("belowFirstCaller", Boolean.valueOf(belowFirstCaller).toString());
me.setAttribute("depthFirstOrdering", Boolean.valueOf(depthFirstOrdering).toString());
me.setAttribute("ordering", "" + ordering);
me.setAttribute("nonPrivateTreatment", "" + nonPrivateTreatment);
me.setAttribute("commentType", "" + commentType);
Element prc = new Element("PrecedingComment");
Element trc = new Element("TrailingComment");
me.getChildren().add(prc);
me.getChildren().add(trc);
precedingComment.writeExternal(prc);
trailingComment.writeExternal(trc);
commentFillString.writeExternal(me);
}
public void addCommentPatternsToList(List<String> list) {
addCommentPatternToList(precedingComment, list);
addCommentPatternToList(trailingComment, list);
}
private void addCommentPatternToList(CommentRule comment, List<String> list) {
String s = null;
if (comment != null) {
s = comment.getCommentText();
}
if (s != null && s.length() > 0) {
String esc = RegexUtil.escape(s);
String fsp = commentFillString.getFillStringPattern();
s = RegexUtil.replaceAllFS(esc, fsp);
s = s.replaceAll("%TL%", "[A-Za-z0-9_()]+");
s = s.replaceAll("%MN%", "[A-Za-z0-9_()]+");
s = s.replaceAll("%AM%", "[A-Za-z0-9_\\\\[\\\\],.]+");
s = s.replaceAll("%LV%", "[0-9]+");
list.add(s);
}
}
}
@@ -0,0 +1,307 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings;
import com.wrq.rearranger.configuration.IListManagerObject;
import com.wrq.rearranger.configuration.IntTextField;
import com.wrq.rearranger.configuration.StringTextArea;
import com.wrq.rearranger.configuration.StringTextField;
import javax.swing.*;
import java.awt.*;
/**
* Contains settings for each secondary method (e.g., "set", "is"). Any number of secondary method definitions
* may be associated with a primary method definition.
*/
public class SecondaryMethodSetting
implements IListManagerObject
{
/** Description of the related method. */
String description;
/**
* Regular expression which method name must match. If the method is to be matched to a field, there must be
* at least one capture group (parenthesized subexpression) which will be treated as the field.
* In the case of a traditional setter method, this pattern is "set%FN%". One substitution is available:
* <pre>
* %FN% field name
* </pre>
*/
String methodNamePattern;
/** number of parameters the secondary method must have. In the case of a traditional setter method, this is one. */
int numParameters;
/**
* regular expression pattern of the type which the secondary method must return.
* In the case of a traditional getter method, this is the field type. One substitution is available:
* <pre>
* %FT% field type
* </pre>
*/
String methodTypePattern;
/**
* regular expression pattern of the attributes of the method.
* In the case of a traditional getter method, this is ".*public.*" (i.e., any public method).
*/
String methodAttributePattern;
/**
* pattern of method body (excluding comments and newline characters). Substitutions are available as follows:
* <pre>
* %FN% field name
* %FT% field type (if field is valid field, else empty string)
* %MT% method return type
* %P1% parameter 1 name (%P2%, %P3% etc for additional parameters)
* %T1% parameter 1 type name
* </pre>
*/
String body;
public SecondaryMethodSetting() {
methodNamePattern = "set%FN%";
numParameters = 1;
methodTypePattern = "void";
methodAttributePattern = ".*public.*";
body = "{\\s*return\\s*%FN%;\\s*}";
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getMethodNamePattern() {
return methodNamePattern;
}
public void setMethodNamePattern(String methodNamePattern) {
this.methodNamePattern = methodNamePattern;
}
public int getNumParameters() {
return numParameters;
}
public void setNumParameters(int numParameters) {
this.numParameters = numParameters;
}
public String getMethodTypePattern() {
return methodTypePattern;
}
public void setMethodTypePattern(String methodTypePattern) {
this.methodTypePattern = methodTypePattern;
}
public String getMethodAttributePattern() {
return methodAttributePattern;
}
public void setMethodAttributePattern(String methodAttributePattern) {
this.methodAttributePattern = methodAttributePattern;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String toString() {
return description;
}
public com.wrq.rearranger.configuration.IListManagerObject deepcopy() {
SecondaryMethodSetting pms = new SecondaryMethodSetting();
pms.description = getDescription();
pms.methodNamePattern = getMethodNamePattern();
pms.numParameters = getNumParameters();
pms.methodTypePattern = getMethodTypePattern();
pms.methodAttributePattern = getMethodAttributePattern();
pms.body = getBody();
return pms;
}
public boolean equals(Object obj) {
if (!(obj instanceof PrimaryMethodSetting)) return false;
PrimaryMethodSetting pms = (PrimaryMethodSetting)obj;
if (!pms.description.equals(description)) return false;
if (!pms.methodNamePattern.equals(methodNamePattern)) return false;
if (pms.numParameters != numParameters) return false;
if (!pms.methodTypePattern.equals(methodTypePattern)) return false;
if (!pms.methodAttributePattern.equals(methodAttributePattern)) return false;
if (!pms.body.equals(body)) return false;
return true;
}
public JPanel getPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
"Matching Method (\"Setter\") Criteria"));
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.NONE;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0.0d;
constraints.weighty = 0.0d;
constraints.gridy = constraints.gridx = 0;
constraints.insets = new Insets(3, 3, 3, 3);
JLabel methodNamePatternLabel = new JLabel("Method name:");
methodNamePatternLabel.setToolTipText(
"Regular expression which method name must match. " +
"If the method is to be matched to a field, there must be\n" +
" at least one capture group (parenthesized subexpression) which will be treated as the field.\n" +
" In the case of a traditional setter method, this pattern is \"set%FN%\".\n" +
" One substitution is available:\n" +
" %FN% field name");
panel.add(methodNamePatternLabel, constraints);
constraints.gridx++;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = .5;
StringTextField primaryPrefixText = new StringTextField() {
public void setValue(String value) {
setMethodNamePattern(value);
}
public String getValue() {
return getMethodNamePattern();
}
};
panel.add(primaryPrefixText, constraints);
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0;
constraints.gridx++;
JLabel nParamLabel = new JLabel("Number of parameters:");
nParamLabel.setToolTipText(
"number of parameters the secondary method must have.\n" +
"In the case of a traditional setter method, this is 1.");
panel.add(nParamLabel, constraints);
constraints.gridx++;
IntTextField nParamText = new IntTextField(
new IntTextField.IGetSet() {
public int get() {
return numParameters;
}
public void set(int value) {
numParameters = value;
}
}, null, null
);
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridwidth = GridBagConstraints.REMAINDER;
panel.add(nParamText, constraints);
constraints.gridx = 0;
constraints.gridy++;
constraints.gridwidth = 1;
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
JLabel returnTypeLabel = new JLabel("Return type:");
returnTypeLabel.setToolTipText(
"regular expression pattern of the type which the secondary method must return.\n" +
" In the case of a traditional setter method, this is void. One substitution is available:\n" +
" * %FT% field type");
panel.add(returnTypeLabel, constraints);
constraints.gridx++;
constraints.weightx = .5;
constraints.fill = GridBagConstraints.HORIZONTAL;
StringTextField returnTypeField = new StringTextField() {
public void setValue(String value) {
methodTypePattern = value;
}
public String getValue() {
return methodTypePattern;
}
};
panel.add(returnTypeField, constraints);
constraints.fill = GridBagConstraints.NONE;
constraints.gridx++;
constraints.weightx = 0;
JLabel methodAttributeLabel = new JLabel("Method attributes:");
methodAttributeLabel.setToolTipText("Protection level or other attributes for the method.\n" +
"In the case of a getter method, this is usually \".*public.*\".");
panel.add(methodAttributeLabel, constraints);
StringTextField methodAttributeField = new StringTextField() {
public void setValue(String value) {
methodAttributePattern = value;
}
public String getValue() {
return methodAttributePattern;
}
};
constraints.gridx++;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = .5;
constraints.fill = GridBagConstraints.HORIZONTAL;
panel.add(methodAttributeField, constraints);
constraints.gridx++;
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.gridy++;
constraints.gridx = 0;
JLabel bodyLabel = new JLabel("Body:");
bodyLabel.setToolTipText("regular expression pattern of method body (excluding comments and newline characters).\n" +
"Substitutions are available as follows:\n" +
" %FN% field name\n" +
" %FT% field type (if field is valid field, else empty string)\n" +
" %MT% method return type\n" +
" %P1% parameter 1 name (%P2%, %P3% etc for additional parameters)\n" +
" %T1% parameter 1 type name");
constraints.gridwidth = 1;
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
panel.add(bodyLabel, constraints);
constraints.gridx++;
StringTextArea bodyField = new StringTextArea() {
public void setValue(String value) {
body = value;
}
public String getValue() {
return body;
}
};
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = 1;
constraints.weighty = .35;
constraints.fill = GridBagConstraints.BOTH;
JScrollPane sp = new JScrollPane(bodyField);
panel.add(sp, constraints);
constraints.gridx = 0;
constraints.gridy++;
constraints.gridheight = GridBagConstraints.REMAINDER;
constraints.fill = GridBagConstraints.NONE;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1;
constraints.weighty = .65;
return panel;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings.atomicAttributes;
import org.jdom.Element;
import java.lang.reflect.Modifier;
/** Common routines for 'abstract' modifier. */
public final class AbstractAttribute
extends AndNotAttribute
{
// -------------------------- STATIC METHODS --------------------------
public static AbstractAttribute readExternal(final Element item) {
final AbstractAttribute result = new AbstractAttribute();
result.loadAttributes(item.getChild(result.getElementName()));
return result;
}
// --------------------------- CONSTRUCTORS ---------------------------
public AbstractAttribute() {
super("abstract", Modifier.ABSTRACT);
}
// -------------------------- OTHER METHODS --------------------------
public final /*AbstractAttribute*/AtomicAttribute deepCopy() {
final AbstractAttribute aba = new AbstractAttribute();
aba.value = value;
aba.invert = invert;
return aba;
}
}
@@ -0,0 +1,152 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings.atomicAttributes;
import com.wrq.rearranger.settings.RearrangerSettings;
import com.wrq.rearranger.util.Constraints;
import org.jdom.Element;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/** Base class for all boolean attributes. */
abstract public class AndNotAttribute
extends AtomicAttribute
{
// ------------------------------ FIELDS ------------------------------
boolean value;
boolean invert;
private final String valueName;
private final int modifierBit;
// --------------------------- CONSTRUCTORS ---------------------------
AndNotAttribute(final String s, final int modifierBit) {
valueName = s;
this.modifierBit = modifierBit;
}
// --------------------- GETTER / SETTER METHODS ---------------------
public final JPanel getAndNotPanel() {
final JPanel andNotPanel = new JPanel(new GridBagLayout());
final Constraints constraints = new Constraints(GridBagConstraints.WEST);
final JCheckBox andBox = new JCheckBox("And");
andBox.setSelected(isValue());
final JCheckBox notBox = new JCheckBox("not");
notBox.setSelected(isInvert());
notBox.setEnabled(andBox.isSelected());
notBox.setForeground(notBox.isSelected() ? Color.BLACK : Color.GRAY);
final JLabel nameLabel = new JLabel(getName());
nameLabel.setEnabled(andBox.isSelected());
andNotPanel.add(andBox, constraints.firstCol());
andNotPanel.add(notBox, constraints.nextCol());
constraints.insets = new Insets(0, 0, 0, 4);
andNotPanel.add(nameLabel, constraints.weightedLastCol());
andBox.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
setValue(andBox.isSelected());
notBox.setEnabled(andBox.isSelected());
nameLabel.setEnabled(andBox.isSelected());
}
});
notBox.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
setInvert(notBox.isSelected());
notBox.setForeground(notBox.isSelected() ? Color.BLACK : Color.GRAY);
}
});
return andNotPanel;
}
private String getName() {
return valueName;
}
public final boolean isInvert() {
return invert;
}
public final void setInvert(final boolean invert) {
this.invert = invert;
}
public final boolean isValue() {
return value;
}
public final void setValue(final boolean value) {
this.value = value;
}
// ------------------------ CANONICAL METHODS ------------------------
public final boolean equals(final Object obj) {
if (!(obj instanceof AndNotAttribute)) return false;
final AndNotAttribute ana = (AndNotAttribute)obj;
return (value == ana.value &&
invert == ana.invert &&
valueName.equals(ana.valueName) &&
modifierBit == ana.modifierBit);
}
// -------------------------- OTHER METHODS --------------------------
public final void appendAttributes(final Element me) {
final Element stElement = new Element(getElementName());
me.getChildren().add(stElement);
stElement.setAttribute("value", Boolean.valueOf(value).toString());
stElement.setAttribute("invert", Boolean.valueOf(invert).toString());
}
final String getElementName() {
final StringBuffer sb = new StringBuffer(valueName.length());
sb.append(valueName);
sb.replace(0, 1, new String("" + sb.charAt(0)).toUpperCase());
for (int i = 1; i < sb.length(); i++) {
if (sb.charAt(i) == ' ') {
sb.deleteCharAt(i);
sb.replace(i, i + 1, new String("" + sb.charAt(i)).toUpperCase());
}
}
return sb.toString();
}
public final String getDescriptiveString() {
return (isValue() ?
isInvert() ? "non-" + valueName + " " : valueName + " "
: "");
}
public final boolean isMatch(final int modifiers) {
return (!isValue()) ? true : ((modifiers & modifierBit) > 0) ^ isInvert();
}
public final void loadAttributes(final Element item) {
value = RearrangerSettings.getBooleanAttribute(item, "value");
invert = RearrangerSettings.getBooleanAttribute(item, "invert");
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings.atomicAttributes;
/** base class for all individual attributes that a field, method or class may have. */
abstract public class AtomicAttribute {
/**
* All subclasses will implement a static public AtomicAttribute readExternal(final Element item) method.
* However, because it is static, the interface can't contain it.
*/
// abstract public AtomicAttribute readExternal(final Element item);
}
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings.atomicAttributes;
import com.wrq.rearranger.ModifierConstants;
import org.jdom.Element;
/** Routines to handle 'enum' class attribute. */
public class EnumAttribute
extends AndNotAttribute
{
// -------------------------- STATIC METHODS --------------------------
public static EnumAttribute readExternal(final Element item) {
final EnumAttribute result = new EnumAttribute();
result.loadAttributes(item.getChild(result.getElementName()));
return result;
}
// --------------------------- CONSTRUCTORS ---------------------------
public EnumAttribute() {
super("enum", ModifierConstants.ENUM);
}
// -------------------------- OTHER METHODS --------------------------
/** final attribute. */
public final /*EnumAttribute*/AtomicAttribute deepCopy() {
final EnumAttribute result = new EnumAttribute();
result.value = value;
result.invert = invert;
return result;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings.atomicAttributes;
import org.jdom.Element;
import java.lang.reflect.Modifier;
/** Routines to handle the 'final' modifier. */
public final class FinalAttribute
extends AndNotAttribute
{
// -------------------------- STATIC METHODS --------------------------
public static FinalAttribute readExternal(final Element item) {
final FinalAttribute result = new FinalAttribute();
result.loadAttributes(item.getChild(result.getElementName()));
return result;
}
// --------------------------- CONSTRUCTORS ---------------------------
public FinalAttribute() {
super("final", Modifier.FINAL);
}
// -------------------------- OTHER METHODS --------------------------
public final /*FinalAttribute*/AtomicAttribute deepCopy() {
final FinalAttribute result = new FinalAttribute();
result.value = value;
result.invert = invert;
return result;
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings.atomicAttributes;
import com.wrq.rearranger.ModifierConstants;
import org.jdom.Element;
public final class ImplementedAttribute
extends AndNotAttribute
{
// -------------------------- STATIC METHODS --------------------------
public static ImplementedAttribute readExternal(final Element item) {
final ImplementedAttribute result = new ImplementedAttribute();
result.loadAttributes(item.getChild(result.getElementName()));
return result;
}
// --------------------------- CONSTRUCTORS ---------------------------
public ImplementedAttribute() {
super("implemented", ModifierConstants.IMPLEMENTED);
}
// -------------------------- OTHER METHODS --------------------------
public final /*ImplementedAttribute*/AtomicAttribute deepCopy() {
final ImplementedAttribute result = new ImplementedAttribute();
result.value = value;
result.invert = invert;
return result;
}
}
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings.atomicAttributes;
import com.wrq.rearranger.ModifierConstants;
import org.jdom.Element;
public final class ImplementingAttribute
extends AndNotAttribute
{
// -------------------------- STATIC METHODS --------------------------
public static ImplementingAttribute readExternal(final Element item) {
final ImplementingAttribute result = new ImplementingAttribute();
result.loadAttributes(item.getChild(result.getElementName()));
return result;
}
// --------------------------- CONSTRUCTORS ---------------------------
public ImplementingAttribute() {
super("implementing", ModifierConstants.IMPLEMENTING);
}
// -------------------------- OTHER METHODS --------------------------
public final /*ImplementingAttribute*/AtomicAttribute deepCopy() {
final ImplementingAttribute result = new ImplementingAttribute();
result.value = value;
result.invert = invert;
return result;
}
}
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2003, 2010, Dave Kriewall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wrq.rearranger.settings.atomicAttributes;
import com.wrq.rearranger.ModifierConstants;
import org.jdom.Element;
public final class InitToAnonClassAttribute
extends AndNotAttribute
{
// -------------------------- STATIC METHODS --------------------------
public static InitToAnonClassAttribute readExternal(final Element item) {
final InitToAnonClassAttribute result = new InitToAnonClassAttribute();
result.loadAttributes(item.getChild(result.getElementName()));
return result;
}
// --------------------------- CONSTRUCTORS ---------------------------
public InitToAnonClassAttribute() {
super("initialized to anonymous class", ModifierConstants.INIT_TO_ANON_CLASS);
}
// -------------------------- OTHER METHODS --------------------------
public final /*InitToAnonClassAttribute*/AtomicAttribute deepCopy() {
final InitToAnonClassAttribute result = new InitToAnonClassAttribute();
result.value = value;
result.invert = invert;
return result;
}
}

Some files were not shown because too many files have changed in this diff Show More