mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-19061 Integrate the Rearranger-plugin into core-IDEA
New rule editing approach is applied
This commit is contained in:
+43
-1
@@ -27,6 +27,8 @@ public class ArrangementSettingsAtomNode implements ArrangementSettingsNode {
|
||||
|
||||
@NotNull private final ArrangementSettingType myType;
|
||||
@NotNull private final Object myValue;
|
||||
|
||||
private boolean myInverted;
|
||||
|
||||
public ArrangementSettingsAtomNode(@NotNull ArrangementSettingType type, @NotNull Object value) {
|
||||
myType = type;
|
||||
@@ -48,8 +50,48 @@ public class ArrangementSettingsAtomNode implements ArrangementSettingsNode {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public boolean isInverted() {
|
||||
return myInverted;
|
||||
}
|
||||
|
||||
public void setInverted(boolean inverted) {
|
||||
myInverted = inverted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myType.hashCode();
|
||||
result = 31 * result + myValue.hashCode();
|
||||
result = 31 * result + (myInverted ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ArrangementSettingsAtomNode node = (ArrangementSettingsAtomNode)o;
|
||||
|
||||
if (myInverted != node.myInverted) {
|
||||
return false;
|
||||
}
|
||||
if (myType != node.myType) {
|
||||
return false;
|
||||
}
|
||||
if (!myValue.equals(node.myValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myType + ": " + myValue;
|
||||
return String.format("%s: %s%s", myType.toString().toLowerCase(), myInverted ? "not " : "", myValue.toString().toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
+49
-27
@@ -15,17 +15,19 @@
|
||||
*/
|
||||
package com.intellij.psi.codeStyle.arrangement.settings;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsCompositeNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNodeVisitor;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Encapsulates information about {@link ArrangementEntryMatcher standard arrangement match rule settings}.
|
||||
* Encapsulates information about {@link ArrangementSettingsNode standard arrangement match rule settings}.
|
||||
* <p/>
|
||||
* Not thread-safe.
|
||||
*
|
||||
@@ -34,37 +36,57 @@ import java.util.Set;
|
||||
*/
|
||||
public class ArrangementMatcherSettings implements Cloneable {
|
||||
|
||||
@NotNull private final Set<ArrangementModifier> myModifiers = EnumSet.noneOf(ArrangementModifier.class);
|
||||
|
||||
@Nullable private ArrangementEntryType myType;
|
||||
|
||||
@Nullable
|
||||
public ArrangementEntryType getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
public void setType(@Nullable ArrangementEntryType type) {
|
||||
myType = type;
|
||||
}
|
||||
@NotNull private final List<ArrangementSettingsNode> myConditions = new ArrayList<ArrangementSettingsNode>();
|
||||
@NotNull private final Set<Object> myValues = new HashSet<Object>();
|
||||
@NotNull private final ArrangementSettingsNodeVisitor myAddVisitor = new MyAddVisitor();
|
||||
@NotNull private final ArrangementSettingsNodeVisitor myRemoveVisitor = new MyRemoveVisitor();
|
||||
|
||||
@NotNull
|
||||
public Set<ArrangementModifier> getModifiers() {
|
||||
return myModifiers;
|
||||
public List<ArrangementSettingsNode> getConditions() {
|
||||
return myConditions;
|
||||
}
|
||||
|
||||
public boolean addModifier(@NotNull ArrangementModifier modifier) {
|
||||
return myModifiers.add(modifier);
|
||||
public boolean addCondition(@NotNull ArrangementSettingsNode condition) {
|
||||
condition.invite(myAddVisitor);
|
||||
return myConditions.add(condition);
|
||||
}
|
||||
|
||||
public boolean removeModifier(@NotNull ArrangementModifier modifier) {
|
||||
return myModifiers.remove(modifier);
|
||||
public boolean removeCondition(@NotNull ArrangementSettingsNode condition) {
|
||||
condition.invite(myRemoveVisitor);
|
||||
return myConditions.remove(condition);
|
||||
}
|
||||
|
||||
public boolean hasCondition(@NotNull Object id) {
|
||||
return myValues.contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArrangementMatcherSettings clone() {
|
||||
public ArrangementMatcherSettings clone() {
|
||||
ArrangementMatcherSettings result = new ArrangementMatcherSettings();
|
||||
result.setType(myType);
|
||||
result.myModifiers.addAll(myModifiers);
|
||||
result.myConditions.addAll(myConditions);
|
||||
result.myValues.addAll(myValues);
|
||||
return result;
|
||||
}
|
||||
|
||||
private class MyAddVisitor implements ArrangementSettingsNodeVisitor {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsAtomNode node) {
|
||||
myValues.add(node.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
|
||||
}
|
||||
}
|
||||
|
||||
private class MyRemoveVisitor implements ArrangementSettingsNodeVisitor {
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsAtomNode node) {
|
||||
myValues.remove(node.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -21,6 +21,8 @@ import com.intellij.psi.codeStyle.arrangement.sort.ArrangementEntrySortType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
* Strategy that defines what subset of standard arrangement settings can be used during defining arrangement settings.
|
||||
@@ -31,14 +33,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
public interface ArrangementStandardSettingsAware {
|
||||
|
||||
// TODO den add doc
|
||||
boolean isNameFilterEnabled(@Nullable ArrangementMatcherSettings settings);
|
||||
boolean isNameFilterEnabled(@Nullable ArrangementMatcherSettings current);
|
||||
|
||||
// TODO den add doc
|
||||
boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatcherSettings settings);
|
||||
boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatcherSettings current);
|
||||
|
||||
// TODO den add doc
|
||||
boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatcherSettings settings);
|
||||
boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatcherSettings current);
|
||||
|
||||
// TODO den add doc
|
||||
boolean isEnabled(@NotNull ArrangementEntrySortType type, @Nullable ArrangementMatcherSettings settings);
|
||||
boolean isEnabled(@NotNull ArrangementEntrySortType type, @Nullable ArrangementMatcherSettings current);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<orderEntry type="library" name="Snappy-Java" level="project" />
|
||||
<orderEntry type="module" module-name="projectModel-impl" exported="" />
|
||||
<orderEntry type="library" scope="TEST" name="Groovy" level="project" />
|
||||
<orderEntry type="library" name="swingx" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
+8
-1
@@ -82,7 +82,14 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementNodeComponent getComponentAt(@NotNull RelativePoint point) {
|
||||
public void setSelected(boolean selected) {
|
||||
for (ArrangementNodeComponent component : myComponents) {
|
||||
component.setSelected(selected);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementNodeComponent getNodeComponentAt(@NotNull RelativePoint point) {
|
||||
if (myScreenBounds == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+36
-9
@@ -70,6 +70,10 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
|
||||
|
||||
@Nullable private Dimension mySize;
|
||||
@Nullable private Rectangle myScreenBounds;
|
||||
|
||||
private boolean mySelected;
|
||||
private boolean myEnabled;
|
||||
private boolean myInverted;
|
||||
|
||||
public ArrangementAtomNodeComponent(@NotNull ArrangementNodeDisplayManager manager, @NotNull ArrangementSettingsAtomNode node) {
|
||||
mySettingsNode = node;
|
||||
@@ -89,13 +93,7 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
|
||||
JPanel roundBorderPanel = new JPanel(new GridBagLayout()) {
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
Color color;
|
||||
if (myScreenBounds != null && myScreenBounds.contains(MouseInfo.getPointerInfo().getLocation())) {
|
||||
color = UIUtil.getTreeSelectionBackground();
|
||||
}
|
||||
else {
|
||||
color = UIUtil.getTabbedPaneBackground();
|
||||
}
|
||||
Color color = mySelected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTabbedPaneBackground();
|
||||
Rectangle bounds = getBounds();
|
||||
g.setColor(color);
|
||||
g.fillRoundRect(0, 0, bounds.width, bounds.height, arcSize, arcSize);
|
||||
@@ -135,10 +133,39 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementNodeComponent getComponentAt(@NotNull RelativePoint point) {
|
||||
public ArrangementNodeComponent getNodeComponentAt(@NotNull RelativePoint point) {
|
||||
return (myScreenBounds != null && myScreenBounds.contains(point.getScreenPoint())) ? this : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instructs current component that it should {@link #getUiComponent() draw} itself according to the given 'selected' state.
|
||||
*
|
||||
* @param selected flag that indicates if current component should be drawn as 'selected'
|
||||
*/
|
||||
public void setSelected(boolean selected) {
|
||||
mySelected = selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs current component that it should {@link #getUiComponent() draw} itself according to the given 'enabled' state.
|
||||
*
|
||||
* @param enabled flag that indicates if current component should be drawn as 'enabled'
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
myEnabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs current component that it should {@link #getUiComponent() draw} itself according to the given 'inverted' state.
|
||||
* <p/>
|
||||
* For example, target rule might look like 'public' and inverting it produces 'not public'.
|
||||
*
|
||||
* @param inverted flag that indicates if current component should be drawn as 'inverted'
|
||||
*/
|
||||
public void setInverted(boolean inverted) {
|
||||
myInverted = inverted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myLabel.getText();
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/15/12 9:14 AM
|
||||
*/
|
||||
public interface ArrangementMatcherEditingListener {
|
||||
|
||||
void startEditing(@NotNull ArrangementMatcherSettings settings);
|
||||
|
||||
void stopEditing();
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import com.intellij.util.ui.MultiRowFlowPanel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Control for managing {@link ArrangementEntryMatcher matching rule conditions}.
|
||||
* <p/>
|
||||
* Not thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/14/12 9:54 AM
|
||||
*/
|
||||
public class ArrangementMatcherRuleEditor extends JPanel {
|
||||
|
||||
@NotNull private final Map<Object, ArrangementAtomNodeComponent> myComponents = new HashMap<Object, ArrangementAtomNodeComponent>();
|
||||
|
||||
@NotNull private final ArrangementStandardSettingsAware myFilter;
|
||||
|
||||
public ArrangementMatcherRuleEditor(@NotNull ArrangementStandardSettingsAware filter) {
|
||||
myFilter = filter;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setLayout(new GridBagLayout());
|
||||
|
||||
ArrangementNodeDisplayManager displayManager = new ArrangementNodeDisplayManager(myFilter);
|
||||
Map<ArrangementSettingType,List<?>> supportedSettings = ArrangementSettingsUtil.buildAvailableOptions(myFilter, null);
|
||||
addRowIfPossible(ArrangementSettingType.TYPE, supportedSettings, displayManager);
|
||||
addRowIfPossible(ArrangementSettingType.MODIFIER, supportedSettings, displayManager);
|
||||
}
|
||||
|
||||
private void addRowIfPossible(@NotNull ArrangementSettingType key,
|
||||
@NotNull Map<ArrangementSettingType, List<?>> supportedSettings,
|
||||
@NotNull ArrangementNodeDisplayManager manager)
|
||||
{
|
||||
List<?> values = supportedSettings.get(key);
|
||||
if (values == null || values.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
add(new JLabel(manager.getDisplayLabel(key)), new GridBag().anchor(GridBagConstraints.WEST));
|
||||
JPanel valuesPanel = new MultiRowFlowPanel(FlowLayout.LEFT, 8, 5);
|
||||
for (Object value : manager.sort(values)) {
|
||||
ArrangementAtomNodeComponent component = new ArrangementAtomNodeComponent(manager, new ArrangementSettingsAtomNode(key, value));
|
||||
myComponents.put(value, component);
|
||||
valuesPanel.add(component.getUiComponent());
|
||||
}
|
||||
add(valuesPanel, new GridBag().anchor(GridBagConstraints.WEST).weightx(1).fillCellHorizontally().coverLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks current editor to refresh its state in accordance with the given arguments (e.g. when new rule is selected and
|
||||
* we want to show only available conditions).
|
||||
*
|
||||
* @param settings current rule settings
|
||||
*/
|
||||
public void updateState(@NotNull ArrangementMatcherSettings settings) {
|
||||
for (ArrangementEntryType type : ArrangementEntryType.values()) {
|
||||
ArrangementAtomNodeComponent component = myComponents.get(type);
|
||||
if (component == null) {
|
||||
continue;
|
||||
}
|
||||
boolean enabled = myFilter.isEnabled(type, settings);
|
||||
boolean selected = settings.hasCondition(type);
|
||||
component.setEnabled(enabled);
|
||||
component.setSelected(selected);
|
||||
}
|
||||
for (ArrangementModifier modifier : ArrangementModifier.values()) {
|
||||
ArrangementAtomNodeComponent component = myComponents.get(modifier);
|
||||
if (component == null) {
|
||||
continue;
|
||||
}
|
||||
boolean enabled = myFilter.isEnabled(modifier, settings);
|
||||
boolean selected = settings.hasCondition(modifier);
|
||||
component.setEnabled(enabled);
|
||||
component.setSelected(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-1
@@ -40,11 +40,18 @@ public interface ArrangementNodeComponent {
|
||||
|
||||
// TODO den add doc
|
||||
@Nullable
|
||||
ArrangementNodeComponent getComponentAt(@NotNull RelativePoint point);
|
||||
ArrangementNodeComponent getNodeComponentAt(@NotNull RelativePoint point);
|
||||
|
||||
// TODO den add doc
|
||||
@Nullable
|
||||
Rectangle getScreenBounds();
|
||||
|
||||
void setScreenBounds(@Nullable Rectangle bounds);
|
||||
|
||||
/**
|
||||
* Instructs current component that it should {@link #getUiComponent() draw} itself according to the given 'selected' state.
|
||||
*
|
||||
* @param selected flag that indicates if current component should be drawn as 'selected'
|
||||
*/
|
||||
void setSelected(boolean selected);
|
||||
}
|
||||
|
||||
+26
-4
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
@@ -34,9 +35,10 @@ import java.util.Map;
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/9/12 3:02 PM
|
||||
*/
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
public class ArrangementNodeDisplayManager {
|
||||
|
||||
private final TObjectIntHashMap<ArrangementSettingType> myMaxWidths = new TObjectIntHashMap<ArrangementSettingType>();
|
||||
@NotNull private final TObjectIntHashMap<ArrangementSettingType> myMaxWidths = new TObjectIntHashMap<ArrangementSettingType>();
|
||||
|
||||
public ArrangementNodeDisplayManager(@NotNull ArrangementStandardSettingsAware filter) {
|
||||
Map<ArrangementSettingType, List<?>> map = ArrangementSettingsUtil.buildAvailableOptions(filter, null);
|
||||
@@ -56,19 +58,26 @@ public class ArrangementNodeDisplayManager {
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
@NotNull
|
||||
public String getDisplayValue(@NotNull ArrangementSettingsAtomNode node) {
|
||||
return getDisplayValue(node.getValue());
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
|
||||
@NotNull
|
||||
public String getDisplayLabel(@NotNull ArrangementSettingType type) {
|
||||
switch (type) {
|
||||
case TYPE: return ApplicationBundle.message("arrangement.text.type");
|
||||
case MODIFIER: return ApplicationBundle.message("arrangement.text.modifier");
|
||||
}
|
||||
return type.toString().toLowerCase();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDisplayValue(@NotNull ArrangementSettingType type) {
|
||||
return type.toString().toLowerCase();
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
@NotNull
|
||||
public String getDisplayValue(@NotNull Object value) {
|
||||
return value.toString().toLowerCase();
|
||||
@@ -77,4 +86,17 @@ public class ArrangementNodeDisplayManager {
|
||||
public int getMaxWidth(@NotNull ArrangementSettingType type) {
|
||||
return myMaxWidths.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks current manager to sort in-place given arrangement condition ids ('field', 'class', 'method', 'public', 'static', 'final' etc).
|
||||
*
|
||||
* @param ids target ids to use
|
||||
* @param <T> id type
|
||||
* @return sorted ids to use (the given list)
|
||||
*/
|
||||
@NotNull
|
||||
public <T> List<T> sort(@NotNull List<T> ids) {
|
||||
// TODO den implement
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
||||
+166
-48
@@ -20,15 +20,19 @@ import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.*;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import gnu.trove.TObjectProcedure;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
@@ -42,23 +46,26 @@ import java.util.List;
|
||||
*/
|
||||
public class ArrangementRuleTree {
|
||||
|
||||
@NotNull private final TIntObjectHashMap<ArrangementNodeComponent> myRenderers = new TIntObjectHashMap<ArrangementNodeComponent>();
|
||||
@NotNull private final List<ArrangementMatcherEditingListener> myListeners = new ArrayList<ArrangementMatcherEditingListener>();
|
||||
@NotNull private final TreeSelectionModel mySelectionModel = new MySelectionModel();
|
||||
@NotNull private final TIntObjectHashMap<ArrangementNodeComponent> myRenderers = new TIntObjectHashMap<ArrangementNodeComponent>();
|
||||
@NotNull private final TIntObjectHashMap<ArrangementMatcherSettings> mySettings =
|
||||
new TIntObjectHashMap<ArrangementMatcherSettings>();
|
||||
|
||||
@NotNull private final DefaultTreeModel myTreeModel;
|
||||
@NotNull private final ArrangementStandardSettingsAware myFilter;
|
||||
@NotNull private final Tree myTree;
|
||||
@NotNull private final ArrangementNodeDisplayManager myDisplayManager;
|
||||
@NotNull private final ArrangementNodeComponentFactory myFactory;
|
||||
|
||||
@Nullable private ArrangementNodeComponent myPrevComponentUnderMouse;
|
||||
private boolean mySkipSelectionChange;
|
||||
|
||||
public ArrangementRuleTree(@NotNull ArrangementStandardSettingsAware filter) {
|
||||
myFilter = filter;
|
||||
myDisplayManager = new ArrangementNodeDisplayManager(filter);
|
||||
myFactory = new ArrangementNodeComponentFactory(myDisplayManager);
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
myTreeModel = new DefaultTreeModel(root);
|
||||
myTree = new Tree(myTreeModel) {
|
||||
DefaultTreeModel treeModel = new DefaultTreeModel(root);
|
||||
myTree = new Tree(treeModel) {
|
||||
@Override
|
||||
protected void setExpandedState(TreePath path, boolean state) {
|
||||
// Don't allow node collapse
|
||||
@@ -66,23 +73,46 @@ public class ArrangementRuleTree {
|
||||
super.setExpandedState(path, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
// Don't allow row selection as we're interested in particular row nodes.
|
||||
myTree.setSelectionModel(null);
|
||||
|
||||
myTree.addMouseMotionListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
onMouseMoved(e);
|
||||
protected boolean isAlwaysPaintRowBackground() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processMouseEvent(MouseEvent e) {
|
||||
// JTree selects a node on mouse click at the same row (even outside the node bounds). We don't want to support
|
||||
// such selection because selected nodes are highlighted at the rule tree, so, it produces a 'blink' effect.
|
||||
mySkipSelectionChange = e.getClickCount() > 0 && getNodeComponentAt(e.getLocationOnScreen()) == null;
|
||||
try {
|
||||
super.processMouseEvent(e);
|
||||
if (mySkipSelectionChange) {
|
||||
notifyEditingListeners(null);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
mySkipSelectionChange = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
myTree.setSelectionModel(mySelectionModel);
|
||||
mySelectionModel.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
setSelection(e.getOldLeadSelectionPath(), false);
|
||||
setSelection(e.getNewLeadSelectionPath(), true);
|
||||
}
|
||||
});
|
||||
myTree.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
onMouseClicked(e);
|
||||
}
|
||||
});
|
||||
myTree.putClientProperty(DataManager.CLIENT_PROPERTY_DATA_PROVIDER, new DataProvider() {
|
||||
@Override
|
||||
public Object getData(@NonNls String dataId) {
|
||||
if (ArrangementSettingsUtil.NODE_COMPONENT.is(dataId)) {
|
||||
return myPrevComponentUnderMouse;
|
||||
}
|
||||
else if (ArrangementSettingsUtil.DISPLAY_MANAGER.is(dataId)) {
|
||||
if (ArrangementSettingsUtil.DISPLAY_MANAGER.is(dataId)) {
|
||||
return myDisplayManager;
|
||||
}
|
||||
else if (ArrangementSettingsUtil.FILTER.is(dataId)) {
|
||||
@@ -95,24 +125,31 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
});
|
||||
|
||||
// TODO den remove
|
||||
List<ArrangementSettingsNode> children = new ArrayList<ArrangementSettingsNode>();
|
||||
children.add(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC));
|
||||
children.add(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.STATIC));
|
||||
children.add(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.FINAL));
|
||||
ArrangementSettingsCompositeNode constants = new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND);
|
||||
constants.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC));
|
||||
constants.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.STATIC));
|
||||
constants.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.FINAL));
|
||||
|
||||
HierarchicalArrangementSettingsNode settingsNode = new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
|
||||
ArrangementSettingsCompositeNode privateFields = new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND);
|
||||
privateFields.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE));
|
||||
|
||||
HierarchicalArrangementSettingsNode fields = new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
|
||||
ArrangementSettingType.TYPE, ArrangementEntryType.FIELD
|
||||
));
|
||||
ArrangementSettingsCompositeNode modifiers = new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND);
|
||||
for (ArrangementSettingsNode child : children) {
|
||||
modifiers.addOperand(child);
|
||||
}
|
||||
settingsNode.addChild(new HierarchicalArrangementSettingsNode(modifiers));
|
||||
//ArrangementSettingsNode node = ArrangementSettingsUtil.buildTreeStructure(settingsNode);
|
||||
if (settingsNode != null) {
|
||||
map(root, settingsNode);
|
||||
}
|
||||
fields.addChild(new HierarchicalArrangementSettingsNode(constants));
|
||||
fields.addChild(new HierarchicalArrangementSettingsNode(privateFields));
|
||||
int row = map(root, fields, null, 0);
|
||||
|
||||
HierarchicalArrangementSettingsNode methods = new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
|
||||
ArrangementSettingType.TYPE, ArrangementEntryType.METHOD
|
||||
));
|
||||
methods.addChild(new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
|
||||
ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC
|
||||
)));
|
||||
methods.addChild(new HierarchicalArrangementSettingsNode(new ArrangementSettingsAtomNode(
|
||||
ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE
|
||||
)));
|
||||
map(root, methods, null, row);
|
||||
|
||||
expandAll(myTree, new TreePath(root));
|
||||
myTree.setRootVisible(false);
|
||||
@@ -120,6 +157,24 @@ public class ArrangementRuleTree {
|
||||
myTree.setCellRenderer(new MyCellRenderer());
|
||||
}
|
||||
|
||||
private void setSelection(@Nullable final TreePath path, boolean selected) {
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TreePath p = path; p != null; p = p.getParentPath()) {
|
||||
int row = myTree.getRowForPath(p);
|
||||
if (row < 0) {
|
||||
return;
|
||||
}
|
||||
ArrangementNodeComponent component = myRenderers.get(row);
|
||||
if (component != null) {
|
||||
component.setSelected(selected);
|
||||
repaintComponent(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void expandAll(Tree tree, TreePath parent) {
|
||||
// Traverse children
|
||||
TreeNode node = (TreeNode)parent.getLastPathComponent();
|
||||
@@ -135,12 +190,50 @@ public class ArrangementRuleTree {
|
||||
tree.expandPath(parent);
|
||||
}
|
||||
|
||||
private static void map(@NotNull DefaultMutableTreeNode parentTreeNode, @NotNull HierarchicalArrangementSettingsNode settingsNode) {
|
||||
private int map(@NotNull DefaultMutableTreeNode parentTreeNode,
|
||||
@NotNull HierarchicalArrangementSettingsNode settingsNode,
|
||||
@Nullable ArrangementMatcherSettings template,
|
||||
int row)
|
||||
{
|
||||
DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(settingsNode.getCurrent());
|
||||
parentTreeNode.add(childTreeNode);
|
||||
for (HierarchicalArrangementSettingsNode node : settingsNode.getChildren()) {
|
||||
map(childTreeNode, node);
|
||||
List<HierarchicalArrangementSettingsNode> children = settingsNode.getChildren();
|
||||
ArrangementMatcherSettings settings = template == null ? new ArrangementMatcherSettings() : template.clone();
|
||||
settings.addCondition(settingsNode.getCurrent());
|
||||
if (children.isEmpty()) {
|
||||
mySettings.put(row, settings);
|
||||
return row + 1;
|
||||
}
|
||||
else {
|
||||
row++;
|
||||
for (HierarchicalArrangementSettingsNode node : children) {
|
||||
row = map(childTreeNode, node, settings, row);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
public void addEditingListener(@NotNull ArrangementMatcherEditingListener listener) {
|
||||
myListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return matcher settings for the selected tree row(s) if any; null otherwise
|
||||
*/
|
||||
@Nullable
|
||||
public ArrangementMatcherSettings getActiveSettings() {
|
||||
TreePath[] paths = mySelectionModel.getSelectionPaths();
|
||||
if (paths == null) {
|
||||
return null;
|
||||
}
|
||||
for (int i = paths.length - 1; i >= 0; i--) {
|
||||
int row = myTree.getRowForPath(paths[i]);
|
||||
ArrangementMatcherSettings settings = mySettings.get(row);
|
||||
if (settings != null) {
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -149,7 +242,7 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ArrangementNodeComponent getComponent(int row, @NotNull ArrangementSettingsNode node) {
|
||||
private ArrangementNodeComponent getNodeComponentAt(int row, @NotNull ArrangementSettingsNode node) {
|
||||
ArrangementNodeComponent result = myRenderers.get(row);
|
||||
if (result == null) {
|
||||
myRenderers.put(row, result = myFactory.getComponent(node));
|
||||
@@ -157,22 +250,25 @@ public class ArrangementRuleTree {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void onMouseMoved(@NotNull MouseEvent e) {
|
||||
ArrangementNodeComponent component = getComponent(e.getLocationOnScreen());
|
||||
if (component == myPrevComponentUnderMouse) {
|
||||
private void onMouseClicked(@NotNull MouseEvent e) {
|
||||
ArrangementNodeComponent component = getNodeComponentAt(e.getLocationOnScreen());
|
||||
if (component != null) {
|
||||
return;
|
||||
}
|
||||
if (myPrevComponentUnderMouse != null) {
|
||||
repaintComponent(myPrevComponentUnderMouse);
|
||||
}
|
||||
if (component != null) {
|
||||
repaintComponent(component);
|
||||
}
|
||||
myPrevComponentUnderMouse = component;
|
||||
// Clear selection
|
||||
mySelectionModel.clearSelection();
|
||||
myRenderers.forEachValue(new TObjectProcedure<ArrangementNodeComponent>() {
|
||||
@Override
|
||||
public boolean execute(ArrangementNodeComponent node) {
|
||||
node.setSelected(false);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
myTree.repaint();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private ArrangementNodeComponent getComponent(Point screenLocation) {
|
||||
private ArrangementNodeComponent getNodeComponentAt(Point screenLocation) {
|
||||
int low = 0;
|
||||
int high = myTree.getRowCount() - 1;
|
||||
|
||||
@@ -187,7 +283,7 @@ public class ArrangementRuleTree {
|
||||
return null;
|
||||
}
|
||||
if (bounds.contains(screenLocation)) {
|
||||
return midVal.getComponentAt(RelativePoint.fromScreen(screenLocation));
|
||||
return midVal.getNodeComponentAt(RelativePoint.fromScreen(screenLocation));
|
||||
}
|
||||
else if (bounds.y > screenLocation.y) {
|
||||
high = mid - 1;
|
||||
@@ -211,6 +307,17 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyEditingListeners(@Nullable ArrangementMatcherSettings settings) {
|
||||
for (ArrangementMatcherEditingListener listener : myListeners) {
|
||||
if (settings == null) {
|
||||
listener.stopEditing();
|
||||
}
|
||||
else {
|
||||
listener.startEditing(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyCellRenderer implements TreeCellRenderer {
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree,
|
||||
@@ -222,7 +329,18 @@ public class ArrangementRuleTree {
|
||||
boolean hasFocus)
|
||||
{
|
||||
ArrangementSettingsNode node = (ArrangementSettingsNode)((DefaultMutableTreeNode)value).getUserObject();
|
||||
return getComponent(row, node).getUiComponent();
|
||||
return getNodeComponentAt(row, node).getUiComponent();
|
||||
}
|
||||
}
|
||||
|
||||
private class MySelectionModel extends DefaultTreeSelectionModel {
|
||||
|
||||
@Override
|
||||
public void setSelectionPath(TreePath path) {
|
||||
if (!mySkipSelectionChange) {
|
||||
super.setSelectionPath(path);
|
||||
notifyEditingListeners(getActiveSettings());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-3
@@ -21,12 +21,17 @@ import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import org.jdesktop.swingx.JXTaskPane;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
@@ -41,11 +46,31 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
|
||||
public ArrangementSettingsPanel(@NotNull CodeStyleSettings settings, @NotNull ArrangementStandardSettingsAware filter) {
|
||||
super(settings);
|
||||
Tree component = new ArrangementRuleTree(filter).getTreeComponent();
|
||||
myContent.add(component, new GridBag().weightx(1).weighty(1).fillCell());
|
||||
final ArrangementRuleTree ruleTree = new ArrangementRuleTree(filter);
|
||||
Tree component = ruleTree.getTreeComponent();
|
||||
myContent.add(new JBScrollPane(component), new GridBag().weightx(1).weighty(1).fillCell().coverLine());
|
||||
CustomizationUtil.installPopupHandler(
|
||||
component, ArrangementConstants.ACTION_GROUP_RULE_EDITOR_CONTEXT_MENU, ArrangementConstants.RULE_EDITOR_PLACE
|
||||
);
|
||||
|
||||
final JXTaskPane editorPane = new JXTaskPane(ApplicationBundle.message("arrangement.title.editor"));
|
||||
final ArrangementMatcherRuleEditor ruleEditor = new ArrangementMatcherRuleEditor(filter);
|
||||
editorPane.add(ruleEditor);
|
||||
editorPane.setCollapsed(true);
|
||||
myContent.add(editorPane, new GridBag().weightx(1).fillCellHorizontally().coverLine());
|
||||
|
||||
ruleTree.addEditingListener(new ArrangementMatcherEditingListener() {
|
||||
@Override
|
||||
public void startEditing(@NotNull ArrangementMatcherSettings settings) {
|
||||
ruleEditor.updateState(settings);
|
||||
editorPane.setCollapsed(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopEditing() {
|
||||
editorPane.setCollapsed(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,6 +102,6 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
|
||||
@Override
|
||||
protected String getTabTitle() {
|
||||
return ApplicationBundle.message("tab.title.arrangement");
|
||||
return ApplicationBundle.message("arrangement.title.settings.tab");
|
||||
}
|
||||
}
|
||||
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.application.options.codeStyle.arrangement.action;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementSettingsUtil;
|
||||
import com.intellij.application.options.codeStyle.arrangement.editor.ArrangementNodeEditor;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/13/12 11:52 AM
|
||||
*/
|
||||
public class ArrangementAddAndConditionAction extends AnAction {
|
||||
|
||||
public ArrangementAddAndConditionAction() {
|
||||
getTemplatePresentation().setText(ApplicationBundle.message("arrangement.action.add.and.node.text"));
|
||||
getTemplatePresentation().setDescription(ApplicationBundle.message("arrangement.action.add.and.node.description"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
Map<ArrangementSettingType, List<?>> availableSettings = ArrangementSettingsUtil.buildAvailableOptions(e.getDataContext());
|
||||
if (availableSettings.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ArrangementNodeDisplayManager displayManager = ArrangementSettingsUtil.DISPLAY_MANAGER.getData(e.getDataContext());
|
||||
if (displayManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
JComponent tree = ArrangementSettingsUtil.TREE.getData(e.getDataContext());
|
||||
if (tree == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Ref<Balloon> balloonRef = new Ref<Balloon>();
|
||||
ArrangementSettingsNode node = ArrangementSettingsUtil.getSettingsNode(e.getDataContext());
|
||||
Consumer<ArrangementSettingsAtomNode> consumer = new Consumer<ArrangementSettingsAtomNode>() {
|
||||
@Override
|
||||
public void consume(ArrangementSettingsAtomNode node) {
|
||||
// TODO den implement
|
||||
Balloon balloon = balloonRef.get();
|
||||
if (balloon != null) {
|
||||
balloon.hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (node == null) {
|
||||
// TODO den implement
|
||||
}
|
||||
else {
|
||||
ArrangementNodeEditor editor = new ArrangementNodeEditor(displayManager, availableSettings, consumer);
|
||||
editor.applyColorsFrom(tree);
|
||||
Balloon balloon = JBPopupFactory.getInstance().createBalloonBuilder(editor).setDisposable(project).setHideOnClickOutside(true)
|
||||
.setFillColor(tree.getBackground()).createBalloon();
|
||||
balloonRef.set(balloon);
|
||||
Point point = MouseInfo.getPointerInfo().getLocation();
|
||||
SwingUtilities.convertPointFromScreen(point, tree);
|
||||
balloon.show(new RelativePoint(tree, point), Balloon.Position.below);
|
||||
}
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.application.options.codeStyle.arrangement.editor;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Editor for choosing a single value from a set of predefined values.
|
||||
* <p/>
|
||||
* Not thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/13/12 4:15 PM
|
||||
*/
|
||||
public class ArrangementAtomEditor extends JPanel {
|
||||
|
||||
@NotNull private final Map<Object, Object> myValues = new HashMap<Object, Object>();
|
||||
|
||||
@NotNull private final Dimension myPrefSize;
|
||||
@NotNull private final JComboBox myValueBox;
|
||||
|
||||
public ArrangementAtomEditor(@NotNull Collection<?> values, @NotNull ArrangementNodeDisplayManager manager) {
|
||||
String[] uiValues = new String[values.size()];
|
||||
int i = 0;
|
||||
for (Object value : values) {
|
||||
String uiValue = manager.getDisplayValue(value);
|
||||
uiValues[i++] = uiValue;
|
||||
myValues.put(uiValue, value);
|
||||
}
|
||||
Arrays.sort(uiValues);
|
||||
myValueBox = new JComboBox(uiValues);
|
||||
setLayout(new GridBagLayout());
|
||||
add(myValueBox, new GridBag().anchor(GridBagConstraints.CENTER).weightx(1).fillCellHorizontally());
|
||||
|
||||
FontMetrics metrics = myValueBox.getFontMetrics(myValueBox.getFont());
|
||||
int maxWidth = 0;
|
||||
String widestText = null;
|
||||
for (String value : uiValues) {
|
||||
int width = metrics.stringWidth(value);
|
||||
if (width > maxWidth) {
|
||||
widestText = value;
|
||||
maxWidth = width;
|
||||
}
|
||||
}
|
||||
if (widestText != null) {
|
||||
myValueBox.setSelectedItem(widestText);
|
||||
}
|
||||
myPrefSize = super.getPreferredSize();
|
||||
if (uiValues.length > 0) {
|
||||
myValueBox.setSelectedItem(uiValues[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Object getValue() {
|
||||
return myValues.get(myValueBox.getSelectedItem());
|
||||
}
|
||||
|
||||
public void applyColorsFrom(@NotNull JComponent component) {
|
||||
myValueBox.setBackground(component.getBackground());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMaximumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return myPrefSize;
|
||||
}
|
||||
}
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.application.options.codeStyle.arrangement.editor;
|
||||
|
||||
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/13/12 12:33 PM
|
||||
*/
|
||||
public class ArrangementNodeEditor extends JPanel {
|
||||
|
||||
@NotNull private final CardLayout myCardLayout = new CardLayout();
|
||||
@NotNull private final JPanel myValuePanel = new JPanel(myCardLayout);
|
||||
@NotNull private final Map<String, ArrangementAtomEditor> myEditors = new HashMap<String, ArrangementAtomEditor>();
|
||||
|
||||
@NotNull private final ArrangementNodeDisplayManager myDisplayManager;
|
||||
@NotNull private final JComboBox myTypeComboBox;
|
||||
@NotNull private final JCheckBox myNegateCheckBox;
|
||||
@NotNull private final Dimension myPrefSize;
|
||||
@NotNull private String myCurrentCard;
|
||||
|
||||
public ArrangementNodeEditor(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@NotNull Map<ArrangementSettingType, List<?>> settings,
|
||||
@NotNull final Consumer<ArrangementSettingsAtomNode> resultProcessor)
|
||||
{
|
||||
myDisplayManager = manager;
|
||||
|
||||
setOpaque(false);
|
||||
setBorder(IdeBorderFactory.createEmptyBorder(0, 8, 0, 8));
|
||||
setLayout(new GridBagLayout());
|
||||
|
||||
myTypeComboBox = new JComboBox();
|
||||
ArrangementSettingType[] types = settings.keySet().toArray(new ArrangementSettingType[settings.size()]);
|
||||
Arrays.sort(types, new Comparator<ArrangementSettingType>() {
|
||||
@Override
|
||||
public int compare(ArrangementSettingType o1, ArrangementSettingType o2) {
|
||||
return myDisplayManager.getDisplayValue(o1).compareTo(myDisplayManager.getDisplayValue(o2));
|
||||
}
|
||||
});
|
||||
|
||||
final Map<Object, ArrangementSettingType> uiText2Type = new HashMap<Object, ArrangementSettingType>();
|
||||
for (ArrangementSettingType type : types) {
|
||||
String displayValue = myDisplayManager.getDisplayValue(type);
|
||||
uiText2Type.put(displayValue, type);
|
||||
myTypeComboBox.addItem(displayValue);
|
||||
}
|
||||
myTypeComboBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
myCardLayout.show(myValuePanel, myCurrentCard = e.getItem().toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
add(myTypeComboBox, new GridBag().insets(0, 3, 0, 0));
|
||||
|
||||
int maxWidth = 0;
|
||||
String widestCardName = null;
|
||||
for (Map.Entry<ArrangementSettingType, List<?>> entry : settings.entrySet()) {
|
||||
List<String> values = new ArrayList<String>();
|
||||
for (Object o : entry.getValue()) {
|
||||
values.add(myDisplayManager.getDisplayValue(o));
|
||||
Collections.sort(values);
|
||||
}
|
||||
ArrangementAtomEditor atomEditor = new ArrangementAtomEditor(values, manager);
|
||||
String cardName = myDisplayManager.getDisplayValue(entry.getKey());
|
||||
myEditors.put(cardName, atomEditor);
|
||||
myValuePanel.add(atomEditor, cardName);
|
||||
Dimension size = atomEditor.getPreferredSize();
|
||||
if (maxWidth < size.width) {
|
||||
widestCardName = cardName;
|
||||
maxWidth = size.width;
|
||||
}
|
||||
}
|
||||
add(myValuePanel, new GridBag().insets(0, 8, 0, 0).fillCellHorizontally().weightx(1).coverLine());
|
||||
|
||||
myNegateCheckBox = new JCheckBox(ApplicationBundle.message("arrangement.text.negate"));
|
||||
add(myNegateCheckBox, new GridBag().insets(0, 0, 0, 0).anchor(GridBagConstraints.WEST).coverLine());
|
||||
|
||||
JButton okButton = new JButton(AllIcons.Actions.Checked);
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ArrangementSettingType type = uiText2Type.get(myTypeComboBox.getSelectedItem());
|
||||
Object value = myEditors.get(myCurrentCard).getValue();
|
||||
resultProcessor.consume(new ArrangementSettingsAtomNode(type, value));
|
||||
}
|
||||
});
|
||||
add(okButton, new GridBag().insets(0, 3, 0, 0).weightx(1).fillCellHorizontally().coverLine());
|
||||
|
||||
if (widestCardName != null) {
|
||||
myCardLayout.show(myValuePanel, widestCardName);
|
||||
myPrefSize = super.getPreferredSize();
|
||||
}
|
||||
else {
|
||||
myPrefSize = super.getPreferredSize();
|
||||
}
|
||||
|
||||
myCardLayout.show(myValuePanel, myCurrentCard = myTypeComboBox.getSelectedItem().toString());
|
||||
}
|
||||
|
||||
public void applyColorsFrom(@NotNull JComponent component) {
|
||||
myTypeComboBox.setBackground(component.getBackground());
|
||||
myNegateCheckBox.setBackground(component.getBackground());
|
||||
for (ArrangementAtomEditor editor : myEditors.values()) {
|
||||
editor.applyColorsFrom(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMaximumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return myPrefSize;
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
|
||||
TreeUI actualUI = ui;
|
||||
if (!isCustomUI()) {
|
||||
if (!(ui instanceof WideSelectionTreeUI) && isWideSelection() && !UIUtil.isUnderGTKLookAndFeel()) {
|
||||
actualUI = new WideSelectionTreeUI(isWideSelection(), !SystemInfo.isMac);
|
||||
actualUI = new WideSelectionTreeUI(isWideSelection(), isAlwaysPaintRowBackground());
|
||||
}
|
||||
}
|
||||
super.setUI(actualUI);
|
||||
@@ -140,6 +140,10 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isAlwaysPaintRowBackground() {
|
||||
return !SystemInfo.isMac;
|
||||
}
|
||||
|
||||
public boolean isFileColorsEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -550,7 +550,8 @@ desktop.entry.sudo.prompt=Please enter your password to create a desktop entry
|
||||
title.tabs.and.indents=Tabs and Indents
|
||||
|
||||
# Arrangement
|
||||
tab.title.arrangement=Arrangement
|
||||
arrangement.action.add.and.node.text=And
|
||||
arrangement.action.add.and.node.description=Add 'and' condition
|
||||
arrangement.title.settings.tab=Arrangement
|
||||
arrangement.title.editor=Edit rule
|
||||
arrangement.text.type=Type
|
||||
arrangement.text.modifier=Modifier
|
||||
arrangement.text.negate=Negate
|
||||
@@ -809,9 +809,7 @@
|
||||
</group>
|
||||
|
||||
<group id="Arrangement.RuleEditor.Context.Menu">
|
||||
<action id="Arrangement.AddNode"
|
||||
class="com.intellij.application.options.codeStyle.arrangement.action.ArrangementAddAndConditionAction"
|
||||
icon="AllIcons.General.Add"/>
|
||||
<!--TODO den implement-->
|
||||
</group>
|
||||
|
||||
</actions>
|
||||
|
||||
@@ -1169,7 +1169,7 @@ public class StringUtil extends StringUtilRt {
|
||||
result.append(item).append(separator);
|
||||
}
|
||||
if (result.length() > 0) {
|
||||
result.setLength(result.length() - 1);
|
||||
result.setLength(result.length() - separator.length());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
+18
-4
@@ -1,6 +1,20 @@
|
||||
package org.jetbrains.plugins.gradle.ui;
|
||||
/*
|
||||
* Copyright 2000-2012 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.util.ui;
|
||||
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -14,8 +28,8 @@ import java.awt.*;
|
||||
* and calculates the height. If the user has an ability to manually change panel size (e.g. indirectly via changing
|
||||
* size of the dialog that serves as a container for the panel), that width is used as a maximum width.
|
||||
*
|
||||
* @author: Denis Zhdanov
|
||||
* @since: Jul 28, 2008
|
||||
* @author Denis Zhdanov
|
||||
* @since Jul 28, 2008
|
||||
*/
|
||||
public class MultiRowFlowPanel extends JPanel {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.plugins.gradle.ui;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ui.MultiRowFlowPanel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user