diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 1337da7e606c..d387559cb913 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -55,12 +55,11 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions private JCheckBox myDoNotAskMeCheckBox; private final String myHelpId; - @NotNull private String myRearrangeEntriesKeyForLanguage; @Nullable private CommonCodeStyleSettings myCommonSettings; private boolean myRearrangeAlwaysEnabled; - public LayoutCodeDialog(@NotNull Project project, + public LayoutCodeDialog(@NotNull Project project, @NotNull String title, @Nullable PsiFile file, @Nullable PsiDirectory directory, @@ -77,7 +76,6 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions && myCommonSettings.isForceArrangeMenuAvailable() && myCommonSettings.FORCE_REARRANGE_MODE == CommonCodeStyleSettings.REARRANGE_ALWAYS; - myRearrangeEntriesKeyForLanguage = LayoutCodeConstants.REARRANGE_ENTRIES_KEY + (myFile == null ? "" : myFile.getLanguage().getDisplayName()); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle(title); init(); @@ -103,7 +101,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions myCbIncludeSubdirs.setSelected(true); //Loading previous state myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false)); - myCbArrangeEntries.setSelected(myRearrangeAlwaysEnabled || PropertiesComponent.getInstance(myProject).getBoolean(myRearrangeEntriesKeyForLanguage, false)); + myCbArrangeEntries.setSelected(myRearrangeAlwaysEnabled || ReformatCodeAction.getLastSavedRearrangeCbState(myProject, myFile)); myCbOnlyVcsChangedRegions.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)); ItemListener listener = new ItemListener() { @@ -188,7 +186,8 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions } myCbArrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries")); - if (myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null) { + if (myDirectory != null || myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null) + { gbConstraints.gridy++; gbConstraints.insets = new Insets(0, 0, 0, 0); panel.add(myCbArrangeEntries, gbConstraints); @@ -280,10 +279,16 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions @Override protected void doOKAction() { super.doOKAction(); - //Saving checkboxes state PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myCbOptimizeImports.isSelected())); - PropertiesComponent.getInstance(myProject).setValue(myRearrangeEntriesKeyForLanguage, Boolean.toString(myCbArrangeEntries.isSelected())); PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected())); + saveRearrangeCbState(myCbArrangeEntries.isSelected()); + } + + private void saveRearrangeCbState(boolean isSelected) { + if (myFile != null) + LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, myFile.getLanguage(), isSelected); + else + LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isSelected); } private boolean canTargetVcsRegions() { @@ -292,7 +297,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions } if (isProcessWholeFile()) { - return FormatChangedTextUtil.hasChanges(myFile); + return myFile != null && FormatChangedTextUtil.hasChanges(myFile); } if (isProcessDirectory()) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java index 1090e007f1a5..f4691c3e1f31 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java @@ -21,8 +21,6 @@ public interface LayoutCodeOptions extends ReformatFilesOptions { boolean isProcessDirectory(); - boolean isRearrangeEntries(); - boolean isIncludeSubdirectories(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java new file mode 100644 index 000000000000..5175cf522556 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.actions; + +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.lang.Language; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +public class LayoutCodeSettingsStorage { + + private LayoutCodeSettingsStorage() { + } + + public static void saveRearrangeEntriesOptionFor(@NotNull Project project, @NotNull Language language, boolean value) { + String key = getRearrangeEntriesKeyForLanguage(language); + PropertiesComponent.getInstance(project).setValue(key, Boolean.toString(value)); + } + + public static void saveRearrangeEntriesOptionFor(@NotNull Project project, boolean value) { + PropertiesComponent.getInstance(project).setValue(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, Boolean.toString(value)); + } + + public static boolean getLastSavedRearrangeEntriesCbStateFor(@NotNull Project project) { + return PropertiesComponent.getInstance(project).getBoolean(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, false); + } + + public static boolean getLastSavedRearrangeEntriesCbStateFor(@NotNull Project project, @NotNull Language language) { + String key = getRearrangeEntriesKeyForLanguage(language); + return PropertiesComponent.getInstance(project).getBoolean(key, false); + } + + private static String getRearrangeEntriesKeyForLanguage(@NotNull Language language) { + return LayoutCodeConstants.REARRANGE_ENTRIES_KEY + language.getDisplayName(); + } + +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java index 31b6cb6cc475..57fac81769e8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java @@ -42,6 +42,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi private JCheckBox myCbOptimizeImports; private JCheckBox myCbOnlyVcsChangedRegions; + private JCheckBox myCbRearrangeEntries; public LayoutProjectCodeDialog(@NotNull Project project, @Nullable Module module, @@ -63,7 +64,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi @Override protected JComponent createCenterPanel() { if (!mySuggestOptimizeImports) return new JLabel(myText); - JPanel panel = new JPanel(new GridLayout(3, 1)); + JPanel panel = new JPanel(new GridLayout(4, 1)); panel.add(new JLabel(myText)); myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports")); panel.add(myCbOptimizeImports); @@ -76,6 +77,13 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi myCbOnlyVcsChangedRegions.setSelected( canTargetVcsRegions && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false) ); + + + myCbRearrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries")); + panel.add(myCbRearrangeEntries); + boolean previousSelectedState = LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject); + myCbRearrangeEntries.setSelected(previousSelectedState); + return panel; } @@ -85,6 +93,11 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi return new Action[]{getOKAction(), getCancelAction(), getHelpAction()}; } + @Override + public boolean isRearrangeEntries() { + return myCbRearrangeEntries.isSelected(); + } + @Override protected void doHelpAction() { HelpManager.getInstance().invokeHelp(HELP_ID); @@ -96,6 +109,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi if (mySuggestOptimizeImports) { PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports())); } + LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries()); } public boolean isOptimizeImports() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java new file mode 100644 index 000000000000..b2f30744c464 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -0,0 +1,111 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.actions; + +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.arrangement.Rearranger; +import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + +public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { + + public static final String COMMAND_NAME = "Rearrange code"; + public static final String PROGRESS_TEXT = "Rearranging code..."; + + @Nullable private Condition myAcceptCondition; + + public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor, + @Nullable Condition acceptCondition) { + super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); + myAcceptCondition = acceptCondition; + } + + public boolean shouldRearrangeFile(@NotNull PsiFile file) { + return myAcceptCondition == null || myAcceptCondition.value(file); + } + + @NotNull + @Override + protected FutureTask prepareTask(@NotNull final PsiFile file, boolean processChangedTextOnly) { + return new FutureTask(new Callable() { + @Override + public Boolean call() throws Exception { + if (!shouldRearrangeFile(file)) return true; + + RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME); + if (rearranger.couldRearrange()) { + rearranger.run(); + return true; + } + return false; + } + }); + } + +} + + +class RearrangeCommand { + @NotNull private PsiFile myFile; + @NotNull private String myCommandName; + @NotNull private Project myProject; + private Document myDocument; + private Runnable myCommand; + + RearrangeCommand(@NotNull Project project, @NotNull PsiFile file, @NotNull String commandName) { + myProject = project; + myFile = file; + myCommandName = commandName; + myDocument = PsiDocumentManager.getInstance(project).getDocument(file); + } + + boolean couldRearrange() { + return myDocument != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; + } + + void run() { + assert myDocument != null; + prepare(); + try { + CommandProcessor.getInstance().executeCommand(myProject, myCommand, myCommandName, null); + } + finally { + PsiDocumentManager.getInstance(myProject).commitDocument(myDocument); + } + } + + private void prepare() { + final ArrangementEngine engine = ServiceManager.getService(myProject, ArrangementEngine.class); + myCommand = new Runnable() { + @Override + public void run() { + engine.arrange(myFile, Collections.singleton(myFile.getTextRange())); + } + }; + PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myDocument); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index 7eeefb0a6635..0dc880d92a53 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -97,6 +97,10 @@ public class ReformatCodeAction extends AnAction implements DumbAware { if (shouldOptimizeImports) { processor = new OptimizeImportsProcessor(processor); } + if (selectedFlags.isRearrangeEntries()) { + processor = new RearrangeCodeProcessor(processor, null); + } + processor.run(); } return; @@ -131,7 +135,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn(); boolean processWholeFile = false; boolean processChangedTextOnly = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); - boolean rearrangeEntries = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, false); + boolean rearrangeEntries = getLastSavedRearrangeCbState(project, file); final boolean showDialog = EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG; @@ -150,6 +154,10 @@ public class ReformatCodeAction extends AnAction implements DumbAware { if (optimizeImports) { processor = new OptimizeImportsProcessor(processor); } + if (selectedFlags.isRearrangeEntries()) { + processor = new RearrangeCodeProcessor(processor, null); + } + processor.run(); return; } @@ -214,6 +222,10 @@ public class ReformatCodeAction extends AnAction implements DumbAware { processor = new OptimizeImportsProcessor(processor); } + if (selectedFlags.isRearrangeEntries()) { + processor = new RearrangeCodeProcessor(processor, null); + } + processor.run(); } @@ -357,6 +369,12 @@ public class ReformatCodeAction extends AnAction implements DumbAware { return dialog; } + public static boolean getLastSavedRearrangeCbState(@NotNull Project project, @Nullable PsiFile file) { + if (file != null) { + return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project, file.getLanguage()); + } + return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project); + } protected static void setTestOptions(ReformatFilesOptions options) { myTestOptions = options; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form index d5f043e108ab..f27be63f56da 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form @@ -3,12 +3,12 @@ - + - + @@ -32,11 +32,6 @@ - - - - - @@ -45,6 +40,19 @@ + + + + + + + + + + + + + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java index 9c8c5164e949..e02f1fc8b2a7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java @@ -26,14 +26,15 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesOptions { + @NotNull private Project myProject; private JPanel myPanel; private JCheckBox myOptimizeImports; private JCheckBox myOnlyChangedText; - private final VirtualFile[] myFiles; + private JCheckBox myRearrangeEntriesCb; public ReformatFilesDialog(@NotNull Project project, @NotNull VirtualFile[] files) { super(project, true); - myFiles = files; + myProject = project; setTitle(CodeInsightBundle.message("dialog.reformat.files.title")); myOptimizeImports.setSelected(isOptmizeImportsOptionOn()); boolean canTargetVcsChanges = false; @@ -48,6 +49,7 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false) ); myOptimizeImports.setSelected(isOptmizeImportsOptionOn()); + myRearrangeEntriesCb.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject)); init(); } @@ -66,12 +68,17 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected(); } + @Override + public boolean isRearrangeEntries() { + return myRearrangeEntriesCb.isSelected(); + } + @Override protected void doOKAction() { super.doOKAction(); PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected())); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, - Boolean.toString(myOnlyChangedText.isSelected())); + PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myOnlyChangedText.isSelected())); + LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries()); } static boolean isOptmizeImportsOptionOn() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java index a0bedf7f4917..37bf43c2c7cb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java @@ -16,7 +16,11 @@ package com.intellij.codeInsight.actions; public interface ReformatFilesOptions { + boolean isOptimizeImports(); boolean isProcessOnlyChangedText(); + + boolean isRearrangeEntries(); + }