diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java index c7bab6b06867..bfd25ce8f0b0 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java @@ -228,6 +228,14 @@ public class BuildArtifactsBeforeRunTaskProvider extends BeforeRunTaskProvider buildArtifactsTasks = runManager.getBeforeRunTasks(configuration, ID); + if (buildArtifactsTasks.isEmpty()) { //Add new task if absent + BuildArtifactsBeforeRunTask task = new BuildArtifactsBeforeRunTask(project); + buildArtifactsTasks.add(task); + List tasks = runManager.getBeforeRunTasks(configuration); + tasks.add(task); + runManager.setBeforeRunTasks(configuration, tasks, false); + } + for (BuildArtifactsBeforeRunTask task : buildArtifactsTasks) { task.setEnabled(true); task.addArtifact(artifact); diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java index 53db32ecfb51..dcd0454c16aa 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java @@ -33,6 +33,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.util.containers.HashMap; @@ -148,7 +149,7 @@ public class JavaMarkObjectActionHandler extends MarkObjectActionHandler { if (node instanceof DebuggerTreeNodeImpl) { final DebuggerTreeNodeImpl _node = (DebuggerTreeNodeImpl)node; final NodeDescriptorImpl descriptor = _node.getDescriptor(); - if (descriptor instanceof ValueDescriptor && value.equals(((ValueDescriptor)descriptor).getValue())) { + if (descriptor instanceof ValueDescriptor && Comparing.equal(value, ((ValueDescriptor)descriptor).getValue())) { _node.labelChanged(); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index aeda55d6c3f6..1136db3dd846 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -447,10 +447,12 @@ public abstract class DebugProcessImpl implements DebugProcess { try { if (thread != null && thread.frameCount() > 0) { StackFrameProxyImpl stackFrame = thread.frame(0); - Location location = stackFrame.location(); - ReferenceType referenceType = location.declaringType(); - if (referenceType != null) { - return referenceType.name(); + if (stackFrame != null) { + Location location = stackFrame.location(); + ReferenceType referenceType = location.declaringType(); + if (referenceType != null) { + return referenceType.name(); + } } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java index 6d50a9264241..33cf0e16f211 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java @@ -19,13 +19,12 @@ import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.actions.*; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.settings.*; -import com.intellij.debugger.ui.breakpoints.Breakpoint; -import com.intellij.debugger.ui.breakpoints.BreakpointFactory; -import com.intellij.debugger.ui.breakpoints.BreakpointPanel; -import com.intellij.debugger.ui.breakpoints.BreakpointWithHighlighter; +import com.intellij.debugger.ui.breakpoints.*; import com.intellij.ide.DataManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; @@ -33,6 +32,9 @@ import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Key; +import com.intellij.ui.popup.util.ItemWrapper; +import com.intellij.ui.popup.util.SplitterItem; import com.intellij.xdebugger.AbstractDebuggerSession; import com.intellij.xdebugger.impl.DebuggerSupport; import com.intellij.xdebugger.impl.actions.DebuggerActionHandler; @@ -48,6 +50,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * @author nik @@ -184,10 +187,12 @@ public class JavaDebuggerSupport extends DebuggerSupport { } private static class JavaBreakpointPanelProvider extends BreakpointPanelProvider { + private List myListeners = new CopyOnWriteArrayList(); + @NotNull public Collection> getBreakpointPanels(@NotNull final Project project, @NotNull final DialogWrapper parentDialog) { List> panels = new ArrayList>(); - final BreakpointFactory[] allFactories = ApplicationManager.getApplication().getExtensions(BreakpointFactory.EXTENSION_POINT_NAME); + final BreakpointFactory[] allFactories = BreakpointFactory.getBreakpointFactories(); for (BreakpointFactory factory : allFactories) { BreakpointPanel panel = factory.createBreakpointPanel(project, parentDialog); if (panel != null) { @@ -198,6 +203,33 @@ public class JavaDebuggerSupport extends DebuggerSupport { return panels; } + @Override + public AnAction[] getAddBreakpointActions(@NotNull Project project) { + List result = new ArrayList(); + BreakpointFactory[] breakpointFactories = BreakpointFactory.getBreakpointFactories(); + for (BreakpointFactory breakpointFactory : breakpointFactories) { + result.add(new AddJavaBreakpointAction(breakpointFactory)); + } + return result.toArray(new AnAction[result.size()]); + } + + @Override + public void addListener(final BreakpointsListener listener, Project project) { + final MyBreakpointManagerListener listener1 = new MyBreakpointManagerListener(listener); + DebuggerManagerEx.getInstanceEx(getCurrentProject()).getBreakpointManager().addBreakpointManagerListener(listener1); + myListeners.add(listener1); + } + + @Override + public void removeListener(BreakpointsListener listener) { + for (MyBreakpointManagerListener managerListener : myListeners) { + if (managerListener.myListener == listener) { + myListeners.remove(managerListener); + break; + } + } + } + public int getPriority() { return 1; } @@ -220,6 +252,55 @@ public class JavaDebuggerSupport extends DebuggerSupport { public void onDialogClosed(final Project project) { DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().updateAllRequests(); } + + @Override + public void provideBreakpointItems(Project project, Collection items) { + for (BreakpointFactory breakpointFactory : BreakpointFactory.getBreakpointFactories()) { + Key category = breakpointFactory.getBreakpointCategory(); + Breakpoint[] breakpoints = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getBreakpoints(category); + if (breakpoints.length > 0) { + items.add(new SplitterItem(breakpointFactory.getDisplayName())); + } + for (Breakpoint breakpoint : breakpoints) { + items.add(breakpointFactory.createBreakpointItem(breakpoint)); + } + } + } + + private static class AddJavaBreakpointAction extends AnAction { + private BreakpointFactory myBreakpointFactory; + + public AddJavaBreakpointAction(BreakpointFactory breakpointFactory) { + myBreakpointFactory = breakpointFactory; + Presentation p = getTemplatePresentation(); + p.setIcon(myBreakpointFactory.getIcon()); + p.setText(breakpointFactory.getDisplayName()); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setVisible(myBreakpointFactory.canAddBreakpoints()); + } + + @Override + public void actionPerformed(AnActionEvent e) { + myBreakpointFactory.addBreakpoint(getEventProject(e)); + } + } + + private static class MyBreakpointManagerListener implements BreakpointManagerListener { + + private final BreakpointsListener myListener; + + public MyBreakpointManagerListener(BreakpointsListener listener) { + myListener = listener; + } + + @Override + public void breakpointsChanged() { + myListener.breakpointsChanged(); + } + } } public static class JavaDebuggerSettingsPanelProvider extends DebuggerSettingsPanelProvider { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java index f7232701bc4c..57be8b16bf3b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java @@ -27,6 +27,7 @@ import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.ThreadReferenceProxyImpl; import com.intellij.debugger.ui.breakpoints.*; import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -300,7 +301,7 @@ public class PositionHighlighter { try { StackFrameProxyImpl frameProxy = myContext.getFrameProxy(); final ThreadReferenceProxyImpl thread = getSuspendContext().getThread(); - isExecutionPoint = thread != null && frameProxy.equals(thread.frame(0)); + isExecutionPoint = thread != null && frameProxy != null && frameProxy.equals(thread.frame(0)); } catch(Throwable th) { LOG.debug(th); @@ -410,7 +411,7 @@ public class PositionHighlighter { DefaultActionGroup group = new DefaultActionGroup(); for (Pair eventDescriptor : myEventsOutOfLine) { Breakpoint breakpoint = eventDescriptor.getFirst(); - ViewBreakpointsAction viewBreakpointsAction = new ViewBreakpointsAction(breakpoint.getDisplayName(), breakpoint); + AnAction viewBreakpointsAction = new ViewBreakpointsAction(breakpoint.getDisplayName(), breakpoint); group.add(viewBreakpointsAction); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java index 3f95b3fb39a5..69e72b01342e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java @@ -62,6 +62,11 @@ public class AnyExceptionBreakpointFactory extends BreakpointFactory{ return new BreakpointPanelAction[0]; //To change body of implemented methods use File | Settings | File Templates. } + @Override + public boolean breakpointCanBeRemoved(Breakpoint breakpoint) { + return false; + } + public @Nullable BreakpointPanel createBreakpointPanel(Project project, DialogWrapper parentDialog) { return null; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java index 4829f5866a64..3d5d52fab2dc 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java @@ -21,6 +21,7 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Key; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import org.jdom.Element; import org.jetbrains.annotations.Nullable; @@ -30,17 +31,21 @@ import javax.swing.*; * Used to deexternalize breakpoints of certain category while reading saved configuration and for creating configuration UI */ public abstract class BreakpointFactory { - public static final ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.debugger.breakpointFactory"); + public static final ExtensionPointName EXTENSION_POINT_NAME = + ExtensionPointName.create("com.intellij.debugger.breakpointFactory"); + + public static BreakpointFactory[] getBreakpointFactories() { + return ApplicationManager.getApplication().getExtensions(EXTENSION_POINT_NAME); + } public abstract Breakpoint createBreakpoint(Project project, final Element element); public abstract Key getBreakpointCategory(); public BreakpointPanel createBreakpointPanel(final Project project, final DialogWrapper parentDialog) { - BreakpointPanel panel = new BreakpointPanel(project, - createBreakpointPropertiesPanel(project, false), - createBreakpointPanelActions(project, parentDialog), - getBreakpointCategory(), getDisplayName(), getHelpID()); + BreakpointPanel panel = + new BreakpointPanel(project, createBreakpointPropertiesPanel(project, false), createBreakpointPanelActions(project, parentDialog), + getBreakpointCategory(), getDisplayName(), getHelpID()); configureBreakpointPanel(panel); return panel; } @@ -51,7 +56,7 @@ public abstract class BreakpointFactory { @Nullable public static BreakpointFactory getInstance(Key category) { - final BreakpointFactory[] allFactories = ApplicationManager.getApplication().getExtensions(BreakpointFactory.EXTENSION_POINT_NAME); + final BreakpointFactory[] allFactories = getBreakpointFactories(); for (final BreakpointFactory factory : allFactories) { if (category.equals(factory.getBreakpointCategory())) { return factory; @@ -60,13 +65,32 @@ public abstract class BreakpointFactory { return null; } - protected void configureBreakpointPanel(BreakpointPanel panel){}; + protected void configureBreakpointPanel(BreakpointPanel panel) { + } protected abstract String getHelpID(); public abstract String getDisplayName(); + @Nullable public abstract BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact); protected abstract BreakpointPanelAction[] createBreakpointPanelActions(Project project, DialogWrapper parentDialog); + + @Nullable + public Breakpoint addBreakpoint(Project project) { + return null; + } + + public boolean canAddBreakpoints() { + return false; + } + + public boolean breakpointCanBeRemoved(Breakpoint breakpoint) { + return true; + } + + public BreakpointItem createBreakpointItem(final Breakpoint breakpoint) { + return new JavaBreakpointItem(this, breakpoint); + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java index f1e295138472..e16066e5ddb9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java @@ -51,6 +51,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; @@ -108,6 +110,17 @@ public abstract class BreakpointPropertiesPanel { private static final int MAX_COMBO_WIDTH = 300; private final FixedSizeButton myConditionMagnifierButton; private boolean myMoreOptionsVisible = true; + private Breakpoint myBreakpoint; + + public boolean isSaveOnRemove() { + return mySaveOnRemove; + } + + public void setSaveOnRemove(boolean saveOnRemove) { + mySaveOnRemove = saveOnRemove; + } + + private boolean mySaveOnRemove = false; public boolean isMoreOptionsVisible() { return myMoreOptionsVisible; @@ -116,13 +129,14 @@ public abstract class BreakpointPropertiesPanel { private void createUIComponents() { myPanel = new JPanel() { @Override - public boolean requestFocus(boolean b) { - return super.requestFocus(b); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void requestFocus() { - super.requestFocus(); //To change body of overridden methods use File | Settings | File Templates. + public void removeNotify() { + super.removeNotify(); + if (mySaveOnRemove) { + saveTo(myBreakpoint, new Runnable() { + @Override + public void run() {} + }); + } } }; } @@ -262,6 +276,24 @@ public abstract class BreakpointPropertiesPanel { myBreakpointComboboxHandler = new BreakpointComboboxHandler(myProject, baseBreakpointCombo); baseBreakpointCombo.setRenderer(new BreakpointComboRenderer(baseBreakpointCombo.getRenderer())); + baseBreakpointCombo.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent event) { + event.getClass();//To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent event) { + //To change body of implemented methods use File | Settings | File Templates. + event.getClass(); + } + + @Override + public void popupMenuCanceled(PopupMenuEvent event) { + //To change body of implemented methods use File | Settings | File Templates. + event.getClass(); + } + }); baseBreakpointCombo.addItemListener(new ItemListener() { public void itemStateChanged(final ItemEvent e) { ComboboxItem item = (ComboboxItem)baseBreakpointCombo.getSelectedItem(); @@ -392,6 +424,7 @@ public abstract class BreakpointPropertiesPanel { * Init UI components with the values from Breakpoint */ public void initFrom(Breakpoint breakpoint, boolean moreOptionsVisible1) { + myBreakpoint = breakpoint; boolean moreOptionsVisible = moreOptionsVisible1; boolean actionsPanelVisible = moreOptionsVisible1; myBreakpointComboboxHandler.initFrom(breakpoint); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java index 79cc37541e60..2e52109b5ae4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java @@ -637,7 +637,8 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { } } - ViewBreakpointsAction viewBreakpointsAction = + + AnAction viewBreakpointsAction = new ViewBreakpointsAction(ActionsBundle.actionText(XDebuggerActions.VIEW_BREAKPOINTS), this); DefaultActionGroup group = new DefaultActionGroup(); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java index aa3165d2151f..255d3cbef5f1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java @@ -39,7 +39,7 @@ import java.awt.event.ActionEvent; * @author Eugene Zhuravlev * Date: Apr 26, 2005 */ -public class ExceptionBreakpointFactory extends BreakpointFactory{ +public class ExceptionBreakpointFactory extends BreakpointFactory { public Breakpoint createBreakpoint(Project project, final Element element) { return new ExceptionBreakpoint(project); } @@ -77,47 +77,43 @@ public class ExceptionBreakpointFactory extends BreakpointFactory{ protected BreakpointPanelAction[] createBreakpointPanelActions(final Project project, DialogWrapper parentDialog) { return new BreakpointPanelAction[]{ new SwitchViewAction(), - new AddExceptionBreakpointAction(project), + new AddAction(this, project), new RemoveAction(project) { - public void update() { - super.update(); - if (getButton().isEnabled()) { - Breakpoint[] selectedBreakpoints = getPanel().getSelectedBreakpoints(); - for (Breakpoint bp : selectedBreakpoints) { - if (bp instanceof AnyExceptionBreakpoint) { - getButton().setEnabled(false); - } + public void update() { + super.update(); + if (getButton().isEnabled()) { + Breakpoint[] selectedBreakpoints = getPanel().getSelectedBreakpoints(); + for (Breakpoint bp : selectedBreakpoints) { + if (bp instanceof AnyExceptionBreakpoint) { + getButton().setEnabled(false); } } } - }, - new ToggleGroupByClassesAction(), - new ToggleFlattenPackagesAction(), - }; + } + }, new ToggleGroupByClassesAction(), new ToggleFlattenPackagesAction(),}; } - public BreakpointPanel createBreakpointPanel(final Project project, final DialogWrapper parentDialog) { - BreakpointPanel panel = new BreakpointPanel(project, - createBreakpointPropertiesPanel(project, false), - createBreakpointPanelActions(project, parentDialog), - getBreakpointCategory(), getDisplayName(), getHelpID()){ - public void resetBreakpoints() { - super.resetBreakpoints(); - Breakpoint[] breakpoints = getBreakpointManager().getBreakpoints(getBreakpointCategory()); - final AnyExceptionBreakpoint anyExceptionBreakpoint = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getAnyExceptionBreakpoint(); - boolean found = false; - for (Breakpoint breakpoint : breakpoints) { - if (breakpoint.equals(anyExceptionBreakpoint)) { - found = true; - break; + BreakpointPanel panel = + new BreakpointPanel(project, createBreakpointPropertiesPanel(project, false), createBreakpointPanelActions(project, parentDialog), + getBreakpointCategory(), getDisplayName(), getHelpID()) { + public void resetBreakpoints() { + super.resetBreakpoints(); + Breakpoint[] breakpoints = getBreakpointManager().getBreakpoints(getBreakpointCategory()); + final AnyExceptionBreakpoint anyExceptionBreakpoint = + DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getAnyExceptionBreakpoint(); + boolean found = false; + for (Breakpoint breakpoint : breakpoints) { + if (breakpoint.equals(anyExceptionBreakpoint)) { + found = true; + break; + } + } + if (!found) { + insertBreakpointAt(anyExceptionBreakpoint, 0); } } - if (!found) { - insertBreakpointAt(anyExceptionBreakpoint, 0); - } - } - }; + }; configureBreakpointPanel(panel); return panel; } @@ -126,29 +122,27 @@ public class ExceptionBreakpointFactory extends BreakpointFactory{ return ExceptionBreakpoint.CATEGORY; } - private static class AddExceptionBreakpointAction extends AddAction { - private final Project myProject; - - public AddExceptionBreakpointAction(Project project) { - myProject = project; - } - - public void actionPerformed(ActionEvent e) { - final PsiClass throwableClass = - JavaPsiFacade.getInstance(myProject).findClass("java.lang.Throwable", GlobalSearchScope.allScope(myProject)); - TreeClassChooser chooser = - TreeClassChooserFactory.getInstance(myProject).createInheritanceClassChooser( - DebuggerBundle.message("add.exception.breakpoint.classchooser.title"), GlobalSearchScope.allScope(myProject), - throwableClass, true, true, null); - chooser.showDialog(); - PsiClass selectedClass = chooser.getSelected(); - String qName = selectedClass == null ? null : JVMNameUtil.getNonAnonymousClassName(selectedClass); - - if (qName != null && qName.length() > 0) { - ExceptionBreakpoint breakpoint = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addExceptionBreakpoint(qName, ((PsiClassOwner)selectedClass.getContainingFile()).getPackageName()); - getPanel().addBreakpoint(breakpoint); - } - } + @Override + public boolean canAddBreakpoints() { + return true; } + @Override + public Breakpoint addBreakpoint(Project project) { + ExceptionBreakpoint breakpoint = null; + final PsiClass throwableClass = + JavaPsiFacade.getInstance(project).findClass("java.lang.Throwable", GlobalSearchScope.allScope(project)); + TreeClassChooser chooser = TreeClassChooserFactory.getInstance(project) + .createInheritanceClassChooser(DebuggerBundle.message("add.exception.breakpoint.classchooser.title"), + GlobalSearchScope.allScope(project), throwableClass, true, true, null); + chooser.showDialog(); + PsiClass selectedClass = chooser.getSelected(); + String qName = selectedClass == null ? null : JVMNameUtil.getNonAnonymousClassName(selectedClass); + + if (qName != null && qName.length() > 0) { + breakpoint = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager() + .addExceptionBreakpoint(qName, ((PsiClassOwner)selectedClass.getContainingFile()).getPackageName()); + } + return breakpoint; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java index c98bc77834b4..738097173c61 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import org.jdom.Element; @@ -73,7 +74,7 @@ public class FieldBreakpointFactory extends BreakpointFactory{ protected BreakpointPanelAction[] createBreakpointPanelActions(final Project project, final DialogWrapper parentDialog) { return new BreakpointPanelAction[] { new SwitchViewAction(), - new AddFieldBreakpointAction(project), + new AddAction(this, project), new GotoSourceAction(project) { public void actionPerformed(ActionEvent e) { super.actionPerformed(e); @@ -91,65 +92,61 @@ public class FieldBreakpointFactory extends BreakpointFactory{ return FieldBreakpoint.CATEGORY; } - private static class AddFieldBreakpointAction extends AddAction { - private final Project myProject; - - public AddFieldBreakpointAction(Project project) { - myProject = project; - } - - public void actionPerformed(ActionEvent e) { - AddFieldBreakpointDialog dialog = new AddFieldBreakpointDialog(myProject) { - protected boolean validateData() { - String className = getClassName(); - if (className.length() == 0) { - Messages.showMessageDialog(myProject, DebuggerBundle.message("error.field.breakpoint.class.name.not.specified"), - DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon()); - return false; - } - String fieldName = getFieldName(); - if (fieldName.length() == 0) { - Messages.showMessageDialog(myProject, DebuggerBundle.message("error.field.breakpoint.field.name.not.specified"), - DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon()); - return false; - } - PsiClass psiClass = JavaPsiFacade.getInstance(myProject).findClass(className, GlobalSearchScope.allScope(myProject)); - if (psiClass != null) { - PsiFile psiFile = psiClass.getContainingFile(); - Document document = PsiDocumentManager.getInstance(myProject).getDocument(psiFile); - if(document != null) { - PsiField field = psiClass.findFieldByName(fieldName, true); - if(field != null) { - int line = document.getLineNumber(field.getTextOffset()); - FieldBreakpoint fieldBreakpoint = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addFieldBreakpoint(document, line, fieldName); - if (fieldBreakpoint != null) { - getPanel().addBreakpoint(fieldBreakpoint); - return true; - } - } - else { - Messages.showMessageDialog( - myProject, - DebuggerBundle.message("error.field.breakpoint.field.not.found", className, fieldName, fieldName), - CommonBundle.getErrorTitle(), - Messages.getErrorIcon() - ); - - } - } - } else { - Messages.showMessageDialog( - myProject, - DebuggerBundle.message("error.field.breakpoint.class.sources.not.found", className, fieldName, className), - CommonBundle.getErrorTitle(), - Messages.getErrorIcon() - ); - } + @Override + public Breakpoint addBreakpoint(final Project project) { + final Ref result = Ref.create(null); + AddFieldBreakpointDialog dialog = new AddFieldBreakpointDialog(project) { + protected boolean validateData() { + String className = getClassName(); + if (className.length() == 0) { + Messages.showMessageDialog(project, DebuggerBundle.message("error.field.breakpoint.class.name.not.specified"), + DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon()); return false; } - }; - dialog.show(); - } + String fieldName = getFieldName(); + if (fieldName.length() == 0) { + Messages.showMessageDialog(project, DebuggerBundle.message("error.field.breakpoint.field.name.not.specified"), + DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon()); + return false; + } + PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project)); + if (psiClass != null) { + PsiFile psiFile = psiClass.getContainingFile(); + Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile); + if(document != null) { + PsiField field = psiClass.findFieldByName(fieldName, true); + if(field != null) { + int line = document.getLineNumber(field.getTextOffset()); + FieldBreakpoint fieldBreakpoint = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().addFieldBreakpoint(document, line, fieldName); + if (fieldBreakpoint != null) { + result.set(fieldBreakpoint); + return true; + } + } + else { + Messages.showMessageDialog(project, + DebuggerBundle.message("error.field.breakpoint.field.not.found", className, fieldName, fieldName), + CommonBundle.getErrorTitle(), + Messages.getErrorIcon() + ); + } + } + } else { + Messages.showMessageDialog(project, + DebuggerBundle.message("error.field.breakpoint.class.sources.not.found", className, fieldName, className), + CommonBundle.getErrorTitle(), + Messages.getErrorIcon() + ); + } + return false; + } + }; + dialog.show(); + return result.get(); } + @Override + public boolean canAddBreakpoints() { + return true; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java new file mode 100644 index 000000000000..4a16d4120bf5 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -0,0 +1,128 @@ +/* + * 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.debugger.ui.breakpoints; + +import com.intellij.debugger.DebuggerManagerEx; +import com.intellij.debugger.SourcePosition; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: intendia +* Date: 10.05.12 +* Time: 3:16 +* To change this template use File | Settings | File Templates. +*/ +class JavaBreakpointItem implements BreakpointItem { + private final Breakpoint myBreakpoint; + private BreakpointFactory myBreakpointFactory; + + public JavaBreakpointItem(BreakpointFactory breakpointFactory, Breakpoint breakpoint) { + myBreakpointFactory = breakpointFactory; + myBreakpoint = breakpoint; + } + + @Override + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + renderer.setIcon(myBreakpoint.getIcon()); + renderer.append(myBreakpoint.getShortName()); + } + + @Override + public void updateMnemonicLabel(JLabel label) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void execute(Project project, JBPopup popup) { + if (myBreakpoint instanceof BreakpointWithHighlighter) { + final SourcePosition position = ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition(); + if (position != null) { + position.navigate(true); + popup.cancel(); + } + } + } + + @Override + public String speedSearchText() { + return myBreakpoint.getDisplayName(); + } + + @Override + public String footerText() { + return myBreakpoint.getDisplayName(); + } + + @Override + public void updateDetailView(DetailView panel) { + BreakpointPropertiesPanel breakpointPropertiesPanel = myBreakpointFactory + .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false); + if (breakpointPropertiesPanel != null) { + breakpointPropertiesPanel.setSaveOnRemove(true); + } + + if (breakpointPropertiesPanel != null) { + breakpointPropertiesPanel.initFrom(myBreakpoint, true); + final JPanel mainPanel = breakpointPropertiesPanel.getPanel(); + panel.setDetailPanel(mainPanel); + } + else { + panel.setDetailPanel(null); + } + + if (myBreakpoint instanceof BreakpointWithHighlighter) { + SourcePosition sourcePosition = ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition(); + VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile(); + panel.navigateInPreviewEditor(virtualFile, new LogicalPosition(sourcePosition.getLine(), 0)); + } else { + panel.clearEditor(); + } + } + + @Override + public boolean allowedToRemove() { + return myBreakpointFactory.breakpointCanBeRemoved(myBreakpoint); + } + + @Override + public void removed(Project project) { + DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().removeBreakpoint(myBreakpoint); + } + + @Override + public Object getBreakpoint() { + return myBreakpoint; + } + + @Override + public boolean isEnabled() { + return myBreakpoint.ENABLED; + } + + @Override + public void setEnabled(boolean state) { + myBreakpoint.ENABLED = state; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java index e7e14ece92ee..e3586870ec1e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java @@ -131,28 +131,17 @@ public class LineBreakpoint extends BreakpointWithHighlighter { } try { List locs = debugProcess.getPositionManager().locationsOfLine(classType, getSourcePosition()); - if (locs.size() > 0) { - Location minLocation = null; - for (final Location loc : locs) { - if (minLocation == null) { - minLocation = loc; + if (!locs.isEmpty()) { + for (Location loc : locs) { + if (LOG.isDebugEnabled()) { + LOG.debug("Found location [codeIndex=" + loc.codeIndex() +"] for reference type " + classType.name() + " at line " + getLineIndex() + "; isObsolete: " + (debugProcess.getVirtualMachineProxy().versionHigher("1.4") && loc.method().isObsolete())); } - else if (loc.codeIndex() < minLocation.codeIndex()) { - minLocation = loc; + BreakpointRequest request = debugProcess.getRequestsManager().createBreakpointRequest(LineBreakpoint.this, loc); + debugProcess.getRequestsManager().enableRequest(request); + if (LOG.isDebugEnabled()) { + LOG.debug("Created breakpoint request for reference type " + classType.name() + " at line " + getLineIndex() + "; codeIndex=" + loc.codeIndex()); } } - - assert minLocation != null; - - if (LOG.isDebugEnabled()) { - LOG.debug("Found location for reference type " + classType.name() + " at line " + getLineIndex() + "; isObsolete: " + (debugProcess.getVirtualMachineProxy().versionHigher("1.4") && minLocation - .method().isObsolete())); - } - BreakpointRequest request = debugProcess.getRequestsManager().createBreakpointRequest(LineBreakpoint.this, minLocation); - debugProcess.getRequestsManager().enableRequest(request); - if (LOG.isDebugEnabled()) { - LOG.debug("Created breakpoint request for reference type " + classType.name() + " at line " + getLineIndex()); - } } else { // there's no executable code in this class diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java index 1fa227eb76f3..9dd7c725a1b7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java @@ -63,7 +63,7 @@ public class MethodBreakpointFactory extends BreakpointFactory{ protected BreakpointPanelAction[] createBreakpointPanelActions(Project project, final DialogWrapper parentDialog) { return new BreakpointPanelAction[]{ new SwitchViewAction(), - new AddWildcardBreakpointAction(project), + new AddAction(this, project), new GotoSourceAction(project) { public void actionPerformed(ActionEvent e) { super.actionPerformed(e); @@ -87,23 +87,19 @@ public class MethodBreakpointFactory extends BreakpointFactory{ return MethodBreakpoint.CATEGORY; } - private static class AddWildcardBreakpointAction extends AddAction { - private final Project myProject; + @Override + public boolean canAddBreakpoints() { + return true; + } - public AddWildcardBreakpointAction(Project project) { - myProject = project; - } - - public void actionPerformed(ActionEvent e) { - AddWildcardBreakpointDialog dialog = new AddWildcardBreakpointDialog(myProject); - dialog.show(); - if (!dialog.isOK()) { - return; - } - final WildcardMethodBreakpoint methodBreakpoint = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addMethodBreakpoint(dialog.getClassPattern(), dialog.getMethodName()); - if (methodBreakpoint != null) { - getPanel().addBreakpoint(methodBreakpoint); - } - } + public WildcardMethodBreakpoint addBreakpoint(Project project) { + AddWildcardBreakpointDialog dialog = new AddWildcardBreakpointDialog(project); + dialog.show(); + WildcardMethodBreakpoint methodBreakpoint; + methodBreakpoint = !dialog.isOK() + ? null + : DebuggerManagerEx.getInstanceEx(project).getBreakpointManager() + .addMethodBreakpoint(dialog.getClassPattern(), dialog.getMethodName()); + return methodBreakpoint; } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/actions/AddAction.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/actions/AddAction.java index 9ecfc0084f82..8e3b37e9bff3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/actions/AddAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/actions/AddAction.java @@ -15,18 +15,28 @@ */ package com.intellij.debugger.ui.breakpoints.actions; +import com.intellij.debugger.ui.breakpoints.Breakpoint; +import com.intellij.debugger.ui.breakpoints.BreakpointFactory; import com.intellij.debugger.ui.breakpoints.BreakpointPanel; import com.intellij.ide.IdeBundle; +import com.intellij.openapi.project.Project; import javax.swing.*; +import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; /** * @author Eugene Zhuravlev * Date: May 25, 2005 - */public abstract class AddAction extends BreakpointPanelAction { - protected AddAction() { + */ +public class AddAction extends BreakpointPanelAction { + protected final Project myProject; + protected BreakpointFactory myBreakpointFactory; + + public AddAction(BreakpointFactory breakpointFactory, Project project) { super(IdeBundle.message("button.add")); + myProject = project; + this.myBreakpointFactory = breakpointFactory; } public void setPanel(BreakpointPanel panel) { @@ -36,4 +46,11 @@ import java.awt.event.KeyEvent; public void update() { } + + public void actionPerformed(ActionEvent e) { + Breakpoint breakpoint = myBreakpointFactory.addBreakpoint(myProject); + if (breakpoint != null) { + getPanel().addBreakpoint(breakpoint); + } + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java index 3a7469a87256..cffb3f0f1762 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -220,6 +220,7 @@ public class JavaDocCompletionContributor extends CompletionContributor { if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) { final PsiDocTagValue valueElement = tag.getValueElement(); endOffset = valueElement.getTextRange().getEndOffset(); + context.setTailOffset(endOffset); } editor.getDocument().deleteString(afterSharp, endOffset); editor.getCaretModel().moveToOffset(signatureOffset); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java index 402fbc3fde63..d966cb14d7a7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -18,6 +18,8 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.*; import com.intellij.codeInsight.completion.proc.VariablesProcessor; import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.generation.OverrideImplementUtil; +import com.intellij.codeInsight.generation.PsiGenerationInfo; import com.intellij.codeInsight.intention.impl.CreateClassDialog; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; @@ -129,7 +131,7 @@ public class CreateFromUsageUtils { returnType = PsiType.VOID; } - PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + JVMElementFactory factory = JVMElementFactories.getFactory(aClass.getLanguage(), aClass.getProject()); LOG.assertTrue(!aClass.isInterface(), "Interface bodies should be already set up"); @@ -190,7 +192,7 @@ public class CreateFromUsageUtils { PsiElement r = PsiTreeUtil.skipSiblingsBackward(body.getRBrace(), PsiWhiteSpace.class); if (l != null && r != null) { int start = l.getTextRange().getStartOffset(); - int end = r.getTextRange().getEndOffset(); + int end = r.getTextRange().getEndOffset(); newEditor.getCaretModel().moveToOffset(Math.max(start, end)); if (end < start) { newEditor.getCaretModel().moveToOffset(end + 1); @@ -200,8 +202,12 @@ public class CreateFromUsageUtils { PsiDocumentManager manager = PsiDocumentManager.getInstance(method.getProject()); manager.doPostponedOperationsAndUnblockDocument(manager.getDocument(containingFile)); EditorModificationUtil.insertStringAtCaret(newEditor, lineIndent); - } else { - newEditor.getSelectionModel().setSelection(Math.min(start, end), Math.max(start, end)); + EditorModificationUtil.insertStringAtCaret(newEditor, "\n", false, false); + } + else { + //correct position caret for groovy and java methods + final PsiGenerationInfo info = OverrideImplementUtil.createGenerationInfo(method); + info.positionCaret(newEditor, true); } newEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } @@ -225,13 +231,13 @@ public class CreateFromUsageUtils { final PsiSubstitutor substitutor, final List> arguments) throws IncorrectOperationException { PsiManager psiManager = method.getManager(); - PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory(); + JVMElementFactory factory = JVMElementFactories.getFactory(method.getLanguage(), method.getProject()); PsiParameterList parameterList = method.getParameterList(); GlobalSearchScope resolveScope = method.getResolveScope(); - GuessTypeParameters guesser = new GuessTypeParameters(factory); + GuessTypeParameters guesser = new GuessTypeParameters(JavaPsiFacade.getElementFactory(method.getProject())); final PsiClass containingClass = method.getContainingClass(); final boolean isInterface = containingClass != null && containingClass.isInterface(); @@ -943,6 +949,7 @@ public class CreateFromUsageUtils { @Nullable private static String getQualifiedName(final PsiClass aClass) { return ApplicationManager.getApplication().runReadAction(new Computable() { + @Nullable @Override public String compute() { return aClass.getQualifiedName(); @@ -993,7 +1000,16 @@ public class CreateFromUsageUtils { assert file != null; PsiElement elementAt = file.findElementAt(offset); PsiParameterList parameterList = PsiTreeUtil.getParentOfType(elementAt, PsiParameterList.class); - if (parameterList == null) return LookupElement.EMPTY_ARRAY; + if (parameterList == null) { + if (elementAt == null) return LookupElement.EMPTY_ARRAY; + final PsiElement parent = elementAt.getParent(); + if (parent instanceof PsiMethod) { + parameterList = ((PsiMethod)parent).getParameterList(); + } + else { + return LookupElement.EMPTY_ARRAY; + } + } PsiParameter parameter = PsiTreeUtil.getParentOfType(elementAt, PsiParameter.class); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java index 98c10eb8ad7a..8117897e5965 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -142,7 +142,10 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { String methodName = ref.getReferenceName(); LOG.assertTrue(methodName != null); - PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + JVMElementFactory factory = JVMElementFactories.getFactory(targetClass.getLanguage(), project); + if (factory == null) { + return; + } PsiMethod method = factory.createMethod(methodName, PsiType.VOID); @@ -251,7 +254,13 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { if (typeParameters.length > 0) { for (PsiTypeParameter typeParameter : typeParameters) { if (checkTypeParam( method, typeParameter)) { - method.getTypeParameterList().add(typeParameter); + final JVMElementFactory factory = JVMElementFactories.getFactory(method.getLanguage(), method.getProject()); + PsiTypeParameterList list = method.getTypeParameterList(); + if (list == null) { + PsiTypeParameterList newList = factory.createTypeParameterList(); + list = (PsiTypeParameterList)method.addAfter(newList, method.getModifierList()); + } + list.add(factory.createTypeParameter(typeParameter.getName(),typeParameter.getExtendsList().getReferencedTypes())); } } } @@ -276,32 +285,59 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { } } - private static boolean checkTypeParam(final PsiElement typeElement, - final PsiTypeParameter typeParameter) { + public static boolean checkTypeParam(final PsiMethod method, final PsiTypeParameter typeParameter) { final String typeParameterName = typeParameter.getName(); - final boolean[] found = new boolean[] {false}; - typeElement.accept(new JavaRecursiveElementWalkingVisitor(){ + final PsiTypeVisitor visitor = new PsiTypeVisitor() { @Override - public void visitElement(PsiElement element) { - if (found[0]) return; - super.visitElement(element); - } - - @Override - public void visitTypeElement(PsiTypeElement type) { - super.visitTypeElement(type); - final PsiClass psiClass = PsiUtil.resolveClassInType(type.getType()); + public Boolean visitClassType(PsiClassType classType) { + final PsiClass psiClass = classType.resolve(); if (psiClass instanceof PsiTypeParameter && - PsiTreeUtil.isAncestor(((PsiTypeParameter)psiClass).getOwner(), typeElement, true)) { - return; + PsiTreeUtil.isAncestor(((PsiTypeParameter)psiClass).getOwner(), method, true)) { + return false; } - if (Comparing.strEqual(typeParameterName, type.getText())) { - found[0] = true; + if (Comparing.strEqual(typeParameterName, classType.getCanonicalText())) { + return true; } + for (PsiType p : classType.getParameters()) { + if (p.accept(this)) return true; + } + return false; } - }); - return found[0]; + + @Override + public Boolean visitPrimitiveType(PsiPrimitiveType primitiveType) { + return false; + } + + @Override + public Boolean visitArrayType(PsiArrayType arrayType) { + return arrayType.getComponentType().accept(this); + } + + @Override + public Boolean visitWildcardType(PsiWildcardType wildcardType) { + final PsiType bound = wildcardType.getBound(); + if (bound != null) { + return bound.accept(this); + } + return false; + } + }; + + final PsiTypeElement rElement = method.getReturnTypeElement(); + if (rElement != null) { + if (rElement.getType().accept(visitor)) return true; + } + + + for (PsiParameter parameter : method.getParameterList().getParameters()) { + final PsiTypeElement element = parameter.getTypeElement(); + if (element != null) { + if (element.getType().accept(visitor)) return true; + } + } + return false; } protected boolean shouldBeAbstract(PsiClass targetClass) { diff --git a/java/java-impl/src/com/intellij/codeInsight/template/impl/JavaTemplateUtil.java b/java/java-impl/src/com/intellij/codeInsight/template/impl/JavaTemplateUtil.java index 8768820d289b..f21854b70a23 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/impl/JavaTemplateUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/impl/JavaTemplateUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -54,11 +54,15 @@ public class JavaTemplateUtil { PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); if (method != null) { PsiTypeParameterList paramList = method.getTypeParameterList(); - PsiTypeParameter[] params = paramList.getTypeParameters(); + PsiTypeParameter[] params = paramList != null ? paramList.getTypeParameters() : PsiTypeParameter.EMPTY_ARRAY; for (PsiTypeParameter param : params) { if (param.getName().equals(aClass.getName())) return; } try { + if (paramList == null) { + final PsiTypeParameterList newList = JVMElementFactories.getFactory(method.getLanguage(), project).createTypeParameterList(); + paramList = (PsiTypeParameterList)method.addAfter(newList, method.getModifierList()); + } paramList.add(aClass.copy()); PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document); } diff --git a/java/java-psi-api/src/com/intellij/psi/JVMElementFactory.java b/java/java-psi-api/src/com/intellij/psi/JVMElementFactory.java index 293be8bd1943..3e6487879d67 100644 --- a/java/java-psi-api/src/com/intellij/psi/JVMElementFactory.java +++ b/java/java-psi-api/src/com/intellij/psi/JVMElementFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -128,5 +128,12 @@ public interface JVMElementFactory { @NotNull PsiElement createExpressionFromText(@NotNull @NonNls String text, @Nullable PsiElement context) throws IncorrectOperationException; + @NotNull PsiElement createReferenceElementByType(PsiClassType type); + + @NotNull + PsiTypeParameterList createTypeParameterList(); + + @NotNull + PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java index 30e8d38b7624..5c876fb79274 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -169,6 +169,34 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps return new LightClassReference(myManager, type.getPresentableText(), refClass, resolveResult.getSubstitutor()); } + @NotNull + @Override + public PsiTypeParameterList createTypeParameterList() { + return createMethodFromText("void foo()", null).getTypeParameterList(); + } + + @NotNull + @Override + public PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes) { + StringBuilder builder = new StringBuilder(); + builder.append("public <").append(name); + if (superTypes.length > 0) { + builder.append(" extends "); + for (PsiClassType type : superTypes) { + builder.append(type.getCanonicalText()).append(','); + } + + builder.delete(builder.length() - 1, builder.length()); + } + builder.append("> void foo(){}"); + try { + return createMethodFromText(builder.toString(), null).getTypeParameters()[0]; + } + catch (RuntimeException e) { + throw new IncorrectOperationException("type parameter text: " + builder.toString()); + } + } + @NotNull @Override public PsiField createField(@NotNull final String name, @NotNull final PsiType type) throws IncorrectOperationException { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java index 91cdd946eb29..c42d906d94cd 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java @@ -381,18 +381,6 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo if (nextSibling != null) { final int startOffset = nextSibling.getTextRange().getStartOffset() - getTextRange().getStartOffset(); int endOffset = nextSibling.getTextRange().getEndOffset() - getTextRange().getStartOffset(); - final PsiElement nextParSibling = nextSibling.getNextSibling(); - if (nextParSibling != null && "(".equals(nextParSibling.getText())) { - endOffset++; - PsiElement nextElement = nextParSibling.getNextSibling(); - if (nextElement != null && SourceTreeToPsiMap.psiToTreeNotNull(nextElement).getElementType() == DOC_TAG_VALUE_TOKEN) { - endOffset += nextElement.getTextLength(); - nextElement = nextElement.getNextSibling(); - } - if (nextElement != null && ")".equals(nextElement.getText())) { - endOffset++; - } - } return new TextRange(startOffset, endOffset); } return new TextRange(getTextLength(), getTextLength()); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java new file mode 100644 index 000000000000..c7f959b6a630 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java @@ -0,0 +1,1731 @@ +/* + * @(#)ClassLoader.java 1.162 02/03/19 + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +import java.io.InputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.io.PrintWriter; +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Vector; +import java.util.Stack; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.jar.Manifest; +import java.net.URL; +import java.net.MalformedURLException; +import java.security.AccessController; +import java.security.AccessControlContext; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.security.ProtectionDomain; +import java.security.Permissions; +import java.security.CodeSource; +import java.security.Policy; +import sun.misc.URLClassPath; +import sun.misc.Resource; +import sun.misc.CompoundEnumeration; +import sun.misc.ClassFileTransformer; +//import sun.misc.Launcher; +import sun.reflect.Reflection; +import sun.security.action.GetPropertyAction; + +/** + * A class loader is an object that is responsible for loading + * classes. The class ClassLoader is an abstract class. + * Given the name of a class, a class loader should attempt to locate + * or generate data that constitutes a definition for the class. A + * typical strategy is to transform the name into a file + * name and then read a "class file" of that name from a file system. + *

+ * Every Class object contains a + * {@link Class#getClassLoader() reference} to the + * ClassLoader that defined it. + *

+ * Class objects for array classes are not created by class loaders, but + * are created automatically as required by the Java runtime. The class + * loader for an array class, as returned by {@link Class#getClassLoader()} + * is the same as the class loader for its element type; if the element + * type is a primitive type, then the array class has no class loader. + *

+ * Applications implement subclasses of ClassLoader in + * order to extend the manner in which the Java virtual machine + * dynamically loads classes. + *

+ * Class loaders may typically be used by security managers to + * indicate security domains. + *

+ * The ClassLoader class uses a delegation model to + * search for classes and resources. Each instance of + * ClassLoader has an associated parent class loader. + * When called upon to find a class or resource, a + * ClassLoader instance will delegate the search for + * the class or resource to its parent class loader before + * attempting to find the class or resource itself. The virtual + * machine's built-in class loader, called the bootstrap class loader, + * does not itself have a parent but may serve as the parent of a + * ClassLoader instance. + *

+ * Normally, the Java virtual machine loads classes from the local + * file system in a platform-dependent manner. For example, on UNIX + * systems, the virtual machine loads classes from the directory + * defined by the CLASSPATH environment variable. + *

+ * However, some classes may not originate from a file; they may + * originate from other sources, such as the network, or they could + * be constructed by an application. The method + * defineClass converts an array of bytes into an + * instance of class Class. Instances of this newly + * defined class can be created using the newInstance + * method in class Class. + *

+ * The methods and constructors of objects created by a class loader + * may reference other classes. To determine the class(es) referred + * to, the Java virtual machine calls the loadClass + * method of the class loader that originally created the class. + *

+ * For example, an application could create a network class loader + * to download class files from a server. Sample code might look like: + *

+ *   ClassLoader loader = new NetworkClassLoader(host, port);
+ *   Object main = loader.loadClass("Main", true).newInstance();
+ *	  . . .
+ * 
+ *

+ * The network class loader subclass must define the methods + * findClass and loadClassData + * to load a class from the network. Once it + * has downloaded the bytes that make up the class, it should use the + * method defineClass to create a class instance. A + * sample implementation is: + *


+ *     class NetworkClassLoader extends ClassLoader {
+ *         String host;
+ *         int port;
+ *
+ *         public Class findClass(String name) {
+ *             byte[] b = loadClassData(name);
+ *             return defineClass(name, b, 0, b.length);
+ *         }
+ *
+ *         private byte[] loadClassData(String name) {
+ *             // load the class data from the connection
+ *              . . .
+ *         }
+ *     }
+ * 

+ * + * @version 1.162, 03/19/02 + * @see java.lang.Class + * @see java.lang.Class#newInstance() + * @see java.lang.ClassLoader#defineClass(byte[], int, int) + * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) + * @see java.lang.ClassLoader#resolveClass(java.lang.Class) + * @since JDK1.0 + */ +public abstract class ClassLoader { + + private static native void registerNatives(); + static { + registerNatives(); + } + + /* + * If initialization succeed this is set to true and security checks will + * succeed. Otherwise the object is not initialized and the object is + * useless. + */ + private boolean initialized = false; + + /* + * The parent class loader for delegation. + */ + private ClassLoader parent; + + /* + * Hashtable that maps packages to certs + */ + private Hashtable package2certs = new Hashtable(11); + + /* + * shared among all packages with unsigned classes + */ + java.security.cert.Certificate[] nocerts; + + /* + * The classes loaded by this class loader. The only purpose of this + * table is to keep the classes from being GC'ed until the loader + * is GC'ed. + */ + private Vector classes = new Vector(); + + /* + * The initiating protection domains for all classes + * loaded by this loader. + */ + private Set domains = new HashSet(); + + /* + * Called by the VM to record every loaded class with this loader. + */ + void addClass(Class c) { + classes.addElement(c); + } + + /* + * The packages defined in this class loader. Each package name is + * mapped to its corresponding Package object. + */ + private HashMap packages = new HashMap(); + + /** + * Creates a new class loader using the specified parent class loader + * for delegation. + *

+ * If there is a security manager, its checkCreateClassLoader + * method is called. This may result in a security exception. + * + * @param parent the parent class loader + * + * @throws SecurityException if a security manager exists and its + * checkCreateClassLoader method doesn't allow creation of a + * new class loader. + * @see java.lang.SecurityException + * @see java.lang.SecurityManager#checkCreateClassLoader() + * @since 1.2 + */ + protected ClassLoader(ClassLoader parent) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkCreateClassLoader(); + } + this.parent = parent; + initialized = true; + } + + /** + * Creates a new class loader using the ClassLoader + * returned by the method getSystemClassLoader() as the + * parent class loader. + *

+ * If there is a security manager, its checkCreateClassLoader + * method is called. This may result in a security exception. + * + * @throws SecurityException + * if a security manager exists and its checkCreateClassLoader + * method doesn't allow creation of a new class loader. + * + * @see java.lang.SecurityException + * @see java.lang.SecurityManager#checkCreateClassLoader() + */ + protected ClassLoader() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkCreateClassLoader(); + } + this.parent = getSystemClassLoader(); + initialized = true; + } + + /** + * Loads the class with the specified name. This method searches for + * classes in the same manner as the {@link #loadClass(String, boolean)} + * method. It is called by the Java virtual machine to resolve class + * references. Calling this method is equivalent to calling + * loadClass(name, false). + * + * @param name the name of the class + * @return the resulting Class object + * @exception ClassNotFoundException if the class was not found + */ + public Class loadClass(String name) throws ClassNotFoundException + { + return loadClass(name, false); + } + + /** + * Loads the class with the specified name. The default implementation of + * this method searches for classes in the following order:

+ * + *

    + *
  1. Call {@link #findLoadedClass(String)} to check if the class has + * already been loaded.

    + *

  2. Call the loadClass method on the parent class + * loader. If the parent is null the class loader + * built-in to the virtual machine is used, instead.

    + *

  3. Call the {@link #findClass(String)} method to find the class.

    + *

+ * + * If the class was found using the above steps, and the + * resolve flag is true, this method will then call the + * {@link #resolveClass(Class)} method on the resulting class object. + *

+ * From the Java 2 SDK, v1.2, subclasses of ClassLoader are + * encouraged to override + * {@link #findClass(String)}, rather than this method.

+ * + * @param name the name of the class + * @param resolve if true then resolve the class + * @return the resulting Class object + * @exception ClassNotFoundException if the class could not be found + */ + protected synchronized Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + // First, check if the class has already been loaded + Class c = findLoadedClass(name); + if (c == null) { + try { + if (parent != null) { + c = parent.loadClass(name, false); + } else { + c = findBootstrapClass0(name); + } + } catch (ClassNotFoundException e) { + // If still not found, then call findClass in order + // to find the class. + c = findClass(name); + } + } + if (resolve) { + resolveClass(c); + } + return c; + } + + /* + * This method is called by the virtual machine to load + * a class. + */ + private synchronized Class loadClassInternal(String name) + throws ClassNotFoundException { + + return loadClass(name); + } + + private void checkPackageAccess(Class cls, ProtectionDomain pd) { + final SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + final String name = cls.getName(); + final int i = name.lastIndexOf('.'); + if (i != -1) { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + sm.checkPackageAccess(name.substring(0, i)); + return null; + } + }, new AccessControlContext(new ProtectionDomain[] {pd})); + } + } + domains.add(pd); + } + + /** + * Finds the specified class. This method should be overridden + * by class loader implementations that follow the new delegation model + * for loading classes, and will be called by the loadClass + * method after checking the parent class loader for the requested class. + * The default implementation throws ClassNotFoundException. + * + * @param name the name of the class + * @return the resulting Class object + * @exception ClassNotFoundException if the class could not be found + * @since 1.2 + */ + protected Class findClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(name); + } + + /** + * Converts an array of bytes into an instance of class + * Class. Before the Class can be used it must be + * resolved. This method is deprecated in favor of the version + * that takes the class name as its first argument, and is more + * secure. + * + * @param b the bytes that make up the class data. The bytes in + * positions off through off+len-1 + * should have the format of a valid class file as defined + * by the + * Java + * Virtual Machine Specification. + * @param off the start offset in b of the class data + * @param len the length of the class data + * @return the Class object that was created from the + * specified class data + * @exception ClassFormatError if the data did not contain a valid class + * @exception IndexOutOfBoundsException if either off or + * len is negative, or if + * off+len is greater than b.length. + * @see ClassLoader#loadClass(java.lang.String, boolean) + * @see ClassLoader#resolveClass(java.lang.Class) + * @deprecated Replaced by defineClass(java.lang.String, byte[], int, int) + */ + protected final Class defineClass(byte[] b, int off, int len) + throws ClassFormatError + { + return defineClass(null, b, off, len, null); + } + + /** + * Converts an array of bytes into an instance of class Class. + * Before the Class can be used it must be resolved. + *

+ * This method assigns a default ProtectionDomain to + * the newly defined class. The ProtectionDomain + * contains the set of permissions granted when + * a call to Policy.getPolicy().getPermissions() is made with + * a code source of null,null. The default domain is + * created on the first invocation of defineClass, and + * re-used on subsequent calls. + *

+ * To assign a specific ProtectionDomain to the class, + * use the defineClass method that takes a + * ProtectionDomain as one of its arguments. + * + * @param name the expected name of the class, or null + * if not known, using '.' and not '/' as the separator + * and without a trailing ".class" suffix. + * @param b the bytes that make up the class data. The bytes in + * positions off through off+len-1 + * should have the format of a valid class file as defined + * by the + * Java + * Virtual Machine Specification. + * @param off the start offset in b of the class data + * @param len the length of the class data + * @return the Class object that was created from the + * specified class data + * @exception ClassFormatError if the data did not contain a valid class + * @exception IndexOutOfBoundsException if either off or + * len is negative, or if + * off+len is greater than b.length. + * @exception SecurityException if an attempt is made to add this class + * to a package that contains classes that were signed by + * a different set of certificates than this class (which + * is unsigned), or if the class name begins with "java.". + * + * @see ClassLoader#loadClass(java.lang.String, boolean) + * @see ClassLoader#resolveClass(java.lang.Class) + * @see java.security.ProtectionDomain + * @see java.security.Policy + * @see java.security.CodeSource + * @see java.security.SecureClassLoader + * @since JDK1.1 + */ + protected final Class defineClass(String name, byte[] b, int off, int len) + throws ClassFormatError + { + return defineClass(name, b, off, len, null); + } + + /** + * Converts an array of bytes into an instance of class Class, + * with an optional ProtectionDomain. If the domain is null, + * then a default domain will be assigned to the class as specified + * in the documentation for {@link #defineClass(String,byte[],int,int)}. + * Before the class can be used it must be resolved. + * + *

The first class defined in a package determines the exact set of + * certificates that all subsequent classes defined in that package must + * contain. The set of certificates for a class is obtained from the + * CodeSource within the ProtectionDomain of + * the class. Any classes added to that package must contain + * the same set of certificates or a SecurityException + * will be thrown. Note that if the name argument is + * null, this check is not performed. You should always pass in the + * name of the class you are defining as well as the bytes. This + * ensures that the class you are defining is indeed the class + * you think it is. + * + *

The specified class name cannot begin with "java.", since all + * classes in the java.* packages can only be defined by the bootstrap + * class loader. If the name parameter is not null, it + * must be equal to the name of the class specified by the byte + * array b, otherwise a ClassFormatError is raised. + * + * @param name the expected name of the class, or null + * if not known, using '.' and not '/' as the separator + * and without a trailing ".class" suffix. + * @param b the bytes that make up the class data. The bytes in + * positions off through off+len-1 + * should have the format of a valid class file as defined + * by the + * Java + * Virtual Machine Specification. + * @param off the start offset in b of the class data + * @param len the length of the class data + * @param protectionDomain the ProtectionDomain of the class + * @return the Class object created from the data, + * and optional ProtectionDomain. + * @exception ClassFormatError if the data did not contain a valid class + * @exception IndexOutOfBoundsException if either off or + * len is negative, or if + * off+len is greater than b.length. + * @exception SecurityException if an attempt is made to add this class + * to a package that contains classes that were signed by + * a different set of certificates than this class, or if + * the class name begins with "java.". + */ + protected final Class defineClass(String name, byte[] b, int off, int len, + ProtectionDomain protectionDomain) + throws ClassFormatError + { + check(); + if ((name != null) && name.startsWith("java.")) { + throw new SecurityException("Prohibited package name: " + + name.substring(0, name.lastIndexOf('.'))); + } + if (protectionDomain == null) { + protectionDomain = getDefaultDomain(); + } + + if (name != null) + checkCerts(name, protectionDomain.getCodeSource()); + + Class c = null; + + try + { + c = defineClass0(name, b, off, len, protectionDomain); + } + catch (ClassFormatError cfe) + { + // Class format error - try to transform the bytecode and + // define the class again + // + Object[] transformers = ClassFileTransformer.getTransformers(); + + for (int i=0; transformers != null && i < transformers.length; i++) + { + try + { + // Transform byte code using transformer + byte[] tb = ((ClassFileTransformer) transformers[i]).transform(b, off, len); + c = defineClass0(name, tb, 0, tb.length, protectionDomain); + break; + } + catch (ClassFormatError cfe2) + { + // If ClassFormatError occurs, try next transformer + } + } + + // Rethrow original ClassFormatError if unable to transform + // bytecode to well-formed + // + if (c == null) + throw cfe; + } + + if (protectionDomain.getCodeSource() != null) { + java.security.cert.Certificate certs[] = + protectionDomain.getCodeSource().getCertificates(); + if (certs != null) + setSigners(c, certs); + } + return c; + } + + private synchronized void checkCerts(String name, CodeSource cs) + { + int i = name.lastIndexOf('.'); + String pname = (i == -1) ? "" : name.substring(0,i); + java.security.cert.Certificate[] pcerts = + (java.security.cert.Certificate[]) package2certs.get(pname); + if (pcerts == null) { + // first class in this package gets to define which + // certificates must be the same for all other classes + // in this package + if (cs != null) { + pcerts = cs.getCertificates(); + } + if (pcerts == null) { + if (nocerts == null) + nocerts = new java.security.cert.Certificate[0]; + pcerts = nocerts; + } + package2certs.put(pname, pcerts); + } else { + java.security.cert.Certificate[] certs = null; + if (cs != null) { + certs = cs.getCertificates(); + } + + if (!compareCerts(pcerts,certs)) { + throw new SecurityException("class \""+ name+ + "\"'s signer information does not match signer information of other classes in the same package"); + } + } + } + + /** + * check to make sure the certs for the new class (certs) are + * the same as the certs for the first class inserted + * in the package (pcerts) + */ + private boolean compareCerts(java.security.cert.Certificate[] pcerts, + java.security.cert.Certificate[] certs) + { + // certs can be null, indicating no certs. + if ((certs == null) || (certs.length == 0)) { + return pcerts.length == 0; + } + + // the length must be the same at this point + if (certs.length != pcerts.length) + return false; + + // go through and make sure all the certs in one array + // are in the other and vice-versa. + boolean match; + for (int i=0; i < certs.length; i++) { + match = false; + for (int j=0; j < pcerts.length; j++) { + if (certs[i].equals(pcerts[j])) { + match = true; + break; + } + } + if (!match) return false; + } + + // now do the same for pcerts + for (int i=0; i < pcerts.length; i++) { + match = false; + for (int j=0; j < certs.length; j++) { + if (pcerts[i].equals(certs[j])) { + match = true; + break; + } + } + if (!match) return false; + } + + return true; + } + + /** + * Links the specified class. + * This (misleadingly named) method may be used by a class loader to + * link a class. If the class c has already been linked, + * then this method simply returns. Otherwise, the class is linked + * as described in the "Execution" chapter of the Java Language + * Specification. + * + * @param c the class to link + * @exception NullPointerException if c is null. + * @see java.lang.ClassLoader#defineClass(java.lang.String,byte[],int,int) + */ + protected final void resolveClass(Class c) { + check(); + resolveClass0(c); + } + + /** + * Finds a class with the specified name, loading it if necessary.

+ * + * Prior to the Java 2 SDK, this method loads a class from the local file + * system in a platform-dependent manner, and returns a class object + * that has no associated class loader.

+ * + * Since the Java 2 SDK v1.2, this method loads the class through the + * system class loader(see {@link #getSystemClassLoader()}). Class objects + * returned might have ClassLoaders associated with them. + * Subclasses of ClassLoader need not usually call this + * method, because most class loaders need to override just {@link + * #findClass(String)}.

+ * + * @param name the name of the class that is to be found + * @return the Class object for the specified + * name + * @exception ClassNotFoundException if the class could not be found + * @see #ClassLoader(ClassLoader) + * @see #getParent() + */ + protected final Class findSystemClass(String name) + throws ClassNotFoundException + { + check(); + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return findBootstrapClass(name); + } + return system.loadClass(name); + } + + /** + * Returns the parent class loader for delegation. Some implementations + * may use null to represent the bootstrap class + * loader. This method will return null in such + * implementations if this class loader's parent is the bootstrap + * class loader. + *

+ * If a security manager is present, and the caller's class loader is + * not null and is not an ancestor of this class loader, then + * this method calls the security manager's checkPermission + * method with a RuntimePermission("getClassLoader") + * permission to ensure it's ok to access the parent class loader. + * If not, a SecurityException will be thrown. + * + * @return the parent ClassLoader + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * access to this class loader's parent class loader. + * + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * + * @since 1.2 + */ + public final ClassLoader getParent() { + if (parent == null) + return null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ClassLoader ccl = getCallerClassLoader(); + if (ccl != null && !isAncestor(ccl)) { + sm.checkPermission(getGetClassLoaderPerm()); + } + } + return parent; + } + + /** + * Sets the signers of a class. This should be called after defining a + * class. + * + * @param c the Class object + * @param signers the signers for the class + * @since JDK1.1 + */ + protected final void setSigners(Class c, Object[] signers) { + check(); + c.setSigners(signers); + } + + private Class findBootstrapClass0(String name) + throws ClassNotFoundException { + check(); + return findBootstrapClass(name); + } + + private native Class defineClass0(String name, byte[] b, int off, int len, + ProtectionDomain pd); + private native void resolveClass0(Class c); + private native Class findBootstrapClass(String name) + throws ClassNotFoundException; + + /* + * Check to make sure the class loader has been initialized. + */ + private void check() { + if (!initialized) { + throw new SecurityException("ClassLoader object not initialized"); + } + } + + /** + * Finds the class with the given name if it had been previously loaded + * through this class loader. + * + * @param name the class name + * @return the Class object, or null if + * the class has not been loaded + * @since JDK1.1 + */ + protected native final Class findLoadedClass(String name); + + /** + * Finds the resource with the given name. A resource is some data + * (images, audio, text, etc) that can be accessed by class code in a way + * that is independent of the location of the code.

+ * + * The name of a resource is a "/"-separated path name that identifies + * the resource.

+ * + * This method will first search the parent class loader for the resource; + * if the parent is null the path of the class loader + * built-in to the virtual machine is searched. That failing, this method + * will call findResource to find the resource.

+ * + * @param name resource name + * @return a URL for reading the resource, or null if + * the resource could not be found or the caller doesn't have + * adequate privileges to get the resource. + * @since JDK1.1 + * @see #findResource(String) + */ + public URL getResource(String name) { + URL url; + if (parent != null) { + url = parent.getResource(name); + } else { + url = getBootstrapResource(name); + } + if (url == null) { + url = findResource(name); + } + return url; + } + + /** + * Finds all the resources with the given name. A resource is some data + * (images, audio, text, etc) that can be accessed by class code in a way + * that is independent of the location of the code.

+ * + * The name of a resource is a "/"-separated path name that identifies the + * resource.

+ * + * The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name resource name + * @return an enumeration of URL to the resource. If no resources could + * be found, the enumeration will be empty. Resources that the + * doesn't have access to will not be in the enumeration. + * @throws IOException if I/O errors occur + * @since 1.2 + * @see #getResource + * @see #findResources + */ + public final Enumeration getResources(String name) throws IOException { + Enumeration[] tmp = new Enumeration[2]; + if (parent != null) { + tmp[0] = parent.getResources(name); + } else { + tmp[0] = getBootstrapResources(name); + } + tmp[1] = findResources(name); + + return new CompoundEnumeration(tmp); + } + + /** + * Returns an Enumeration of URLs representing all the resources with + * the given name. Class loader implementations should override this + * method to specify where to load resources from. + * + * @param name the resource name + * @return an Enumeration of URLs for the resources + * @throws IOException if I/O errors occur + * @since 1.2 + */ + protected Enumeration findResources(String name) throws IOException { + return new CompoundEnumeration(new Enumeration[0]); + } + + /** + * Finds the resource with the given name. Class loader + * implementations should override this method to specify where to + * find resources. + * + * @param name the resource name + * @return a URL for reading the resource, or null + * if the resource could not be found + * @since 1.2 + */ + protected URL findResource(String name) { + return null; + } + + /** + * Find a resource of the specified name from the search path used to load + * classes.

+ * + * In JDK1.1, the search path used is that of the virtual machine's + * built-in class loader.

+ * + * Since the Java 2 SDK v1.2, this method locates the resource through the system class + * loader (see {@link #getSystemClassLoader()}). + * + * @param name the resource name + * @return a URL for reading the resource, or null if + * the resource could not be found + * @since JDK1.1 + */ + public static URL getSystemResource(String name) { + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return getBootstrapResource(name); + } + return system.getResource(name); + } + + /** + * Find resources from the VM's built-in classloader. + */ + private static URL getBootstrapResource(String name) { + URLClassPath ucp = getBootstrapClassPath(); + Resource res = ucp.getResource(name); + return res != null ? res.getURL() : null; + } + + /** + * Finds all resources of the specified name from the search path used to + * load classes. The resources thus found are returned as an + * Enumeration of URL objects.

+ * + * The search order is described in the documentation for {@link + * #getSystemResource(String)}.

+ * + * @param name the resource name + * @return an enumeration of resource URLs + * @throws IOException if I/O errors occur + * @since 1.2 + */ + public static Enumeration getSystemResources(String name) + throws IOException + { + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return getBootstrapResources(name); + } + return system.getResources(name); + } + + /** + * Find resources from the VM's built-in classloader. + */ + private static Enumeration getBootstrapResources(String name) + throws IOException + { + final Enumeration e = getBootstrapClassPath().getResources(name); + return new Enumeration () { + public Object nextElement() { + return ((Resource)e.nextElement()).getURL(); + } + public boolean hasMoreElements() { + return e.hasMoreElements(); + } + }; + } + + /* + * Returns the URLClassPath that is used for finding system resources. + */ + static URLClassPath getBootstrapClassPath() { + if (bootstrapClassPath == null) { + bootstrapClassPath = sun.misc.Launcher.getBootstrapClassPath(); + } + return bootstrapClassPath; + } + + private static URLClassPath bootstrapClassPath; + + /** + * Returns an input stream for reading the specified resource. + * + * The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name the resource name + * @return an input stream for reading the resource, or null + * if the resource could not be found + * @since JDK1.1 + */ + public InputStream getResourceAsStream(String name) { + URL url = getResource(name); + try { + return url != null ? url.openStream() : null; + } catch (IOException e) { + return null; + } + } + + /** + * Open for reading, a resource of the specified name from the search path + * used to load classes.

+ * + * The search order is described in the documentation for {@link + * #getSystemResource(String)}.

+ * + * @param name the resource name + * @return an input stream for reading the resource, or null + * if the resource could not be found + * @since JDK1.1 + */ + public static InputStream getSystemResourceAsStream(String name) { + URL url = getSystemResource(name); + try { + return url != null ? url.openStream() : null; + } catch (IOException e) { + return null; + } + } + + /** + * Returns the system class loader for delegation. This is the default + * delegation parent for new ClassLoader instances, and + * is typically the class loader used to start the application. + *

+ * This method is first invoked early in the runtime's startup + * sequence, at which point it creates the system class loader + * and sets it as the context class loader of the invoking + * Thread. + *

+ * The default system class loader is an implementation-dependent + * instance of this class. + *

+ * If the system property java.system.class.loader is + * defined when this method is first invoked then the value of that + * property is taken to be the name of a class that will be returned as + * the system class loader. The class is loaded using the default system + * class loader and must define a public constructor that takes a single + * parameter of type ClassLoader which is used + * as the delegation parent. An instance is then created using this + * constructor with the default system class loader as the parameter. + * The resulting class loader is defined to be the system class loader. + *

+ * If a security manager is present, and the caller's class loader is + * not null and the caller's class loader is not the same as or an ancestor of + * the system class loader, then + * this method calls the security manager's checkPermission + * method with a RuntimePermission("getClassLoader") + * permission to ensure it's ok to access the system class loader. + * If not, a SecurityException will be thrown. + * + * @return the system ClassLoader for delegation, or + * null if none + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * access to the system class loader. + * @throws IllegalStateException + * if invoked recursively during the construction + * of the class loader specified by the + * java.system.class.loader property. + * @throws Error + * if the system property java.system.class.loader + * is defined but the named class could not be loaded, the + * provider class does not define the required constructor, or an + * exception is thrown by that constructor when it is invoked. The + * underlying cause of the error can be retrieved via the + * {@link Throwable#getCause()} method. + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * @revised 1.4 + */ + public static ClassLoader getSystemClassLoader() { + initSystemClassLoader(); + if (scl == null) { + return null; + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ClassLoader ccl = getCallerClassLoader(); + if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) { + sm.checkPermission(getGetClassLoaderPerm()); + } + } + return scl; + } + + private static synchronized void initSystemClassLoader() { + if (!sclSet) { + if (scl != null) + throw new IllegalStateException("recursive call"); + sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); + if (l != null) { + Throwable oops = null; + scl = l.getClassLoader(); + try { + PrivilegedExceptionAction a; + a = new SystemClassLoaderAction(scl); + scl = (ClassLoader) AccessController.doPrivileged(a); + } catch (PrivilegedActionException pae) { + oops = pae.getCause(); + if (oops instanceof InvocationTargetException) { + oops = oops.getCause(); + } + } + if (oops != null) { + if (oops instanceof Error) { + throw (Error) oops; + } else { + // wrap the exception + throw new Error(oops); + } + } + } + sclSet = true; + } + } + + // Returns true if the specified class loader can be found + // in this class loader's delegation chain. + boolean isAncestor(ClassLoader cl) { + ClassLoader acl = this; + do { + acl = acl.parent; + if (cl == acl) { + return true; + } + } while (acl != null); + return false; + } + + // Returns the caller's class loader, or null if none. + // NOTE this must always be called when there is exactly one + // intervening frame from the core libraries on the stack between + // this method's invocation and the desired caller. + static ClassLoader getCallerClassLoader() { + // NOTE use of more generic Reflection.getCallerClass() + Class caller = Reflection.getCallerClass(3); + // This can be null if the VM is requesting it + if (caller == null) { + return null; + } + // Circumvent security check since this is package-private + return caller.getClassLoader0(); + } + + // The class loader for the system + private static ClassLoader scl; + + // Set to true once the system class loader has been set + private static boolean sclSet; + + // Permission to access system or parent class loader + private static RuntimePermission getClassLoaderPerm = null; + + static RuntimePermission getGetClassLoaderPerm() + { + if (getClassLoaderPerm == null) + getClassLoaderPerm = new RuntimePermission("getClassLoader"); + return getClassLoaderPerm; + } + + /** + * Defines a package by name in this ClassLoader. This allows class + * loaders to define the packages for their classes. Packages must be + * created before the class is defined, and package names must be + * unique within a class loader and cannot be redefined or changed + * once created. + * + * @param name the package name + * @param specTitle the specification title + * @param specVersion the specification version + * @param specVendor the specification vendor + * @param implTitle the implementation title + * @param implVersion the implementation version + * @param implVendor the implementation vendor + * @param sealBase If not null, then this package is sealed with + * respect to the given code source URL. Otherwise, + * the package is not sealed. + * @return the newly defined Package object + * @exception IllegalArgumentException if package name duplicates an + * existing package either in this class loader or one of + * its ancestors + * @since 1.2 + */ + protected Package definePackage(String name, String specTitle, + String specVersion, String specVendor, + String implTitle, String implVersion, + String implVendor, URL sealBase) + throws IllegalArgumentException + { + synchronized (packages) { + Package pkg = getPackage(name); + if (pkg != null) { + throw new IllegalArgumentException(name); + } + pkg = new Package(name, specTitle, specVersion, specVendor, + implTitle, implVersion, implVendor, + sealBase); + packages.put(name, pkg); + return pkg; + } + } + + /** + * Returns a Package that has been defined by this class loader or any + * of its ancestors. + * + * @param name the package name + * @return the Package corresponding to the given name, or null if not + * found + * @since 1.2 + */ + protected Package getPackage(String name) { + synchronized (packages) { + Package pkg = (Package)packages.get(name); + if (pkg == null) { + if (parent != null) { + pkg = parent.getPackage(name); + } else { + pkg = Package.getSystemPackage(name); + } + if (pkg != null) { + packages.put(name, pkg); + } + } + return pkg; + } + } + + /** + * Returns all of the Packages defined by this class loader and its + * ancestors. + * + * @return the array of Package objects defined by this + * ClassLoader + * @since 1.2 + */ + protected Package[] getPackages() { + Map map; + synchronized (packages) { + map = (Map)packages.clone(); + } + Package[] pkgs; + if (parent != null) { + pkgs = parent.getPackages(); + } else { + pkgs = Package.getSystemPackages(); + } + if (pkgs != null) { + for (int i = 0; i < pkgs.length; i++) { + String pkgName = pkgs[i].getName(); + if (map.get(pkgName) == null) { + map.put(pkgName, pkgs[i]); + } + } + } + return (Package[])map.values().toArray(new Package[map.size()]); + } + + /** + * Returns the absolute path name of a native library. The VM + * invokes this method to locate the native libraries that belong + * to classes loaded with this class loader. If this method returns + * null, the VM searches the library along the path + * specified as the java.library.path property. + * + * @param libname the library name + * @return the absolute path of the native library + * @see java.lang.System#loadLibrary(java.lang.String) + * @see java.lang.System#mapLibraryName(java.lang.String) + * @since 1.2 + */ + protected String findLibrary(String libname) { + return null; + } + + /** + * The inner class NativeLibrary denotes a loaded native library + * instance. Every classloader contains a vector of loaded native + * libraries in the private field nativeLibraries. + * The native libraries loaded into the system are entered into + * the systemNativeLibraries vector. + * + * Every native library reuqires a particular version of JNI. This + * is denoted by the private jniVersion field. This field is set + * by the VM when it loads the library, and used by the VM to pass + * the correct version of JNI to the native methods. + * + * @version 1.162, 03/19/02 + * @see java.lang.ClassLoader + * @since 1.2 + */ + static class NativeLibrary { + /* opaque handle to native library, used in native code. */ + long handle; + /* the version of JNI environment the native library requires. */ + private int jniVersion; + /* the class from which the library is loaded, also indicates + the loader this native library belongs. */ + private Class fromClass; + /* the canonicalized name of the native library. */ + String name; + + native void load(String name); + native long find(String name); + native void unload(); + + public NativeLibrary(Class fromClass, String name) { + this.name = name; + this.fromClass = fromClass; + } + + protected void finalize() { + synchronized (loadedLibraryNames) { + if (fromClass.getClassLoader() != null && handle != 0) { + /* remove the native library name */ + int size = loadedLibraryNames.size(); + for (int i = 0; i < size; i++) { + if (name.equals(loadedLibraryNames.elementAt(i))) { + loadedLibraryNames.removeElementAt(i); + break; + } + } + /* unload the library. */ + ClassLoader.nativeLibraryContext.push(this); + try { + unload(); + } finally { + ClassLoader.nativeLibraryContext.pop(); + } + } + } + } + /* Called in the VM to determine the context class in + JNI_Load/JNI_Unload */ + static Class getFromClass() { + return ((NativeLibrary) + (ClassLoader.nativeLibraryContext.peek())).fromClass; + } + } + + /* the "default" domain. Set as the default ProtectionDomain + * on newly created classses. + */ + private ProtectionDomain defaultDomain = null; + + /* + * returns (and initializes) the default domain. + */ + + private synchronized ProtectionDomain getDefaultDomain() { + if (defaultDomain == null) { + CodeSource cs = new CodeSource(null, null); + defaultDomain = new ProtectionDomain(cs, null, this, null); + } + return defaultDomain; + } + + /* All native library names we've loaded. */ + private static Vector loadedLibraryNames = new Vector(); + /* Native libraries belonging to system classes. */ + private static Vector systemNativeLibraries = new Vector(); + /* Native libraries associated with the class loader. */ + private Vector nativeLibraries = new Vector(); + + /* native libraries being loaded/unloaded. */ + private static Stack nativeLibraryContext = new Stack(); + + /* The paths searched for libraries */ + static private String usr_paths[]; + static private String sys_paths[]; + + private static String[] initializePath(String propname) { + String ldpath = System.getProperty(propname, ""); + String ps = File.pathSeparator; + int ldlen = ldpath.length(); + int i, j, n; + // Count the separators in the path + i = ldpath.indexOf(ps); + n = 0; + while (i >= 0) { + n++; + i = ldpath.indexOf(ps, i+1); + } + + // allocate the array of paths - n :'s = n + 1 path elements + String[] paths = new String[n + 1]; + + // Fill the array with paths from the ldpath + n = i = 0; + j = ldpath.indexOf(ps); + while (j >= 0) { + if (j - i > 0) { + paths[n++] = ldpath.substring(i, j); + } else if (j - i == 0) { + paths[n++] = "."; + } + i = j + 1; + j = ldpath.indexOf(ps, i); + } + paths[n] = ldpath.substring(i, ldlen); + return paths; + } + + + /* Called in the java.lang.Runtime class to implement load + * and loadLibrary. + */ + static void loadLibrary(Class fromClass, String name, + boolean isAbsolute) { + ClassLoader loader = + (fromClass == null) ? null : fromClass.getClassLoader(); + if (sys_paths == null) { + usr_paths = initializePath("java.library.path"); + sys_paths = initializePath("sun.boot.library.path"); + } + if (isAbsolute) { + if (loadLibrary0(fromClass, new File(name))) { + return; + } + throw new UnsatisfiedLinkError("Can't load library: " + name); + } + if (loader != null) { + String libfilename = loader.findLibrary(name); + if (libfilename != null) { + File libfile = new File(libfilename); + if (!libfile.isAbsolute()) { + throw new UnsatisfiedLinkError( + "ClassLoader.findLibrary failed to return an absolute path: " + libfilename); + } + if (loadLibrary0(fromClass, libfile)) { + return; + } + throw new UnsatisfiedLinkError ("Can't load " + libfilename); + } + } + for (int i = 0 ; i < sys_paths.length ; i++) { + File libfile = new File(sys_paths[i], System.mapLibraryName(name)); + if (loadLibrary0(fromClass, libfile)) { + return; + } + } + if (loader != null) { + for (int i = 0 ; i < usr_paths.length ; i++) { + File libfile = new File(usr_paths[i], + System.mapLibraryName(name)); + if (loadLibrary0(fromClass, libfile)) { + return; + } + } + } + // Oops, it failed + throw new UnsatisfiedLinkError("no " + name + " in java.library.path"); + } + + private static boolean loadLibrary0(Class fromClass, final File file) { + Boolean exists = (Boolean) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return new Boolean(file.exists()); + } + }); + if (!exists.booleanValue()) { + return false; + } + String name; + try { + name = file.getCanonicalPath(); + } catch (IOException e) { + return false; + } + ClassLoader loader = + (fromClass == null) ? null : fromClass.getClassLoader(); + Vector libs = + loader != null ? loader.nativeLibraries : systemNativeLibraries; + synchronized (libs) { + int size = libs.size(); + for (int i = 0; i < size; i++) { + NativeLibrary lib = (NativeLibrary)libs.elementAt(i); + if (name.equals(lib.name)) { + return true; + } + } + + synchronized (loadedLibraryNames) { + if (loadedLibraryNames.contains(name)) { + throw new UnsatisfiedLinkError + ("Native Library " + + name + + " already loaded in another classloader"); + } + /* If the library is being loaded (must be by + * the same thread, because Runtime.load and + * Runtime.loadLibrary are synchronous). The + * reason is can occur is that the JNI_OnLoad + * function can cause another loadLibrary call. + * + * Thus we can use a static stack to hold the list + * of libraries we are loading. + * + * If there is a pending load operation for the + * library, we immediately return success; otherwise, + * we raise UnsatisfiedLinkError. + */ + int n = nativeLibraryContext.size(); + for (int i = 0; i < n; i++) { + NativeLibrary lib = (NativeLibrary) + nativeLibraryContext.elementAt(i); + if (name.equals(lib.name)) { + if (loader == lib.fromClass.getClassLoader()) { + return true; + } else { + throw new UnsatisfiedLinkError + ("Native Library " + + name + + " is being loaded in another classloader"); + } + } + } + NativeLibrary lib = new NativeLibrary(fromClass, name); + nativeLibraryContext.push(lib); + try { + lib.load(name); + } finally { + nativeLibraryContext.pop(); + } + if (lib.handle != 0) { + loadedLibraryNames.addElement(name); + libs.addElement(lib); + return true; + } + return false; + } + } + } + + /* Called in the VM class linking code. */ + static long findNative(ClassLoader loader, String name) { + Vector libs = + loader != null ? loader.nativeLibraries : systemNativeLibraries; + synchronized (libs) { + int size = libs.size(); + for (int i = 0; i < size; i++) { + NativeLibrary lib = (NativeLibrary)libs.elementAt(i); + long entry = lib.find(name); + if (entry != 0) + return entry; + } + } + return 0; + } + + /* + * The default toggle for assertion checking. + */ + private boolean defaultAssertionStatus = false; + + /* + * Maps String packageName to Boolean package default assertion status + * Note that the default package is placed under a null map key. + * If this field is null then we are delegating assertion status queries + * to the VM, i.e., none of this ClassLoader's assertion status + * modification methods have been called. + */ + private Map packageAssertionStatus = null; + + /* + * Maps String fullyQualifiedClassName to Boolean assertionStatus + * If this field is null then we are delegating assertion status queries + * to the VM, i.e., none of this ClassLoader's assertion status + * modification methods have been called. + */ + Map classAssertionStatus = null; + + /** + * Sets the default assertion status for this class loader. This setting + * determines whether classes loaded by this class loader and initialized + * in the future will have assertions enabled or disabled by default. + * This setting may be overridden on a per-package or per-class basis by + * invoking {@link #setPackageAssertionStatus(String,boolean)} or {@link + * #setClassAssertionStatus(String,boolean)}. + * + * @param enabled true if classes loaded by this class loader + * will henceforth have assertions enabled by default, + * false if they will have assertions disabled by default. + * @since 1.4 + */ + public synchronized void setDefaultAssertionStatus(boolean enabled) { + if (classAssertionStatus == null) + initializeJavaAssertionMaps(); + + defaultAssertionStatus = enabled; + } + + /** + * Sets the package default assertion status for the named + * package. The package default assertion status determines the + * assertion status for classes initialized in the future that belong + * to the named package or any of its "subpackages." + *

+ * A subpackage of a package named p is any package whose name + * begins with "p." . For example, javax.swing.text is + * a subpackage of javax.swing, and both java.util + * and java.lang.reflect are subpackages of java. + *

+ * In the event that multiple package defaults apply to a given + * class, the package default pertaining to the most specific package + * takes precedence over the others. For example, if + * javax.lang and javax.lang.reflect both have + * package defaults associated with them, the latter package + * default applies to classes in javax.lang.reflect. + *

+ * Package defaults take precedence over the class loader's default + * assertion status, and may be overridden on a per-class basis by + * invoking {@link #setClassAssertionStatus(String,boolean)}. + * + * @param packageName the name of the package whose package default + * assertion status is to be set. A null value + * indicates the unnamed package that is "current" + * (JLS 7.4.2). + * @param enabled true if classes loaded by this classloader + * and belonging to the named package or any of its subpackages + * will have assertions enabled by default, false if they + * will have assertions disabled by default. + * @since 1.4 + */ + public synchronized void setPackageAssertionStatus(String packageName, + boolean enabled) + { + if (packageAssertionStatus == null) + initializeJavaAssertionMaps(); + + packageAssertionStatus.put(packageName, Boolean.valueOf(enabled)); + } + + /** + * Sets the desired assertion status for the named top-level class in + * this class loader and any nested classes contained therein. + * This setting takes precedence over the class loader's default + * assertion status, and over any applicable per-package default. + * This method has no effect if the named class has already been + * initialized. (Once a class is initialized, its assertion status cannot + * change.) + *

+ * If the named class is not a top-level class, this call will have no + * effect on the actual assertion status of any class, and its return + * value is undefined. + * + * @param className the fully qualified class name of the top-level class + * whose assertion status is to be set. + * @param enabled true if the named class is to have assertions + * enabled when (and if) it is initialized, false if the + * class is to have assertions disabled. + * @since 1.4 + */ + public synchronized void setClassAssertionStatus(String className, + boolean enabled) + { + if (classAssertionStatus == null) + initializeJavaAssertionMaps(); + + classAssertionStatus.put(className, Boolean.valueOf(enabled)); + } + + /** + * Sets the default assertion status for this class loader to + * false and discards any package defaults or class assertion + * status settings associated with the class loader. This call is + * provided so that class loaders can be made to ignore any command line + * or persistent assertion status settings and "start with a clean slate." + * + * @since 1.4 + */ + public synchronized void clearAssertionStatus() { + /* + * Whether or not "Java assertion maps" are initialized, set + * them to empty maps, effectively ignoring any present settings. + */ + classAssertionStatus = new HashMap(); + packageAssertionStatus = new HashMap(); + + defaultAssertionStatus = false; + } + + /** + * Returns the assertion status that would be assigned to the specified + * class if it were to be initialized at the time this method is invoked. + * If the named class has had its assertion status set, the most recent + * setting will be returned; otherwise, if any package default assertion + * status pertains to this class, the most recent setting for the most + * specific pertinent package default assertion status is returned; + * otherwise, this class loader's default assertion status is returned. + * + * @param className the fully qualified class name of the class whose + * desired assertion status is being queried. + * @return the desired assertion status of the specified class. + * @see #setClassAssertionStatus(String,boolean) + * @see #setPackageAssertionStatus(String,boolean) + * @see #setDefaultAssertionStatus(boolean) + * @since 1.4 + */ + synchronized boolean desiredAssertionStatus(String className) { + Boolean result; + + // assert classAssertionStatus != null; + // assert packageAssertionStatus != null; + + // Check for a class entry + result = (Boolean)classAssertionStatus.get(className); + if (result != null) + return result.booleanValue(); + + // Check for most specific package entry + int dotIndex = className.lastIndexOf("."); + if (dotIndex < 0) { // default package + result = (Boolean)packageAssertionStatus.get(null); + if (result != null) + return result.booleanValue(); + } + while(dotIndex > 0) { + className = className.substring(0, dotIndex); + result = (Boolean)packageAssertionStatus.get(className); + if (result != null) + return result.booleanValue(); + dotIndex = className.lastIndexOf(".", dotIndex-1); + } + + // Return the classloader default + return defaultAssertionStatus; + } + + // Set up the assertions with information provided by the VM. + private void initializeJavaAssertionMaps() { + // assert Thread.holdsLock(this); + + classAssertionStatus = new HashMap(); + packageAssertionStatus = new HashMap(); + AssertionStatusDirectives directives = retrieveDirectives(); + + for(int i=0; iclasses.length; i++) + classAssertionStatus.put(directives.classes[i], + Boolean.valueOf(directives.classEnabled[i])); + + for(int i=0; ipackages.length; i++) + packageAssertionStatus.put(directives.packages[i], + Boolean.valueOf(directives.packageEnabled[i])); + + defaultAssertionStatus = directives.deflt; + } + + // Retrieves the assertion directives from the VM. + private static native AssertionStatusDirectives retrieveDirectives(); + +} + + +class SystemClassLoaderAction implements PrivilegedExceptionAction { + private ClassLoader parent; + + SystemClassLoaderAction(ClassLoader parent) { + this.parent = parent; + } + + public Object run() throws Exception { + ClassLoader sys; + Constructor ctor; + Class c; + Class cp[] = { ClassLoader.class }; + Object params[] = { parent }; + + String cls = System.getProperty("java.system.class.loader"); + if (cls == null) { + return parent; + } + + c = Class.forName(cls, true, parent); + ctor = c.getDeclaredConstructor(cp); + sys = (ClassLoader) ctor.newInstance(params); + Thread.currentThread().setContextClassLoader(sys); + return sys; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aThinlet_hl.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aThinlet_hl.java new file mode 100644 index 000000000000..8aca05ad4bfb --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aThinlet_hl.java @@ -0,0 +1,5393 @@ +/* + Thinlet GUI toolkit - www.thinlet.com + Copyright (C) 2002 Robert Bajzat (robert.bajzat@thinlet.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//package thinlet; //java +//midp package thinlet.midp; + +import java.applet.*; //java +import java.awt.*; //java +import java.awt.datatransfer.*; //java +import java.awt.image.*; //java +import java.awt.event.*; //java +import java.lang.reflect.*; //java +import java.io.*; +import java.net.*; //java +import java.util.*; +//midp import javax.microedition.lcdui.*; +//midp import javax.microedition.midlet.*; + +/** + * + */ +public class Thinlet extends Container //java + implements Runnable, Serializable { //java +//midp public class Thinlet extends Canvas implements CommandListener { + + //midp private static final Boolean TRUE = new Boolean(true); + //midp private static final Boolean FALSE = new Boolean(false); + + //midp private transient Font font; + private transient Color c_bg; + private transient Color c_text; + private transient Color c_textbg; + private transient Color c_border; + private transient Color c_disable; + private transient Color c_hover; + private transient Color c_press; + private transient Color c_focus; + private transient Color c_select; + private transient Color c_ctrl = null; //java + //midp private transient Color c_ctrl; + private transient int block; + private transient Image gradient; //java + { + setFont(new Font("SansSerif", Font.PLAIN, 12)); //java + //midp setFont(Font.getDefaultFont()); + setColors(0xe6e6e6, 0x000000, 0xffffff, + 0x909090, 0xb0b0b0, 0xededed, 0xb9b9b9, 0x89899a, 0xc5c5dd); // f99237 eac16a // e68b2c ffc73c + } + + private transient Thread timer; + private transient long watchdelay; + private transient long watch; + private transient String clipboard; + + private Object content = createImpl("desktop"); + private transient Object mouseinside; + private transient Object insidepart; + private transient Object mousepressed; + private transient Object pressedpart; + private transient int referencex, referencey; + private transient int mousex, mousey; + private transient Object focusowner; + private transient boolean focusinside; //midp { focusinside = true; } + private transient Object popupowner; + private transient Object tooltipowner; + //private transient int pressedkey; + + //java> + private static final int DRAG_ENTERED = AWTEvent.RESERVED_ID_MAX + 1; + private static final int DRAG_EXITED = AWTEvent.RESERVED_ID_MAX + 2; + + private static long WHEEL_MASK = 0; + private static int MOUSE_WHEEL = 0; + private static Method wheelrotation = null; + static { + try { + WHEEL_MASK = AWTEvent.class.getField("MOUSE_WHEEL_EVENT_MASK").getLong(null); + MOUSE_WHEEL = MouseEvent.class.getField("MOUSE_WHEEL").getInt(null); + } catch (Exception exc) { /* not 1.4 */ } + } + { + if (MOUSE_WHEEL != 0) { // disable global focus-manager for this component in 1.4 + try { + getClass().getMethod("setFocusTraversalKeysEnabled", new Class[] { Boolean.TYPE }). + invoke(this, new Object[] { Boolean.FALSE }); + } catch (Exception exc) { /* never */ } + } + enableEvents(AWTEvent.COMPONENT_EVENT_MASK | + AWTEvent.FOCUS_EVENT_MASK | AWTEvent.KEY_EVENT_MASK | + AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | WHEEL_MASK); + } + //Color(background); c_text = new Color(text); + c_textbg = new Color(textbackground); c_border = new Color(border); + c_disable = new Color(disable); c_hover = new Color(hover); + c_press = new Color(press); c_focus = new Color(focus); + c_select = new Color(select); + //midp c_ctrl = c_hover; + //java> + int[] pix = new int[block * block]; + int r1 = c_bg.getRed(); int r2 = c_press.getRed(); + int g1 = c_bg.getGreen(); int g2 = c_press.getGreen(); + int b1 = c_bg.getBlue(); int b2 = c_press.getBlue(); + for (int i = 0; i < block; i++) { + int r = r1 - (r1 - r2) * i / block; + int g = g1 - (g1 - g2) * i / block; + int b = b1 - (b1 - b2) * i / block; + int color = (255 << 24) | (r << 16) | (g << 8) | b; + for (int j = 0; j < block; j++) { + pix[i * block + j] = color; + //pix[j * block + i] = color; + } + } + gradient = createImage(new MemoryImageSource(block, block, pix, 0, block)); + //Font font) { + block = getFontMetrics(font).getHeight(); //java + super.setFont(font); //java + //midp block = font.getHeight(); + //midp this.font = font; + } + + /** + * + */ + private void doLayout(Object component) { + String classname = getClass(component); + if ("combobox" == classname) { + if (getBoolean(component, "editable", true)) { + Image icon = getIcon(component, "icon", null); + layoutField(component, block, false, + (icon != null) ? icon.getWidth(this) : 0); + } // set editable -> validate (overwrite textfield repaint) + else { + int selected = getInteger(component, "selected", -1); + if (selected != -1) { + Object choice = getItem(component, "choice", selected); + set(component, "text", get(choice, "text")); + set(component, "icon", get(choice, "icon")); + } + } + } + else if (("textfield" == classname) || ("passwordfield" == classname)) { + layoutField(component, 0, ("passwordfield" == classname), 0); + } + else if ("textarea" == classname) { + String text = getString(component, "text", ""); + int start = getInteger(component, "start", 0); + if (start > text.length()) { setInteger(component, "start", start = text.length(), 0); } + int end = getInteger(component, "end", 0); + if (end > text.length()) { setInteger(component, "end", end = text.length(), 0); } + int caretx = 0; int carety = 0; + FontMetrics fm = getFontMetrics(getFont()); //java + int width = 0, height = 0; + for (int i = 0, j = 0; j != -1; i = j + 1) { + j = text.indexOf('\n', i); + if (i != j) { // && i != text.length() + String line = (j != -1) ? text.substring(i, j) : text.substring(i); //java + width = Math.max(width, fm.stringWidth(line)); //java + //midp width = font.substringWidth(text, i, ((j != -1) ? j : text.length()) - i); + } + if ((end >= i) && ((j == -1) || (end <= j))) { + caretx = fm.stringWidth(text.substring(i, end)); //java + //midp caretx = font.substringWidth(text, i, end - i); + carety = height; + } + height += fm.getHeight(); + } + layoutScrollPane(component, width + 2, + height - fm.getLeading() + 2, 0, 0); + scrollToVisible(component, caretx, carety, + 2, fm.getAscent() + fm.getDescent() + 2); + } + else if ("tabbedpane" == classname) { + Rectangle bounds = getRectangle(component, "bounds"); + String placement = getString(component, "placement", "top"); + boolean horizontal = ((placement == "top") || (placement == "bottom")); + int tabd = 0; + int tabsize = 0; + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Dimension d = getSize(comp, 8, 4, "left"); + setRectangle(comp, "bounds", + horizontal ? tabd : 0, horizontal ? 0 : tabd, d.width, d.height); + tabd += horizontal ? d.width : d.height; + tabsize = Math.max(tabsize, horizontal ? d.height : d.width); + } + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Rectangle r = getRectangle(comp, "bounds"); + if (horizontal) { + if (placement == "bottom") { r.y = bounds.height - tabsize; } + r.height = tabsize; + } else { + if (placement == "right") { r.x = bounds.width - tabsize; } + r.width = tabsize; + } + } + int cx = (placement == "left") ? (tabsize + 1) : 2; + int cy = (placement == "top") ? (tabsize + 1) : 2; + int cwidth = bounds.width - (horizontal ? 4 : (tabsize + 3)); + int cheight = bounds.height - (horizontal ? (tabsize + 3) : 4); + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if (!getBoolean(comp, "visible", true)) { continue; } + setRectangle(comp, "bounds", cx, cy, cwidth, cheight); + doLayout(comp); + } + } + else if (("panel" == classname) || (classname == "dialog")) { + int gap = getInteger(component, "gap", 0); + int[][] grid = getGrid(component, gap); + if (grid != null) { + int top = getInteger(component, "top", 0); + int left = getInteger(component, "left", 0); + int bottom = getInteger(component, "bottom", 0); + int right = getInteger(component, "right", 0); + if (classname == "dialog") { + int titleheight = getInteger(component, "titleheight", 0); + top += 4 + titleheight; left += 4; bottom += 4; right += 4; + } + + Rectangle bounds = getRectangle(component, "bounds"); + for (int i = 0; i < 2; i++) { + int d = ((i == 0) ? (bounds.width - left - right) : + (bounds.height - top - bottom)) - + getSum(grid[i], 0, grid[i].length, gap, false); + if (d != 0) { + int w = getSum(grid[2 + i], 0, grid[2 + i].length, 0, false); + if (w > 0) { + for (int j = 0; j < grid[i].length; j++) { + if (grid[2 + i][j] != 0) { + grid[i][j] += d * grid[2 + i][j] / w; + } + } + } + } + } + + int i = 0; + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if (!getBoolean(comp, "visible", true)) { continue; } + int ix = left + getSum(grid[0], 0, grid[4][i], gap, true); + int iy = top + getSum(grid[1], 0, grid[5][i], gap, true); + int iwidth = getSum(grid[0], grid[4][i], grid[6][i], gap, false); + int iheight = getSum(grid[1], grid[5][i], grid[7][i], gap, false); + String halign = getString(comp, "halign", "fill"); + String valign = getString(comp, "valign", "fill"); + if ((halign != "fill") || (valign != "fill")) { + Dimension d = getPreferredSize(comp); + if (halign != "fill") { + int dw = Math.max(0, iwidth - d.width); + if (halign == "center") { ix += dw / 2; } + else if (halign == "right") { ix += dw; } + iwidth -= dw; + } + if (valign != "fill") { + int dh = Math.max(0, iheight - d.height); + if (valign == "center") { iy += dh / 2; } + else if (valign == "bottom") { iy += dh; } + iheight -= dh; + } + } + setRectangle(comp, "bounds", ix, iy, iwidth, iheight); + doLayout(comp); + i++; + } + } + } + else if ("desktop" == classname) { + Rectangle bounds = getRectangle(component, "bounds"); + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + String iclass = getClass(comp); + if (iclass == "dialog") { + Dimension d = getPreferredSize(comp); + if (get(comp, "bounds") == null) + setRectangle(comp, "bounds", + Math.max(0, (bounds.width - d.width) / 2), + Math.max(0, (bounds.height - d.height) / 2), + Math.min(d.width, bounds.width), Math.min(d.height, bounds.height)); + } else if ((iclass == "combolist") || (iclass == "popupmenu")) { + iclass = iclass; //compiler bug + } else { + setRectangle(comp, "bounds", 0, 0, bounds.width, bounds.height); + } + doLayout(comp); + } + } + else if ("spinbox" == classname) { + layoutField(component, block, false, 0); + } + else if ("splitpane" == classname) { + Rectangle bounds = getRectangle(component, "bounds"); + boolean horizontal = ("vertical" != get(component, "orientation")); + int divider = getInteger(component, "divider", -1); + int maxdiv = (horizontal ? bounds.width : bounds.height) - 5; + + Object comp1 = get(component, "component"); + boolean visible1 = (comp1 != null) && getBoolean(comp1, "visible", true); + if (divider == -1) { + int d1 = 0; + if (visible1) { + Dimension d = getPreferredSize(comp1); + d1 = horizontal ? d.width : d.height; + } + divider = Math.min(d1, maxdiv); + setInteger(component, "divider", divider, -1); + } + else if (divider > maxdiv) { + setInteger(component, "divider", divider = maxdiv, -1); + } + + if (visible1) { + setRectangle(comp1, "bounds", 0, 0, horizontal ? divider : bounds.width, + horizontal ? bounds.height : divider); + doLayout(comp1); + } + Object comp2 = (comp1 != null) ? get(comp1, ":next") : null; + if ((comp2 != null) && getBoolean(comp2, "visible", true)) { + setRectangle(comp2, "bounds", horizontal ? (divider + 5) : 0, + horizontal ? 0 : (divider + 5), + horizontal ? (bounds.width - 5 - divider) : bounds.width, + horizontal ? bounds.height : (bounds.height - 5 - divider)); + doLayout(comp2); + } + } + else if (("list" == classname) || + ("table" == classname) || ("tree" == classname)) { + int width = 0; + int columnheight = 0; + if ("table" == classname) { + for (Object column = get(component, "column"); + column != null; column = get(column, ":next")) { + width += getInteger(column, "width", 80); + Dimension d = getSize(column, 2, 2, "left"); + columnheight = Math.max(columnheight, d.height); + } + } + String itemname = ("list" == classname) ? "item" : + (("table" == classname) ? "row" : "node"); + int y = 0; + int level = 0; + for (Object item = get(component, itemname); item != null;) { + int x = 0; + int iwidth = 0; int iheight = 0; + if ("table" == classname) { + iwidth = width; + for (Object cell = get(item, "cell"); + cell != null; cell = get(cell, ":next")) { + Dimension d = getSize(cell, 2, 3, "left"); + iheight = Math.max(iheight, d.height); + } + } + else { + if ("tree" == classname) { + x = (level + 1) * block; + } + Dimension d = getSize(item, 2, 3, "left"); + iwidth = d.width; iheight = d.height; + width = Math.max(width, x + d.width); + } + setRectangle(item, "bounds", x, y, iwidth, iheight); + y += iheight; + if ("tree" == classname) { + Object next = get(item, "node"); + if ((next != null) && getBoolean(item, "expanded", true)) { + level++; + } else { + while (((next = get(item, ":next")) == null) && (level > 0)) { + item = getParent(item); + level--; + } + } + item = next; + } else { + item = get(item, ":next"); + } + } + layoutScrollPane(component, width, y - 1, 0, columnheight); + } + else if ("menubar" == classname) { + Rectangle bounds = getRectangle(component, "bounds"); + int x = 0; + for (Object menu = get(component, "menu"); + menu != null; menu = get(menu, ":next")) { + Dimension d = getSize(menu, 8, 4, "left"); + setRectangle(menu, "bounds", x, 0, d.width, bounds.height); + x += d.width; + } + } + else if (("combolist" == classname) || ("popupmenu" == classname)) { + boolean combo = ("combolist" == classname); + int pw = 0; int ph = 0; int pxy = combo ? 0 : 1; + for (Object item = get(get(component, combo ? "combobox" : "menu"), + combo ? "choice" : "menu"); item != null; item = get(item, ":next")) { + String itemclass = combo ? null : getClass(item); + Dimension d = (itemclass == "separator") ? new Dimension(1, 1) : + getSize(item, 8 , 4, "left"); + if (itemclass == "checkboxmenuitem") { + d.width = d.width + block + 3; + d.height = Math.max(block, d.height); + } + else if (itemclass == "menu") { + d.width += block; + } + setRectangle(item, "bounds", pxy, pxy + ph, d.width, d.height); + pw = Math.max(pw, d.width); + ph += d.height; + } + Rectangle r = getRectangle(component, "bounds"); + r.width = pw + 2; r.height = ph + 2; + if (combo) { + Rectangle db = getRectangle(content, "bounds"); + if (r.y + ph + 2 > db.height) { + r.width = pw + 2 + block; + r.height = db.height - r.y; + } + else { + r.height = Math.min(r.height, db.height - r.y); + } + r.width = Math.min(r.width, db.width - r.x); + layoutScrollPane(component, pw, ph, 0, 0);//~ + } + } + //java> + else if ("bean" == classname) { + Rectangle r = getRectangle(component, "bounds"); + ((Component) get(component, "bean")).setBounds(r); + } + //MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); //java + } + popup(popupmenu, "popupmenu"); + } + if ((selected == null) || (getClass(selected) != "menu")) { return null; } + popup = createImpl("popupmenu"); + set(popup, "menu", selected); + set(component, "popupmenu", popup); + + Rectangle bounds = getRectangle(selected, "bounds"); + if ("menubar" == classname) { + px = bounds.x; py = bounds.y + bounds.height - 1; + } else { + px = bounds.x + getRectangle(component, "bounds").width - 4; + py = bounds.y; + } + } + else { //if ("combobox" == classname) { + popup = createImpl("combolist"); + set(popup, "combobox", component); + set(component, "combolist", popup); + + py = getRectangle(component, "bounds").height + 1; + } + if (("menubar" == classname) || ("combobox" == classname)) { + popupowner = component; + } + insertItem(content, "component", popup, 0); + set(popup, ":parent", content); + while (component != content) { + Rectangle r = getRectangle(component, "bounds"); + px += r.x; py += r.y; + component = getParent(component); + } + setRectangle(popup, "bounds", px, py, 0, 0); + doLayout(popup); repaint(popup); + return popup; + } + + /** + * + */ + private void closeup(Object combobox, Object combolist, Object item) { + if ((item != null) && getBoolean(item, "enabled", true)) { + String text = getString(item, "text", ""); + set(combobox, "text", text); // if editable + setInteger(combobox, "start", text.length(), 0); + setInteger(combobox, "end", 0, 0); + set(combobox, "icon", get(item, "icon")); + validate(combobox); + setInteger(combobox, "selected", getIndex(combobox, "choice", item), -1); + invoke(combobox, "action"); + } + set(combolist, "combobox", null); + set(combobox, "combolist", null); + removeItemImpl(content, "component", combolist); + repaint(combolist); + set(combolist, ":parent", null); + popupowner = null; + if (mouseinside == combolist) { + findComponent(content, mousex, mousey); + handleMouseEvent(mousex, mousex, 1, false, false, false, //java + MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); //java + } + } + + /** + * + */ + private void closeup(Object menubar) { + set(menubar, "selected", null); + popup(menubar, "menubar"); + repaint(menubar); // , selected + popupowner = null; + } + + /** + * + */ + private void closeup() { + if (popupowner != null) { + String classname = getClass(popupowner); + if ("menubar" == classname) { + closeup(popupowner); + } + else if ("combobox" == classname) { + closeup(popupowner, get(popupowner, "combolist"), null); + } + } + } + + /** + * + */ + private void showTip() { + String text = null; + tooltipowner = null; + String classname = getClass(mouseinside); + if ((classname == "tabbedpane") || (classname == "menubar") || (classname == "popupmenu")) { + if (insidepart != null) { + text = getString(insidepart, "tooltip", null); + } + } + else if (classname == "combolist") { + if (insidepart instanceof Object[]) { + text = getString(insidepart, "tooltip", null); + } + } + //list table tree + if (text == null) { text = getString(mouseinside, "tooltip", null); } + else { tooltipowner = insidepart; } + if (text != null) { + FontMetrics fm = getFontMetrics(getFont()); + int width = fm.stringWidth(text) + 4; + int height = fm.getAscent() + fm.getDescent() + 4; + if (tooltipowner == null) { tooltipowner = mouseinside; } + setRectangle(tooltipowner, "tooltipbounds", mousex + 10, mousey + 10, width, height); + repaint(mousex + 10, mousey + 10, width, height); + } + } + + /** + * + */ + private void hideTip() { + if (tooltipowner != null) { + Rectangle bounds = getRectangle(tooltipowner, "tooltipbounds"); + set(tooltipowner, "tooltipbounds", null); + tooltipowner = null; + repaint(bounds.x, bounds.y, bounds.width, bounds.height); + } + } + + /** + * + */ + private void layoutField(Object component, int dw, boolean hidden, int left) { + int width = getRectangle(component, "bounds").width - left -dw; + String text = getString(component, "text", ""); + int start = getInteger(component, "start", 0); + if (start > text.length()) { setInteger(component, "start", start = text.length(), 0); } + int end = getInteger(component, "end", 0); + if (end > text.length()) { setInteger(component, "end", end = text.length(), 0); } + int offset = getInteger(component, "offset", 0); + int off = offset; + FontMetrics fm = getFontMetrics(getFont()); + int caret = hidden ? (fm.charWidth('*') * end) : + fm.stringWidth(text.substring(0, end)); //java + //midp font.substringWidth(text, 0, end); + if (off > caret) { + off = caret; + } + else if (off < caret - width + 4) { + off = caret - width + 4; + } + off = Math.max(0, Math.min(off, (hidden ? (fm.charWidth('*') * + text.length()) : fm.stringWidth(text)) - width + 4)); + if (off != offset) { + setInteger(component, "offset", off, 0); + } + } + + /** + * + */ + private void layoutScrollPane(Object component, + int contentwidth, int contentheight, int rowwidth, int columnheight) { + Rectangle bounds = getRectangle(component, "bounds"); + boolean hneed = false; boolean vneed = false; + if (contentwidth > bounds.width - rowwidth - 2) { + hneed = true; + vneed = (contentheight > bounds.height - columnheight - 2 - block); + } + if (vneed || (contentheight > bounds.height - columnheight - 2)) { + vneed = true; + hneed = hneed || (contentwidth > bounds.width - rowwidth - 2 - block); + } + int viewportwidth = bounds.width - rowwidth - (vneed ? block : 0); + int viewportheight = bounds.height - columnheight - (hneed ? block : 0); + setRectangle(component, ":port", + rowwidth, columnheight, viewportwidth, viewportheight); //?rowwidth + + Rectangle view = getRectangle(component, ":view"); + setRectangle(component, ":view", + (view != null) ? Math.max(0, + Math.min(view.x, contentwidth - viewportwidth + 2)) : 0, + (view != null) ? Math.max(0, + Math.min(view.y, contentheight - viewportheight + 2)) : 0, + Math.max(viewportwidth - 2, contentwidth), + Math.max(viewportheight - 2, contentheight)); + } + + /** + * + */ + private void scrollToVisible(Object component, + int x, int y, int width, int height) { + Rectangle view = getRectangle(component, ":view"); + Rectangle port = getRectangle(component, ":port"); + int vx = Math.max(x + width - port.width + 2, Math.min(view.x, x)); + int vy = Math.max(y + height - port.height + 2, Math.min(view.y, y)); + if ((view.x != vx) || (view.y != vy)) { + repaint(component); // horizontal | vertical + view.x = vx; view.y = vy; + } + } + + /** + * + */ + public Dimension getPreferredSize() { + return getPreferredSize(content); + } + + /** + * + */ + private Dimension getPreferredSize(Object component) { + int width = getInteger(component, "width", 0); + int height = getInteger(component, "height", 0); + if ((width > 0) && (height > 0)) { + return new Dimension(width, height); + } + String classname = getClass(component); + //System.out.println("classname: " + classname); + if ("label" == classname) { + return getSize(component, 0, 0, "left"); + } + if ("button" == classname) { + return getSize(component, 12, 6, "center"); + } + if ("checkbox" == classname) { + Dimension d = getSize(component, 0, 0, "left"); + d.width = d.width + block + 3; + d.height = Math.max(block, d.height); + return d; + } + if ("combobox" == classname) { + if (getBoolean(component, "editable", true)) { + Dimension size = getFieldSize(component); + Image icon = getIcon(component, "icon", null); + if (icon != null) { + size.width += icon.getWidth(this); + size.height = Math.max(size.height, icon.getHeight(this) + 2); + } + size.width += block; + return size; + } else { + int selected = getInteger(component, "selected", -1); + return getSize((selected != -1) ? + getItemImpl(component, "choice", selected) : + get(component, "choice"), 4 + block, 4, "left"); + } + } + if (("textfield" == classname) || ("passwordfield" == classname)) { + return getFieldSize(component); + } + if ("textarea" == classname) { + int columns = getInteger(component, "columns", 0); + int rows = getInteger(component, "rows", 0); // 'e' -> 'm' ? + FontMetrics fm = getFontMetrics(getFont()); //java + return new Dimension( + ((columns > 0) ? (columns * fm.charWidth('e') + 2) : 76) + 2 + block, + ((rows > 0) ? (rows * fm.getHeight() - fm.getLeading() + 2) : 76) + 2 + block); + } + if ("tabbedpane" == classname) { + String placement = getString(component, "placement", "top"); + boolean horizontal = ((placement == "top") || (placement == "bottom")); + int tabsize = 0; + int contentwidth = 0; int contentheight = 0; + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Dimension d = getSize(comp, 8, 4, "left"); + tabsize = Math.max(tabsize, horizontal ? d.height : d.width); + } + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if (!getBoolean(comp, "visible", true)) { continue; } + Dimension d = getPreferredSize(comp); + contentwidth = Math.max(contentwidth, d.width); + contentheight = Math.max(contentheight, d.height); + } + return new Dimension(contentwidth + (horizontal ? 4 : (tabsize + 3)), + contentheight + (horizontal ? (tabsize + 3) : 4)); + } + if (("panel" == classname) || (classname == "dialog")) { + Dimension size = new Dimension( + getInteger(component, "left", 0) + getInteger(component, "right", 0), + getInteger(component, "top", 0) + getInteger(component, "bottom", 0)); + if (classname == "dialog") { + int titleheight = getSize(component, 0, 0, "left").height; + setInteger(component, "titleheight", titleheight, 0); + size.width += 8; size.height += 8 + titleheight; + } + int gap = getInteger(component, "gap", 0); + int[][] grid = getGrid(component, gap); + if (grid != null) { + size.width += getSum(grid[0], 0, grid[0].length, gap, false); + size.height += getSum(grid[1], 0, grid[1].length, gap, false); + } + return size; + } + else if ("desktop" == classname) { + Dimension size = new Dimension(); + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + String iclass = getClass(comp); + if ((iclass != "dialog") && (iclass != "popupmenu") && + (iclass != "combolist")) { + Dimension d = getPreferredSize(comp); + size.width = Math.max(d.width, size.width); + size.height = Math.max(d.height, size.height); + } + } + return size; + } + if ("spinbox" == classname) { + Dimension size = getFieldSize(component); + size.width += block; + return size; + } + if ("progressbar" == classname) { + boolean horizontal = ("vertical" != get(component, "orientation")); + return new Dimension(horizontal ? 76 : 6, horizontal ? 6 : 76); + } + if ("slider" == classname) { + boolean horizontal = ("vertical" != get(component, "orientation")); + return new Dimension(horizontal ? 76 : 10, horizontal ? 10 : 76); + } + if ("splitpane" == classname) { + boolean horizontal = ("vertical" != get(component, "orientation")); + Object comp1 = get(component, "component"); + Dimension size = ((comp1 == null) || !getBoolean(comp1, "visible", true)) ? + new Dimension() : getPreferredSize(comp1); + Object comp2 = get(comp1, ":next"); + if ((comp2 != null) && getBoolean(comp2, "visible", true)) { + Dimension d = getPreferredSize(comp2); + size.width = horizontal ? (size.width + d.width) : + Math.max(size.width, d.width); + size.height = horizontal ? Math.max(size.height, d.height) : + (size.height + d.height); + } + if (horizontal) { size.width += 5; } else { size.height += 5; } + return size; + } + if (("list" == classname) || + ("table" == classname) || ("tree" == classname)) { + return new Dimension(76 + 2 + block, 76 + 2 + block); + } + if ("separator" == classname) { + return new Dimension(1, 1); + } + if ("menubar" == classname) { + Dimension size = new Dimension(0, 0); + for (Object menu = get(component, "menu"); + menu != null; menu = get(menu, ":next")) { + Dimension d = getSize(menu, 8, 4, "left"); + size.width += d.width; + size.height = Math.max(size.height, d.height); + } + return size; + } + //java> + if ("bean" == classname) { + return ((Component) get(component, "bean")).getPreferredSize(); + } + // columns)) { + x = 0; y++; j = -1; + } + else if (columnheight[x + j] > y) { + x += (j + 1); j = -1; + } + } + if (y + rowspan > grid[1].length) { + int[] rowheights = new int[y + rowspan]; + System.arraycopy(grid[1], 0, rowheights, 0, grid[1].length); + grid[1] = rowheights; + int[] rowweights = new int[y + rowspan]; + System.arraycopy(grid[3], 0, rowweights, 0, grid[3].length); + grid[3] = rowweights; + } + for (int j = 0; j < colspan; j++) { + columnheight[x + j] = y + rowspan; + } + + int weightx = getInteger(comp, "weightx", 0); + int weighty = getInteger(comp, "weighty", 0); + Dimension d = getPreferredSize(comp); + + if (colspan == 1) { + grid[0][x] = Math.max(grid[0][x], d.width); // columnwidths + grid[2][x] = Math.max(grid[2][x], weightx); // columnweights + } + else { + if (cache == null) { cache = new int[4][count]; } + cache[0][i] = d.width; + cache[2][i] = weightx; + if ((nextsize == 0) || (colspan < nextsize)) { nextsize = colspan; } + } + if (rowspan == 1) { + grid[1][y] = Math.max(grid[1][y], d.height); // rowheights + grid[3][y] = Math.max(grid[3][y], weighty); // rowweights + } + else { + if (cache == null) { cache = new int[4][count]; } + cache[1][i] = d.height; + cache[3][i] = weighty; + if ((nextsize == 0) || (rowspan < nextsize)) { nextsize = rowspan; } + } + grid[4][i] = x; //gridx + grid[5][i] = y; //gridy + grid[6][i] = colspan; //gridwidth + grid[7][i] = rowspan; //gridheight + + x += colspan; + i++; + } + + while (nextsize != 0) { + int size = nextsize; nextsize = 0; + for (int j = 0; j < 2; j++) { // horizontal, vertical + for (int k = 0; k < count; k++) { + if (grid[6 + j][k] == size) { // gridwidth, gridheight + int gridpoint = grid[4 + j][k]; // gridx, gridy + + int weightdiff = cache[2 + j][k]; + for (int m = 0; (weightdiff > 0) && (m < size); m++) { + weightdiff -= grid[2 + j][gridpoint + m]; + } + if (weightdiff > 0) { + int weightsum = cache[2 + j][k] - weightdiff; + for (int m = 0; (weightsum > 0) && (m < size); m++) { + int weight = grid[2 + j][gridpoint + m]; + if (weight > 0) { + int weightinc = weight * weightdiff / weightsum; + grid[2 + j][gridpoint + m] += weightinc; + weightdiff -= weightinc; + weightsum -= weightinc; + } + } + grid[2 + j][gridpoint + size - 1] += weightdiff; + } + + int sizediff = cache[j][k]; + int weightsum = 0; + for (int m = 0; (sizediff > 0) && (m < size); m++) { + sizediff -= grid[j][gridpoint + m]; + weightsum += grid[2 + j][gridpoint + m]; + } + if (sizediff > 0) { + for (int m = 0; (weightsum > 0) && (m < size); m++) { + int weight = grid[2 + j][gridpoint + m]; + if (weight > 0) { + int sizeinc = weight * sizediff / weightsum; + grid[j][gridpoint + m] += sizeinc; + sizediff -= sizeinc; + weightsum -= weight; + } + } + grid[j][gridpoint + size - 1] += sizediff; + } + } + else if ((grid[6 + j][k] > size) && + ((nextsize == 0) || (grid[6 + j][k] < nextsize))) { + nextsize = grid[6 + j][k]; + } + } + } + } + return grid; + } + + /** + * + */ + private int getSum(int[] values, + int from, int length, int gap, boolean last) { + if (length <= 0) { return 0; } + int value = 0; + for (int i = 0; i < length; i++) { + value += values[from + i]; + } + return value + (length - (last ? 0 : 1)) * gap; + } + + /** + * + */ + private Dimension getFieldSize(Object component) { + String text = getString(component, "text", ""); + int columns = getInteger(component, "columns", 0); + FontMetrics fm = getFontMetrics(getFont()); + return new Dimension(((columns > 0) ? + (columns * fm.charWidth('e')) : 76) + 4, + fm.getAscent() + fm.getDescent() + 4); // fm.stringWidth(text) + } + + /** + * + */ + private Dimension getSize(Object component, + int dx, int dy, String defaultalignment) { + String text = getString(component, "text", null); + int tw = 0; int th = 0; + if (text != null) { + FontMetrics fm = getFontMetrics(getFont()); + tw = fm.stringWidth(text); + th = fm.getAscent() + fm.getDescent(); + } + Image icon = getIcon(component, "icon", null); + int iw = 0; int ih = 0; + if (icon != null) { + iw = icon.getWidth(this); + ih = icon.getHeight(this); + } + return new Dimension(tw + iw + dx, Math.max(th, ih) + dy); + } + //java> + + /** + * + */ + public void update(Graphics g) { + paint(g); + } + + /** + *~ + */ + public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { + if (infoflags == ImageObserver.ALLBITS) { + validate(content); + return super.imageUpdate(img, infoflags, x, y, width, height); + } + return true; + } + + /** + * + */ + public void paint(Graphics g) { + //g.setColor(Color.orange); + //g.fillRect(0, 0, getSize().width, getSize().height); + //long time = System.currentTimeMillis(); + Rectangle clip = g.getClipBounds(); + ///dg.setClip(r.x, r.y, r.width, r.height); + paint(g, clip.x, clip.y, clip.width, clip.height, content, isEnabled()); + //System.out.println(System.currentTimeMillis() - time); + ///g.setClip(0, 0, getSize().width, getSize().height); + //g.setColor(Color.red); g.drawRect(clip.x, clip.y, clip.width - 1, clip.height - 1); + } + + //Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, + Object component, boolean enabled) { + if (!getBoolean(component, "visible", true)) { return; } + Rectangle bounds = getRectangle(component, "bounds"); + if (bounds == null) { return; } + if (bounds.width < 0) { + bounds.width = Math.abs(bounds.width); + doLayout(component); + } + if ((clipx + clipwidth < bounds.x) || + (clipx > bounds.x + bounds.width) || + (clipy + clipheight < bounds.y) || + (clipy > bounds.y + bounds.height)) { + return; + } + clipx -= bounds.x; clipy -= bounds.y; + String classname = getClass(component); + boolean pressed = (mousepressed == component); + boolean inside = (mouseinside == component) && + ((mousepressed == null) || pressed); + boolean focus = focusinside && (focusowner == component); + enabled = getBoolean(component, "enabled", true); //enabled && + g.translate(bounds.x, bounds.y); + //g.setClip(0, 0, bounds.width, bounds.height); + + if ("label" == classname) { + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + 0, 0, bounds.width, bounds.height, + enabled ? c_text : c_disable, "left", true); + } + else if ("button" == classname) { + paintRect(g, 0, 0, bounds.width, bounds.height, + enabled ? c_border : c_disable, + enabled ? ((inside != pressed) ? c_hover : + (pressed ? c_press : c_ctrl)) : c_bg, true, true, true, true); + if (focus) { + g.setColor(c_focus); + g.drawRect(2, 2, bounds.width - 5, bounds.height - 5); + } + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + 6, 3, bounds.width - 12, bounds.height - 6, + enabled ? c_text : c_disable, "center", true); + } + else if ("checkbox" == classname) { + boolean selected = getBoolean(component, "selected", false); + String group = getString(component, "group", null); + Color border = enabled ? c_border : c_disable; + Color foreground = enabled ? ((inside != pressed) ? c_hover : + (pressed ? c_press : c_ctrl)) : c_bg; + int dy = (bounds.height - block + 2) / 2; + if (group == null) { + paintRect(g, 1, dy + 1, block - 2, block - 2, + border, foreground, true, true, true, true); + } else { + g.setColor((foreground != c_ctrl) ? foreground : c_bg); + g.fillOval(1, dy + 1, block - 3, block - 3); //java + g.setColor(border); + g.drawOval(1, dy + 1, block - 3, block - 3); //java + } + if (focus) { + g.setColor(c_focus); + if (group == null) { + g.drawRect(3, dy + 3, block - 7, block - 7); + } else { + g.drawOval(3, dy + 3, block - 7, block - 7); //java + } + } + if((!selected && inside && pressed) || + (selected && (!inside || !pressed))) { + g.setColor(enabled ? c_text : c_disable); + if (group == null) { + g.fillRect(3, dy + block - 9, 2, 6); + g.drawLine(3, dy + block - 4, block - 4, dy + 3); + g.drawLine(4, dy + block - 4, block - 4, dy + 4); + } else { + g.fillOval(5, dy + 5, block - 10, block - 10); //java + g.drawOval(4, dy + 4, block - 9, block - 9); //java + } + } + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + block + 3, 0, bounds.width - block - 3, bounds.height, + enabled ? c_text : c_disable, "left", true); + } + else if ("combobox" == classname) { + if (getBoolean(component, "editable", true)) { + Image icon = getIcon(component, "icon", null); + int left = (icon != null) ? icon.getWidth(this) : 0; + paintField(g, clipx, clipy, clipwidth, clipheight, component, + bounds.width - block, bounds.height, + inside, pressed, focus, enabled, false, left); + if (icon != null) { + g.drawImage(icon, 2, (bounds.height - icon.getHeight(this)) / 2, this); //java + //midp g.drawImage(icon, 2, bounds.height / 2, Graphics.LEFT | Graphics.VCENTER); + } + paintArrow(g, bounds.width - block, 0, block, bounds.height, + 'S', enabled, inside, pressed, "down", true, false, true, true); + } else { + paintRect(g, 0, 0, bounds.width, bounds.height, + enabled ? c_border : c_disable, + enabled ? ((inside != pressed) ? c_hover : + (pressed ? c_press : c_ctrl)) : c_bg, true, true, true, true); + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + 2, 2, bounds.width - block - 4, bounds.height - 4, + enabled ? c_text : c_disable, "left", false); + paintArrow(g, bounds.width - block, 0, block, bounds.height, 'S'); + if (focus) { + g.setColor(c_focus); + g.drawRect(2, 2, bounds.width - block - 5, bounds.height - 5); + } + } + } + else if ("combolist" == classname) { + Rectangle view = getRectangle(component, ":view"); + Rectangle viewport = getRectangle(component, ":port"); + g.setColor(c_border); + g.drawRect(viewport.x, viewport.y, viewport.width - 1, viewport.height - 1); + if (paintScrollPane(g, clipx, clipy, clipwidth, clipheight, + bounds, view, viewport, enabled, inside, pressed)) { + Object selected = get(component, "inside"); + int ly = clipy - viewport.y - 1; + int yfrom = view.y + Math.max(0, ly); + int yto = view.y + Math.min(viewport.height - 2, ly + clipheight); + for (Object choice = get(get(component, "combobox"), "choice"); + choice != null; choice = get(choice, ":next")) { + Rectangle r = getRectangle(choice, "bounds"); + if (yto <= r.y) { break; } + if (yfrom >= r.y + r.height) { continue; } + boolean armed = (selected == choice); + paintRect(g, r.x, r.y, bounds.width - 2, r.height, c_border, + armed ? c_select : c_bg, false, false, false, false); + paintContent(choice, g, clipx, yfrom, clipwidth, yto - yfrom, + r.x + 4, r.y + 2, bounds.width - 10, r.height - 4, + getBoolean(choice, "enabled", true) ? c_text : c_disable, "left", false); + } + resetScrollPane(g, clipx, clipy, clipwidth, clipheight, view, viewport); + } + //paintRect(g, 0, 0, bounds.width, bounds.height, + // secondary1, c_ctrl, true, true, true, true); + } + else if (("textfield" == classname) || ("passwordfield" == classname)) { + paintField(g, clipx, clipy, clipwidth, clipheight, component, + bounds.width, bounds.height, + inside, pressed, focus, enabled, ("passwordfield" == classname), 0); + } + else if ("textarea" == classname) { + Rectangle view = getRectangle(component, ":view"); + Rectangle viewport = getRectangle(component, ":port"); + boolean editable = getBoolean(component, "editable", true); + paintRect(g, viewport.x, viewport.y, viewport.width, viewport.height, + enabled ? c_border : c_disable, editable ? c_textbg : c_bg, + true, true, true, true); + if (paintScrollPane(g, clipx, clipy, clipwidth, clipheight, + bounds, view, viewport, enabled, inside, pressed)) { + String text = getString(component, "text", ""); + int start = focus ? getInteger(component, "start", 0) : 0; + int end = focus ? getInteger(component, "end", 0) : 0; + int is = Math.min(start, end); int ie = Math.max(start, end); + boolean wrap = getBoolean(component, "wrap", false); + FontMetrics fm = g.getFontMetrics(); //java + int fontascent = fm.getAscent(); int fontheight = fm.getHeight(); //java + //midp int fontheight = fm.getHeight(); + int ascent = 1; + int ly = clipy - viewport.y - 1; + int yfrom = view.y + Math.max(0, ly); + int yto = view.y + Math.min(viewport.height - 2, ly + clipheight); + //g.setColor(Color.pink); g.fillRect(0, yfrom - 1, 75, 2); g.fillRect(0, yto - 1, 75, 2); + + boolean prevletter = false; int n = text.length(); char c = 0; + for (int i = 0, j = -1, k = 0; k <= n; k++) { // j is the last space index (before k) + if (yto <= ascent) { break; } + if (wrap) { + if (((k == n) || ((c = text.charAt(k)) == '\n') || (c == ' ')) && + (j > i) && (fm.stringWidth(text.substring(i, k)) > viewport.width - 4)) { + k--; // draw line to the begin of the current word (+ spaces) if it is out of width + } + else if ((k == n) || (c == '\n')) { // draw line to the text/line end + j = k; prevletter = false; + } + else { + if ((c == ' ') && (prevletter || (j > i))) { j = k; } // keep spaces starting the line + prevletter = (c != ' '); + continue; + } + } + else { + if ((k == n) || ((c = text.charAt(k)) == '\n')) { j = k; } else { continue; } + } + if (yfrom < ascent + fontheight) { + String line = (j != -1) ? text.substring(i, j) : text.substring(i); //java + if (focus && (is != ie) && (ie >= i) && ((j == -1) || (is <= j))) { + int xs = (is < i) ? -1 : (((j != -1) && (is > j)) ? (view.width - 1) : + fm.stringWidth(text.substring(i, is))); //java + //midp font.substringWidth(text, i, is - i)); + int xe = ((j != -1) && (ie > j)) ? (view.width - 1) : + fm.stringWidth(text.substring(i, ie)); //java + //midp font.substringWidth(text, i, ie - i); + g.setColor(c_select); + g.fillRect(1 + xs, ascent, xe - xs, fontheight); + } + g.setColor(enabled ? c_text : c_disable); + g.drawString(line, 1, ascent + fontascent); //java + //midp g.drawSubstring(text, i, ((j != -1) ? j : text.length()) - i, 1, ascent, Graphics.LEFT | Graphics.TOP); + if (focus && (end >= i) && ((j == -1) || (end <= j))) { + int caret = fm.stringWidth(text.substring(i, end)); //java + //midp int caret = font.substringWidth(text, i, end - i); + g.setColor(c_focus); + g.fillRect(caret, ascent, 1, fontheight); + } + } + ascent += fontheight; + i = j + 1; + } + resetScrollPane(g, clipx, clipy, clipwidth, clipheight, view, viewport); + } + } + else if ("tabbedpane" == classname) { + int i = 0; Rectangle last = null; + int selected = getInteger(component, "selected", 0); + String placement = getString(component, "placement", "top"); + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Rectangle r = getRectangle(comp, "bounds"); + boolean hover = !(selected == i) && inside && + (mousepressed == null) && (insidepart == comp); + boolean sel = (selected == i); + boolean tabenabled = enabled && getBoolean(comp, "enabled", true); + paintRect(g, r.x, r.y, r.width, r.height, + enabled ? c_border : c_disable, + tabenabled ? (sel ? c_bg : (hover ? c_hover : c_ctrl)) : c_ctrl, + (placement != "bottom") || !sel, (placement != "right") || !sel, + (placement == "bottom") || ((placement == "top") && !sel), + (placement == "right") || ((placement == "left") && !sel)); + if (focus && sel) { + g.setColor(c_focus); + g.drawRect(r.x + 2, r.y + 2, r.width - 4, r.height - 4); + } + paintContent(comp, g, clipx, clipy, clipwidth, clipheight, + r.x + 4, r.y + 2, r.width - 8, r.height - 4, + tabenabled ? c_text : c_disable, "left", true); + i++; last = r; + } + if (last != null) { + boolean horizontal = ((placement == "top") || (placement == "bottom")); + paintRect(g, horizontal ? (last.x + last.width) : last.x, + horizontal ? last.y : (last.y + last.height), + horizontal ? (bounds.width - last.x - last.width) : last.width, + horizontal ? last.height : (bounds.height - last.y - last.height), + enabled ? c_border : c_disable, c_bg, + (placement != "top"), (placement != "left"), + (placement == "top"), (placement == "left")); + paintRect(g, (placement == "left") ? last.width : 0, + (placement == "top") ? last.height : 0, + horizontal ? bounds.width : (bounds.width - last.width), + horizontal ? (bounds.height - last.height) : bounds.height, + enabled ? c_border : c_disable, c_bg, + (placement != "top"), (placement != "left"), + (placement != "bottom"), (placement != "right")); + } + Object tabcontent = getItemImpl(component, "component", selected); + if (tabcontent != null) { + paint(g, clipx, clipy, clipwidth, clipheight, tabcontent, enabled); + } + } + else if (("panel" == classname) || ("dialog" == classname)) { + if ("dialog" == classname) { + int titleheight = getInteger(component, "titleheight", 0); + paintRect(g, 0, 0, bounds.width, 3 + titleheight, + c_border, c_ctrl, true, true, false, true); + paintRect(g, 0, 3 + titleheight, bounds.width, bounds.height - 3 - titleheight, + c_border, c_press, false, true, true, true); + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + 3, 2, bounds.width - 6, titleheight, c_text, "left", false); + paintRect(g, 3, 3 + titleheight, bounds.width - 6, bounds.height - 6 - titleheight, + c_border, c_bg, true, true, true, true); + } else { + paintRect(g, 0, 0, bounds.width, bounds.height, + c_border, c_bg, false, false, false, false); + } + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + paint(g, clipx, clipy, clipwidth, clipheight, comp, enabled); + } + } + else if ("desktop" == classname) { + paintReverse(g, clipx, clipy, clipwidth, clipheight, + get(component, "component"), enabled); + //g.setColor(Color.red); if (clip != null) g.drawRect(clipx, clipy, clipwidth, clipheight); + if (tooltipowner != null) { + Rectangle r = getRectangle(tooltipowner, "tooltipbounds"); + paintRect(g, r.x, r.y, r.width, r.height, + c_border, c_bg, true, true, true, true); + String text = getString(tooltipowner, "tooltip", null); + g.setColor(c_text); + g.drawString(text, r.x + 2, r.y + g.getFontMetrics().getAscent() + 2); //java + //midp g.drawString(text, r.x + 2, r.y + (r.height - font.getHeight()) / 2, Graphics.LEFT | Graphics.TOP); + } + } + else if ("spinbox" == classname) { + paintField(g, clipx, clipy, clipwidth, clipheight, component, + bounds.width - block, bounds.height, + inside, pressed, focus, enabled, false, 0); + paintArrow(g, bounds.width - block, 0, block, bounds.height / 2, + 'N', enabled, inside, pressed, "up", true, false, false, true); + paintArrow(g, bounds.width - block, bounds.height / 2, + block, bounds.height - (bounds.height / 2), + 'S', enabled, inside, pressed, "down", true, false, true, true); + } + else if ("progressbar" == classname) { + int minimum = getInteger(component, "minimum", 0); + int maximum = getInteger(component, "maximum", 100); + int value = getInteger(component, "value", 0); + boolean horizontal = ("vertical" != get(component, "orientation")); + int length = (value - minimum) * + ((horizontal ? bounds.width : bounds.height) - 1) / (maximum - minimum); + paintRect(g, 0, 0, horizontal ? length : bounds.width, + horizontal ? bounds.height : length, enabled ? c_border : c_disable, + c_select, true, true, horizontal, !horizontal); + paintRect(g, horizontal ? length : 0, horizontal ? 0 : length, + horizontal ? (bounds.width - length) : bounds.width , + horizontal ? bounds.height : (bounds.height - length), + enabled ? c_border : c_disable, c_bg, true, true, true, true); + } + else if ("slider" == classname) { + int minimum = getInteger(component, "minimum", 0); + int maximum = getInteger(component, "maximum", 100); + int value = getInteger(component, "value", 0); + boolean horizontal = ("vertical" != get(component, "orientation")); + int length = (value - minimum) * + ((horizontal ? bounds.width : bounds.height) - block) / + (maximum - minimum); + paintRect(g, horizontal ? 0 : 3, horizontal ? 3 : 0, + horizontal ? length : (bounds.width - 6), + horizontal ? (bounds.height - 6) : length, + enabled ? c_border : c_disable, + c_bg, true, true, horizontal, !horizontal); + paintRect(g, horizontal ? length : 0, horizontal ? 0 : length, + horizontal ? block : bounds.width, horizontal ? bounds.height : block, + enabled ? c_border : c_disable, + enabled ? c_ctrl : c_bg, true, true, true, true); + if (focus) { + g.setColor(c_focus); + g.drawRect(horizontal ? (length + 2) : 2, horizontal ? 2 : (length + 2), + (horizontal ? block : bounds.width) - 5, + (horizontal ? bounds.height : block) - 5); + //g.drawRect(length + 1, 1, block - 3, bounds.height - 3); + } + paintRect(g, horizontal ? (block + length) : 3, + horizontal ? 3 : (block + length), + bounds.width - (horizontal ? (block + length) : 6), + bounds.height - (horizontal ? 6 : (block + length)), + enabled ? c_border : c_disable, + c_bg, horizontal, !horizontal, true, true); + } + else if ("splitpane" == classname) { + boolean horizontal = ("vertical" != get(component, "orientation")); + int divider = getInteger(component, "divider", -1); + paintRect(g, horizontal ? divider : 0, horizontal ? 0 : divider, + horizontal ? 5 : bounds.width, horizontal ? bounds.height : 5, + c_border, c_bg, false, false, false, false); + g.setColor(enabled ? (focus ? c_focus : c_border) : c_disable); + int xy = horizontal ? bounds.height : bounds.width; + int xy1 = Math.max(0, xy / 2 - 12); + int xy2 = Math.min(xy / 2 + 12, xy - 1); + for (int i = divider + 1; i < divider + 4; i += 2) { + if (horizontal) { g.drawLine(i, xy1, i, xy2); } + else { g.drawLine(xy1, i, xy2, i); } + } + Object comp1 = get(component, "component"); + if (comp1 != null) { + paint(g, clipx, clipy, clipwidth, clipheight, comp1, enabled); + Object comp2 = get(comp1, ":next"); + if (comp2 != null) { + paint(g, clipx, clipy, clipwidth, clipheight, comp2, enabled); + } + } + } + else if (("list" == classname) || + ("table" == classname) || ("tree" == classname)) { + Rectangle view = getRectangle(component, ":view"); + Rectangle viewport = getRectangle(component, ":port"); + int[] columnwidths = null; + int lx = clipx - viewport.x - 1; + int xfrom = view.x + Math.max(0, lx); + int xto = view.x + Math.min(viewport.width - 2, lx + clipwidth); + if ("table" == classname) { + columnwidths = new int[getItemCountImpl(component, "column")]; + int i = 0; int x = 0; boolean drawheader = (clipy < viewport.y); + if (drawheader) { g.setClip(viewport.x, 0, viewport.width, viewport.y); } + for (Object column = get(component, "column"); + column != null; column = get(column, ":next")) { + boolean lastcolumn = (i == columnwidths.length - 1); + int width = getInteger(column, "width", 80); + if (lastcolumn) { width = Math.max(width, viewport.width - x); } + columnwidths[i] = width; + if (drawheader && (xfrom < x + width) && (xto > x)) { + paintRect(g, x - view.x, 0, width, viewport.y, + enabled ? c_border : c_disable, enabled ? c_ctrl : c_bg, + true, true, false, lastcolumn); + paintContent(column, g, clipx, clipy, clipwidth, clipheight, + x + 2 - view.x, 1, width - 2, + viewport.y - 2, enabled ? c_text : c_disable, "left", false); + } + i++; x += width; + } + if (drawheader) { g.setClip(clipx, clipy, clipwidth, clipheight); } + } + paintRect(g, viewport.x, viewport.y, viewport.width, viewport.height, + enabled ? c_border : c_disable, c_textbg, true, true, true, true); + if (paintScrollPane(g, clipx, clipy, clipwidth, clipheight, bounds, + view, viewport, enabled, inside, pressed)) { + Object lead = get(component, "lead"); + int ly = clipy - viewport.y - 1; + int yfrom = view.y + Math.max(0, ly); + int yto = view.y + Math.min(viewport.height - 2, ly + clipheight); + for (Object item = get(component, ("list" == classname) ? "item" : + (("table" == classname) ? "row" : "node")); item != null;) { + Rectangle r = getRectangle(item, "bounds"); + if (lead == null) { + set(component, "lead", lead = item); // draw first item focused when lead is null + } + if (yto <= r.y) { break; } // the clip bounds are above + + Object next = ("tree" == classname) ? get(item, "node") : null; + boolean expanded = (next != null) && + getBoolean(item, "expanded", true); + if (yfrom < r.y + r.height) { // the clip rectangle is not bellow the current item + boolean selected = getBoolean(item, "selected", false); + paintRect(g, 0, r.y, view.width, r.height, + c_bg, selected ? c_select : c_textbg, false, false, true, false); + if (focus && (lead == item)) { + g.setColor(c_focus); + g.drawRect(0, r.y, view.width - 1, r.height - 2); + } + if ("table" == classname) { + int x = 0; int i = 0; + for (Object cell = get(item, "cell"); + cell != null; cell = get(cell, ":next")) { + if (xto <= x) { break; } + int iwidth = (i < columnwidths.length) ? columnwidths[i] : 80; + if (xfrom < x + iwidth) { + boolean cellenabled = enabled && getBoolean(cell, "enabled", true); + paintContent(cell, g, xfrom, yfrom, xto - xfrom, yto - yfrom, + r.x + x + 1, r.y + 1, iwidth - 2, r.height - 3, + cellenabled ? c_text : c_disable, "left", false); + } + x += iwidth; i++; + } + } else { + boolean itemenabled = enabled && getBoolean(item, "enabled", true); + paintContent(item, g, xfrom, yfrom, xto - xfrom, yto - yfrom, + r.x + 1, r.y + 1, view.width - r.x - 2, + r.height - 3, itemenabled ? c_text : c_disable, "left", false); + + if (next != null) { + int x = r.x - block / 2; + int y = r.y + (r.height - 1) / 2; + //g.drawRect(x - 4, y - 4, 8, 8); + paintRect(g, x - 4, y - 4, 9, 9, itemenabled ? c_border : c_disable, + itemenabled ? c_ctrl : c_bg, true, true, true, true); + g.setColor(itemenabled ? c_text : c_disable); + g.drawLine(x - 2, y, x + 2, y); + if (!expanded) { + g.drawLine(x, y - 2, x, y + 2); + } + } + } + } + if ("tree" == classname) { + if ((next == null) || !expanded) { + while ((item != component) && ((next = get(item, ":next")) == null)) { + item = getParent(item); + } + } + item = next; + } else { + item = get(item, ":next"); + } + } + /*if (columnwidths != null) { + g.setColor(c_bg); + for (int i = 0, cx = -1; i < columnwidths.length - 1; i++) { + cx += columnwidths[i]; + g.drawLine(cx, 0, cx, view.height); + } + }*/ + resetScrollPane(g, clipx, clipy, clipwidth, clipheight, view, viewport); + } + } + else if ("separator" == classname) { + g.setColor(enabled ? c_border : c_disable); + g.fillRect(0, 0, bounds.width, bounds.height); + } + else if ("menubar" == classname) { + Object selected = get(component, "selected"); + int lastx = 0; + for (Object menu = get(component, "menu"); + menu != null; menu = get(menu, ":next")) { + Rectangle mb = getRectangle(menu, "bounds"); + if (clipx + clipwidth <= mb.x) { break; } + if (clipx >= mb.x + mb.width) { continue; } + boolean armed = (selected == menu); + boolean hoover = (selected == null) && (insidepart == menu); + paintRect(g, mb.x, 0, mb.width, bounds.height, enabled ? c_border : c_disable, + enabled ? (armed ? c_select : (hoover ? c_hover : c_ctrl)) : c_bg, + armed, armed, true, armed); + paintContent(menu, g, clipx, clipy, clipwidth, clipheight, + mb.x + 4, 1, mb.width, bounds.height, + (enabled && getBoolean(menu, "enabled", true)) ? c_text : c_disable, + "left", true); + lastx = mb.x + mb.width; + } + paintRect(g, lastx, 0, bounds.width - lastx, bounds.height, + enabled ? c_border : c_disable, enabled ? c_ctrl : c_bg, + false, false, true, false); + } + else if ("popupmenu" == classname) { + paintRect(g, 0, 0, bounds.width, bounds.height, + c_border, c_bg, true, true, true, true); + Object selected = get(component, "selected"); + for (Object menu = get(get(component, "menu"), "menu"); + menu != null; menu = get(menu, ":next")) { + Rectangle r = getRectangle(menu, "bounds"); + if (clipy + clipheight <= r.y) { break; } + if (clipy >= r.y + r.height) { continue; } + String itemclass = getClass(menu); + if (itemclass == "separator") { + g.setColor(c_border); + g.fillRect(r.x, r.y, bounds.width - 2, r.height); + } else { + boolean armed = (selected == menu); + boolean menuenabled = getBoolean(menu, "enabled", true); + paintRect(g, r.x, r.y, bounds.width - 2, r.height, c_border, + armed ? c_select : c_bg, false, false, false, false); + int tx = r.x; + if (itemclass == "checkboxmenuitem") { + tx += block + 3; + boolean checked = getBoolean(menu, "selected", false); + String group = getString(menu, "group", null); + g.translate(r.x + 4, r.y + 2); + g.setColor(menuenabled ? c_border : c_disable); + if (group == null) { + g.drawRect(1, 1, block - 3, block - 3); + } else { + g.drawOval(1, 1, block - 3, block - 3); //java + } + if (checked) { + g.setColor(menuenabled ? c_text : c_disable); + if (group == null) { + g.fillRect(3, block - 9, 2, 6); + g.drawLine(3, block - 4, block - 4, 3); + g.drawLine(4, block - 4, block - 4, 4); + } else { + g.fillOval(5, 5, block - 10, block - 10); //java + g.drawOval(4, 4, block - 9, block - 9); //java + } + } + g.translate(-r.x - 4, -r.y - 2); + } + paintContent(menu, g, clipx, clipy, clipwidth, clipheight, + tx + 4, r.y + 2, bounds.width - 10, + r.height - 4, menuenabled ? c_text : c_disable, "left", true); + if (itemclass == "menu") { + paintArrow(g, r.x + bounds.width - block, r.y, block, r.height, 'E'); + } + } + } + } + //java> + else if ("bean" == classname) { + g.clipRect(0, 0, bounds.width, bounds.height); + ((Component) get(component, "bean")).paint(g); + g.setClip(clipx, clipy, clipwidth, clipheight); + } + //translate(-bounds.x, -bounds.y); + clipx += bounds.x; clipy += bounds.y; + } + + /** + * + */ + private void paintReverse(Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, + Object component, boolean enabled) { + if (component != null) { + Rectangle bounds = getRectangle(component, "bounds"); + if ((clipx < bounds.x) || + (clipx + clipwidth > bounds.x + bounds.width) || + (clipy < bounds.y) || + (clipy + clipheight > bounds.y + bounds.height)) { + paintReverse(g, clipx, clipy, clipwidth, clipheight, + get(component, ":next"), enabled); + } + paint(g, clipx, clipy, clipwidth, clipheight, component, enabled); + } + } + + /** + * + */ + private void paintField(Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, Object component, + int width, int height, boolean inside, boolean pressed, + boolean focus, boolean enabled, boolean hidden, int left) { + boolean editable = getBoolean(component, "editable", true); + paintRect(g, 0, 0, width, height, enabled ? c_border : c_disable, + editable ? c_textbg : c_bg, true, true, true, true); + g.clipRect(1 + left, 1, width - left - 2, height - 2); + + String text = getString(component, "text", ""); + int offset = getInteger(component, "offset", 0); + FontMetrics fm = g.getFontMetrics(); //java + + int caret = 0; + if (focus) { + int start = getInteger(component, "start", 0); + int end = getInteger(component, "end", 0); + caret = hidden ? (fm.charWidth('*') * end) : + fm.stringWidth(text.substring(0, end)); //java + //midp font.substringWidth(text, 0, end); + if (start != end) { + int is = hidden ? (fm.charWidth('*') * start) : + fm.stringWidth(text.substring(0, start)); //java + //midp font.substringWidth(text, 0, start); + g.setColor(c_select); + g.fillRect(2 + left - offset + Math.min(is, caret), 1, + Math.abs(caret - is), height - 2); + } + } + + if (focus) { + g.setColor(c_focus); + g.fillRect(1 + left - offset + caret, 1, 1, height - 2); + } + + g.setColor(enabled ? c_text : c_disable); + int fx = 2 + left - offset; + int fy = (height + fm.getAscent() - fm.getDescent()) / 2; //java + //midp int fy = (height - font.getHeight()) / 2; + if (hidden) { + int fh = fm.charWidth('*'); + for (int i = text.length(); i > 0; i--) { + g.drawString("*", fx, fy); //java + //midp g.drawChar('*', fx, fy, Graphics.LEFT | Graphics.TOP); + fx += fh; + } + } else { + g.drawString(text, fx, fy); //java + //midp g.drawString(text, fx, fy, Graphics.LEFT | Graphics.TOP); + } + g.setClip(clipx, clipy, clipwidth, clipheight); + } + + /** + * + */ + private boolean paintScrollPane(Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, Rectangle bounds, + Rectangle view, Rectangle viewport, + boolean enabled, boolean inside, boolean pressed) { + if ((viewport.y + viewport.height < bounds.height) && + (clipy + clipheight > viewport.y + viewport.height)) { // need horizontal + int x = viewport.x; + int y = viewport.y + viewport.height; + int height = bounds.height - y; + int button = Math.min(block, viewport.width / 2); + int track = viewport.width - (2 * button); //max 10 + int knob = Math.min(track, Math.max(track * (viewport.width - 2) / view.width, 6)); + int decrease = view.x * (track - knob) / + (view.width - viewport.width + 2); + int increase = track - decrease - knob; + paintArrow(g, x, y, button, height, + 'W', enabled, inside, pressed, "left", false, true, true, false); + paintRect(g, x + button, y, decrease, height, + enabled ? c_border : c_disable, c_bg, false, true, true, false); + paintRect(g, x + button + decrease, y, knob, height, + enabled ? c_border : c_disable, enabled ? c_ctrl : c_bg, false, true, true, true); + int n = Math.min(5, (knob - 4) / 3); + g.setColor(enabled ? c_border : c_disable); + int cx = (x + button + decrease) + (knob + 2 - n * 3) / 2; + for (int i = 0; i < n; i++ ) { + g.drawLine(cx + i * 3, y + 2, cx + i * 3, y + height - 4); + } + paintRect(g, x + button + decrease + knob, y, increase, height, + enabled ? c_border : c_disable, c_bg, false, false, true, true); + paintArrow(g, x + button + track, y, button, height, + 'E', enabled, inside, pressed, "right", false, false, true, true); + } + if ((viewport.x + viewport.width < bounds.width) && + (clipx + clipwidth > viewport.x + viewport.width)) { // need vertical + int x = viewport.x + viewport.width; + int y = viewport.y; + int width = bounds.width - x; + //if (y > 0) { + // paintRect(g, x - 1, 0, width + 1, y, + // enabled ? c_border : c_disable, c_bg, false, true, false, false); + //} + int track = viewport.height - (2 * block); + int knob = track * (viewport.height - 2) / view.height; + int decrease = view.y * (track - knob) / + (view.height - viewport.height + 2); + int increase = track - decrease - knob; + paintArrow(g, x, y, width, block, + 'N', enabled, inside, pressed, "up", true, false, false, true); + paintRect(g, x, y + block, width, decrease, + enabled ? c_border : c_disable, c_bg, true, false, false, true); + paintRect(g, x, y + block + decrease, width, knob, + enabled ? c_border : c_disable, enabled ? c_ctrl : c_bg, true, false, true, true); + int n = Math.min(5, (knob - 4) / 3); + g.setColor(enabled ? c_border : c_disable); + int cy = (y + block + decrease) + (knob + 2 - n * 3) / 2; + for (int i = 0; i < n; i++ ) { + g.drawLine(x + 2, cy + i * 3, x + width - 4, cy + i * 3); + } + paintRect(g, x, y + block + decrease + knob, width, increase, + enabled ? c_border : c_disable, c_bg, false, false, true, true); + paintArrow(g, x, y + block + track, width, block, + 'S', enabled, inside, pressed, "down", false, false, true, true); + } + if ((clipx + clipwidth > viewport.x) && (clipy + clipheight > viewport.y) && + (clipx < viewport.x + viewport.width) && (clipy < viewport.y + viewport.height)) { + g.clipRect(viewport.x + 1, viewport.y + 1, viewport.width - 2, viewport.height - 2); + g.translate(viewport.x + 1 - view.x, viewport.y + 1 - view.y); + return true; + } + return false; + } + + /** + * + */ + private void resetScrollPane(Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, + Rectangle view, Rectangle viewport) { + g.translate(view.x - viewport.x - 1, view.y - viewport.y - 1); + g.setClip(clipx, clipy, clipwidth, clipheight); + } + + /** + * + */ + private void paintRect(Graphics g, int x, int y, int width, int height, + Color border, Color bg, + boolean top, boolean left, boolean bottom, boolean right) { + if ((width <= 0) || (height <= 0)) return; + g.setColor(border); + if (top) { + g.drawLine(x + width - 1, y, x, y); + y++; height--; if (height <= 0) return; + } + if (left) { + g.drawLine(x, y, x, y + height - 1); + x++; width--; if (width <= 0) return; + } + if (bottom) { + g.drawLine(x, y + height - 1, x + width - 1, y + height - 1); + height--; if (height <= 0) return; + } + if (right) { + g.drawLine(x + width - 1, y + height - 1, x + width - 1, y); + width--; if (width <= 0) return; + } + + //java> + if (bg == c_ctrl) { + if (height > block) { + g.setColor(c_bg); + g.fillRect(x, y, width, height - block); + } + for (int i = 0; i < width; i += block) { + g.drawImage(gradient, x + i, (height > block) ? (y + height - block) : y, + x + Math.min(i + block, width), y + height, + 0, 0, Math.min(block, width - i), Math.min(block, height), null); + } + /*if (width > block) { + g.setColor(c_bg); + g.fillRect(x, y, width - block, height); + } + for (int i = 0; i < height; i += block) { + g.drawImage(gradient, (width > block) ? (x + width - block) : x, y + i, + x + width, y + Math.min(i + block, height), + 0, 0, Math.min(block, width), Math.min(block, height - i), null); + }*/ + } + else { + g.setColor(bg); + g.fillRect(x, y, width, height); + } + //Graphics g, int x, int y, int width, int height, + char dir, boolean enabled, boolean inside, boolean pressed, String part, + boolean top, boolean left, boolean bottom, boolean right) { + inside = inside && (insidepart == part); + pressed = pressed && (pressedpart == part); + paintRect(g, x, y, width, height, enabled ? c_border : c_disable, + enabled ? ((inside != pressed) ? c_hover : + (pressed ? c_press : c_ctrl)) : c_bg, + top, left, bottom, right); + g.setColor(enabled ? c_text : c_disable); + paintArrow(g, x, y, width, height, dir); + } + + /** + * + */ + private void paintArrow(Graphics g, + int x, int y, int width, int height, char dir) { + int cx = x + width / 2 - 2; + int cy = y + height / 2 - 2; + for (int i = 0; i < 4; i++) { + if (dir == 'N') { // north + g.drawLine(cx + 1 - i, cy + i, cx + 1/*2*/ + i, cy + i); + } + else if (dir == 'W') { // west + g.drawLine(cx + i, cy + 1 - i, cx + i, cy + 1/*2*/ + i); + } + else if (dir == 'S') { // south + g.drawLine(cx + 1 - i, cy + 4 - i, cx + 1/*2*/ + i, cy + 4 - i); + } + else { // east + g.drawLine(cx + 4 - i, cy + 1 - i, cx + 4 - i, cy + 1/*2*/ + i); + } + } + } + + /** + * + */ + private void paintContent(Object component, Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, + int x, int y, int width, int height, Color fg, String defaultalignment, + boolean checkmnemonic) { + String text = getString(component, "text", null); + Image icon = getIcon(component, "icon", null); + if ((text == null) && (icon == null)) { return; } + String alignment = getString(component, "alignment", defaultalignment); + + FontMetrics fm = null; //java + int tw = 0, th = 0; + int ta = 0; //java + if (text != null) { + fm = g.getFontMetrics(); //java + tw = fm.stringWidth(text); + ta = fm.getAscent(); //java + th = fm.getDescent() + ta; //java + //midp th = font.getHeight(); + g.setColor(fg); + } + int iw = 0, ih = 0; + if (icon != null) { + iw = icon.getWidth(this); + ih = icon.getHeight(this); //java + } + + boolean clipped = (tw + iw > width) || (th > height) || (ih > height); + int cx = x; + if ("center" == alignment) { cx += (width - tw - iw) / 2; } + else if ("right" == alignment) { cx += width - tw - iw; } + + if (clipped) { g.clipRect(x, y, width, height); } + if (icon != null) { + g.drawImage(icon, cx, y + (height - ih) / 2, this); //java + //midp g.drawImage(icon, cx, y + height / 2, Graphics.LEFT | Graphics.VCENTER); + cx += iw; + } + if (text != null) { + int ty = y + (height - th) / 2 + ta; //java + g.drawString(text, cx, ty); //java + //midp g.drawString(text, cx, y + (height - th) / 2, Graphics.LEFT | Graphics.TOP); + if (checkmnemonic) { + int mnemonic = getInteger(component, "mnemonic", -1); + if ((mnemonic != -1) && (mnemonic < text.length())) { + int mx = cx + fm.stringWidth(text.substring(0, mnemonic)); //java + //midp int mx = cx + font.substringWidth(text, 0, mnemonic); + //midp int ty = (height + th) / 2; + g.drawLine(mx, ty + 1, mx + fm.charWidth(text.charAt(mnemonic)), ty + 1); + } + } + } + if (clipped) { g.setClip(clipx, clipy, clipwidth, clipheight); } + } + //midp private void setTimer(long delay) {} + //java> + + /** + * + */ + public synchronized void run() { + while (timer == Thread.currentThread()) { + try { + if (watch == 0) { + wait(0); + } else { + long current = System.currentTimeMillis(); + if (watch > current) { + wait(watch - current); + } else { + watch = 0; + if ((watchdelay == 300L) || (watchdelay == 60L)) { + if (processScroll(mousepressed, pressedpart)) { setTimer(60L); } + } else if ((watchdelay == 375L) || (watchdelay == 75L)) { + if (processSpin(mousepressed, pressedpart)) { setTimer(75L); } + } else if (watchdelay == 750L) { + //System.out.println("> tip: " + getClass(mouseinside) + " : " + ((insidepart instanceof Object[]) ? getClass(insidepart) : insidepart)); + showTip(); + } + } + } + } catch (InterruptedException ie) {} //ie.printStackTrace(); + } + } + + /** + * + */ + private void setTimer(long delay) { + watchdelay = delay; + if (delay == 0) { + watch = 0; + } else { + long prev = watch; + watch = System.currentTimeMillis() + delay; + if (timer == null) { + timer = new Thread(this); + timer.setPriority(Thread.MIN_PRIORITY); + timer.setDaemon(true); + timer.start(); + } + if ((prev == 0) || (watch < prev)) { + synchronized (this) { notify(); } //try {}catch (IllegalMonitorStateException imse) {} + } + } + } + + /** + * + */ + public boolean isFocusTraversable() { + return true; + } + + // 0) { + processKeyPress((popupowner != null) ? popupowner : focusowner, + false, false, 1, keyCode, 0); + } + else { + int keychar = 0, key = 0; + switch (getGameAction(keyCode)) { + case UP: key = KeyEvent.VK_UP; break; + case LEFT: key = KeyEvent.VK_LEFT; break; + case DOWN: key = KeyEvent.VK_DOWN; break; + case RIGHT: key = KeyEvent.VK_RIGHT; break; + case FIRE: key = KeyEvent.VK_ENTER; keychar = KeyEvent.VK_SPACE; break; + case GAME_A: key = KeyEvent.VK_ESCAPE; break; + } + if (key != 0) { + processKeyPress((popupowner != null) ? popupowner : focusowner, + false, false, 1, keychar, key); + } + //if (keyCode == getKeyCode(LEFT)) { + } + } + } + + protected void keyRepeated(int keyCode) { + keyPressed(keyCode); + } + + private static final Command nextcommand = new Command("Next", Command.SCREEN, 0); + //private static final Command prevcommand = new Command("Previous", Command.SCREEN, 0); + { + addCommand(nextcommand); + //addCommand(prevcommand); + setCommandListener(this); + } + + public void commandAction(Command command, Displayable displayable) { + if (command == nextcommand) { + setNextFocusable(focusowner, false); + repaint(focusowner); + closeup(); + } + //else if (command == prevcommand) { + //setPreviousFocusable(focusowner, null, true, true, false); + //repaint(focusowner); + //closeup(); + //} + } + midp*/ + //java> + + /** + * + */ + protected void processEvent(AWTEvent e) { + int id = e.getID(); + if ((id >= MouseEvent.MOUSE_FIRST) && (id <= MouseEvent.MOUSE_LAST)) { + MouseEvent me = (MouseEvent) e; + int x = me.getX(); + int y = me.getY(); + int clickcount = me.getClickCount(); + boolean shiftdown = me.isShiftDown(); + boolean controldown = me.isControlDown(); + boolean popuptrigger = me.isPopupTrigger(); + if (id == MouseEvent.MOUSE_ENTERED) { + if (mousepressed == null) { + findComponent(content, x, y); + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); + } + } + else if (id == MouseEvent.MOUSE_MOVED) { + Object previnside = mouseinside; + Object prevpart = insidepart; + findComponent(content, x, y); + if ((previnside == mouseinside) && (prevpart == insidepart)) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_MOVED, mouseinside, insidepart); + } + else { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_EXITED, previnside, prevpart); + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); + } + } + else if (id == MouseEvent.MOUSE_EXITED) { + if (mousepressed == null) { + Object mouseexit = mouseinside; + Object exitpart = insidepart; + mouseinside = insidepart = null; + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_EXITED, mouseexit, exitpart); + } + } + else if (id == MouseEvent.MOUSE_PRESSED) { + if (popupowner != null) { + String classname = getClass(mouseinside); + if ((popupowner != mouseinside) && + (classname != "popupmenu") && (classname != "combolist")) { + closeup(); + } + } + mousepressed = mouseinside; + pressedpart = insidepart; + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_PRESSED, mousepressed, pressedpart); + } + else if (id == MouseEvent.MOUSE_DRAGGED) { + Object previnside = mouseinside; + Object prevpart = insidepart; + findComponent(content, x, y); + boolean same = (previnside == mouseinside) && (prevpart == insidepart); + boolean isin = (mousepressed == mouseinside) && (pressedpart == insidepart); + boolean wasin = (mousepressed == previnside) && (pressedpart == prevpart); + + if (wasin && !isin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_EXITED, mousepressed, pressedpart); + } + else if (!same && (popupowner != null) && !wasin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + DRAG_EXITED, previnside, prevpart); + } + if (isin && !wasin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_ENTERED, mousepressed, pressedpart); + } + else if (!same && (popupowner != null) && !isin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + DRAG_ENTERED, mouseinside, insidepart); + } + if (isin == wasin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_DRAGGED, mousepressed, pressedpart); + } + } + else if (id == MouseEvent.MOUSE_RELEASED) { + Object mouserelease = mousepressed; + Object releasepart = pressedpart; + mousepressed = pressedpart = null; + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_RELEASED, mouserelease, releasepart); + if ((mouseinside != null) && + ((mouserelease != mouseinside) || (releasepart != insidepart))) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); + } + } + } + else if (id == MOUSE_WHEEL) { + Rectangle port = getRectangle(mouseinside, ":port"); + if (port != null) { // is scrollable + Rectangle bounds = getRectangle(mouseinside, "bounds"); + try { // mouse wheel is supported since 1.4 thus it use reflection + if (wheelrotation == null) { + wheelrotation = e.getClass().getMethod("getWheelRotation", null); + } + int rotation = ((Integer) wheelrotation.invoke(e, null)).intValue(); + + if (port.x + port.width < bounds.width) { // has vertical scrollbar + processScroll(mouseinside, (rotation > 0) ? "down" : "up"); + } + else if (port.y + port.height < bounds.height) { // has horizontal scrollbar + processScroll(mouseinside, (rotation > 0) ? "right" : "left"); + } + } catch (Exception exc) { /* never */ } + } + } + else if ((id == KeyEvent.KEY_PRESSED) || (id == KeyEvent.KEY_TYPED)) { + if (focusinside && ((popupowner != null) || (focusowner != null))) { + hideTip(); + KeyEvent ke = (KeyEvent) e; + int keychar = ke.getKeyChar(); + boolean control = (keychar <= 0x1f) || + ((keychar >= 0x7f) && (keychar <= 0x9f)) || + (keychar >= 0xffff) || ke.isControlDown(); + if (control == (id == KeyEvent.KEY_PRESSED)) { + int keycode = control ? ke.getKeyCode() : 0; + if (!processKeyPress((popupowner != null) ? popupowner : focusowner, + ke.isShiftDown(), ke.isControlDown(), ke.getModifiers(), + control ? 0 : keychar, keycode)) { + if ((keycode == KeyEvent.VK_TAB) || + ((keycode == KeyEvent.VK_F6) && (ke.isAltDown() || ke.isControlDown()))) { + boolean outgo = (keycode == KeyEvent.VK_F6); + if (!ke.isShiftDown() ? setNextFocusable(focusowner, outgo) : + setPreviousFocusable(focusowner, outgo)) { + ke.consume(); + } else if (MOUSE_WHEEL != 0) { // 1.4 + if (!ke.isShiftDown()) { + transferFocus(); + } + else { try { + getClass().getMethod("transferFocusBackward", null). invoke(this, null); + } catch (Exception exc) { /* never */ } } + } + repaint(focusowner); + closeup(); + } + else if (keycode == KeyEvent.VK_F8) { + for (Object splitpane = focusowner; + splitpane != null; splitpane = getParent(splitpane)) { + if (getClass(splitpane) == "splitpane") { + setFocus(splitpane); repaint(splitpane); break; //middle + } + } + } + } + else ke.consume(); + /*else if (keycode == KeyEvent.VK_F10) { + Object menubar = null; // find("class", "menubar") + if ((menubar != null) && (get(menubar, "selected") == null)) { + set(menubar, "selected", getMenu(menubar, null, true, false)); + Object popup = popup(menubar, "menubar"); + set(popup, "selected", getMenu(popup, null, true, true)); + repaint(menubar); // , selected + } + }*/ + } + } + } + /*else if (id == KeyEvent.KEY_RELEASED) { + if (focusinside && (focusowner != null)) { + KeyEvent ke = (KeyEvent) e; + //pressedkey = 0; + processKeyRelease(focusowner, ke, ke.getKeyCode()); + } + }*/ + else if (id == FocusEvent.FOCUS_LOST) { + focusinside = false; + if (focusowner != null) { repaint(focusowner); } + closeup(); + } + else if (id == FocusEvent.FOCUS_GAINED) { + focusinside = true; + if (focusowner == null) { setFocus(content); } + else { repaint(focusowner); } + } + else if ((id == ComponentEvent.COMPONENT_RESIZED) || + (id == ComponentEvent.COMPONENT_SHOWN)) { + Dimension d = getSize(); + //System.out.println(id + ": " + d.width + ", " + d.height); + setRectangle(content, "bounds", 0, 0, d.width, d.height); + validate(content); + closeup(); + if (!focusinside) { requestFocus(); } + } + } + + /** + * + */ + /*private boolean processKeyPress(Object component, + KeyEvent e, int keycode, Object invoker) { + if (processKeyPress(component, e, keycode)) { return true; } + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if ((comp != invoker) && processKeyPress(comp, e, keycode, null)) { + return true; + } + } + if ((invoker != null) && (component != content)) { + Object parent = getParent(component); + if (parent != null) { + return processKeyPress(parent, e, keycode, component); + } + } + return false; + }*/ + //KeyEvent.VK_SPACE || + ((keycode == KeyEvent.VK_ENTER) && + (getString(component, "type", null) == "default")) || + ((keycode == KeyEvent.VK_ESCAPE) && //... + (getString(component, "type", null) == "cancel"))) { + //pressedkey = keychar; + invoke(component, "action"); + repaint(component); + return true; + } + } + else if ("checkbox" == classname) { + if (keychar == KeyEvent.VK_SPACE) { + changeCheck(component, true); + repaint(component); + return true; + } + } + else if ("combobox" == classname) { + Object combolist = get(component, "combolist"); + if (combolist == null) { + if (getBoolean(component, "editable", true) && + processField(component, shiftdown, controldown, modifiers, + keychar, keycode, false, false)) { + setInteger(component, "selected", -1, -1); + return true; + } + if ((keychar == KeyEvent.VK_SPACE) || (keycode == KeyEvent.VK_DOWN)) { + combolist = popup(component, classname); + int selected = getInteger(component, "selected", -1); + set(combolist, "inside", (selected != -1) ? + getItemImpl(component, "choice", selected) : + get(component, "choice")); //scroll to it! + } + else return false; + } else { + if ((keycode == KeyEvent.VK_UP) || + (keycode == KeyEvent.VK_DOWN) || (keycode == KeyEvent.VK_PAGE_UP) || + (keycode == KeyEvent.VK_PAGE_DOWN) || + (keycode == KeyEvent.VK_HOME) || (keycode == KeyEvent.VK_END)) { + Object selected = get(combolist, "inside"); + Object next = getListItem(component, combolist, + keycode, selected, "choice", null); + if (next != null) { + set(combolist, "inside", next); + Rectangle r = getRectangle(next, "bounds"); + scrollToVisible(combolist, r.x, r.y, 0, r.height); + if (selected != null) { repaint(combolist, "combolist", selected); } + repaint(combolist, "combolist", next); + } + } + else if ((keycode == KeyEvent.VK_ENTER) || (keychar == KeyEvent.VK_SPACE)) { + closeup(component, combolist, get(combolist, "inside")); //Alt+Up + } + else if (keycode == KeyEvent.VK_ESCAPE) { + closeup(component, combolist, null); + } + else return processField(component, shiftdown, controldown, modifiers, + keychar, keycode, false, false); + } + return true; + } + else if (("textfield" == classname) || ("passwordfield" == classname)) { + return processField(component, shiftdown, controldown, modifiers, + keychar, keycode, false, ("passwordfield" == classname)); + } + else if ("textarea" == classname) { + String text = getString(component, "text", ""); + int start = getInteger(component, "start", 0); + int end = getInteger(component, "end", 0); + + int istart = start; + int iend = end; + String insert = null; + if ((keycode == KeyEvent.VK_HOME) && !controldown) { + while ((iend > 0) && (text.charAt(iend - 1) != '\n')) { iend--; } + if (!shiftdown) { istart = iend; } + } + else if ((keycode == KeyEvent.VK_END) && !controldown) { + iend = text.indexOf('\n', end); + if (iend == -1) { iend = text.length(); } + if (!shiftdown) { istart = iend; } + } + else if ((keycode == KeyEvent.VK_UP) || + (keycode == KeyEvent.VK_PAGE_UP)) { + int prev = end; + while ((prev > 0) && (text.charAt(prev - 1) != '\n')) { prev--; } + if (prev != 0) { + int dx = end - prev; + int lines = (keycode == KeyEvent.VK_PAGE_UP) ? + (getRectangle(component, ":port").height / + getFontMetrics(getFont()).getHeight()) : 1; + int first = prev; + do { + prev = first; first--; lines--; + while ((first > 0) && (text.charAt(first - 1) != '\n')) { first--; } + } while ((first > 0) && (lines > 0)); + iend = Math.min(first + dx, prev - 1); + if (!shiftdown) { istart = iend; } + } + } + else if ((keycode == KeyEvent.VK_DOWN) || + (keycode == KeyEvent.VK_PAGE_DOWN)) { + int next = text.indexOf('\n', end); + if (next != -1) { + int prev = end; + while ((prev > 0) && (text.charAt(prev - 1) != '\n')) { prev--; } + if (keycode == KeyEvent.VK_PAGE_DOWN) { + int lines = getRectangle(component, ":port").height / + getFontMetrics(getFont()).getHeight(); + for (int more = 0; (lines > 1) && + ((more = text.indexOf('\n', next + 1)) != -1); next = more) { + lines--; + } + } + int last = text.indexOf('\n', next + 1); + iend = Math.min(next + 1 + end - prev, + (last == -1) ? (text.length() + 1) : last); + if (!shiftdown) { istart = iend; } + } + } + return changeField(component, text, insert, istart, iend, start, end) ? + true : processField(component, shiftdown, controldown, modifiers, + keychar, keycode, true, false); + } + else if ("tabbedpane" == classname) { + if ((keycode == KeyEvent.VK_RIGHT) || (keycode == KeyEvent.VK_DOWN) || + (keycode == KeyEvent.VK_LEFT) || (keycode == KeyEvent.VK_UP)) { + int selected = getInteger(component, "selected", 0); + boolean increase = (keycode == KeyEvent.VK_RIGHT) || (keycode == KeyEvent.VK_DOWN); + int newvalue = selected; + int n = increase ? getItemCountImpl(component, "tab") : 0; + int d = (increase ? 1 : -1); + for (int i = selected + d; increase ? (i < n) : (i >= 0); i += d) { + if (getBoolean(getItemImpl(component, "tab", i), "enabled", true)) { + newvalue = i; break; + } + } + if (newvalue != selected) { + setInteger(component, "selected", newvalue, 0); + repaint(component); + invoke(component, "action"); + } + } + } + else if ("spinbox" == classname) { + if ((keycode == KeyEvent.VK_UP) || (keycode == KeyEvent.VK_DOWN)) { + processSpin(component, (keycode == KeyEvent.VK_UP)? "up" : "down"); + return true; + } + return processField(component, shiftdown, controldown, modifiers, + keychar, keycode, false, false); + } + else if ("slider" == classname) { + int value = getInteger(component, "value", 0); + int d = 0; + if ((keycode == KeyEvent.VK_HOME) || (keycode == KeyEvent.VK_LEFT) || + (keycode == KeyEvent.VK_UP) || (keycode == KeyEvent.VK_PAGE_UP)) { + d = getInteger(component, "minimum", 0) - value; + if ((keycode == KeyEvent.VK_LEFT) || (keycode == KeyEvent.VK_UP)) { + d = Math.max(d, -getInteger(component, "unit", 5)); + } + else if (keycode == KeyEvent.VK_PAGE_UP) { + d = Math.max(d, -getInteger(component, "block", 25)); + } + } + else if ((keycode == KeyEvent.VK_END) || (keycode == KeyEvent.VK_RIGHT) || + (keycode == KeyEvent.VK_DOWN) || (keycode == KeyEvent.VK_PAGE_DOWN)) { + d = getInteger(component, "maximum", 100) - value; + if ((keycode == KeyEvent.VK_RIGHT) || (keycode == KeyEvent.VK_DOWN)) { + d = Math.min(d, getInteger(component, "unit", 5)); + } + else if (keycode == KeyEvent.VK_PAGE_DOWN) { + d = Math.min(d, getInteger(component, "block", 25)); + } + } + if (d != 0) { + setInteger(component, "value", value + d, 0); + repaint(component); + invoke(component, "action"); + } + } + else if ("splitpane" == classname) { + int divider = getInteger(component, "divider", -1); + int d = 0; + if (keycode == KeyEvent.VK_HOME) { + d = -divider; + } + else if ((keycode == KeyEvent.VK_LEFT) || (keycode == KeyEvent.VK_UP)) { + d = Math.max(-10, -divider); + } + else if ((keycode == KeyEvent.VK_END) || + (keycode == KeyEvent.VK_RIGHT) || (keycode == KeyEvent.VK_DOWN)) { + boolean horizontal = ("vertical" != get(component, "orientation")); + Rectangle bounds = getRectangle(component, "bounds"); + int max = (horizontal ? bounds.width : bounds.height) - 5; + d = max - divider; + if (keycode != KeyEvent.VK_END) { + d = Math.min(d, 10); + } + } + if (d != 0) { + setInteger(component, "divider", divider + d, -1); + validate(component); + } + } + else if ("list" == classname) { + return processList(component, shiftdown, controldown, keychar, keycode, "item", null); + } + else if ("table" == classname) { + return processList(component, shiftdown, controldown, keychar, keycode, "row", null); + } + else if ("tree" == classname) { + //? clear childs' selection, select this is its subnode was selected + if (keycode == KeyEvent.VK_LEFT) { + Object lead = get(component, "lead"); + if ((get(lead, "node") != null) && getBoolean(lead, "expanded", true)) { + setBoolean(lead, "expanded", false, true); + selectItem(component, lead, "node", "node"); + validate(component); + invoke(component, "collapse"); //lead + return true; + } + else { + Object parent = getParent(lead); + if (parent != component) { + selectItem(component, parent, "node", "node"); + setLead(component, lead, parent); + return true; + } + } + } + //? for interval mode select its all subnode or deselect all after + else if (keycode == KeyEvent.VK_RIGHT) { + Object lead = get(component, "lead"); + Object node = get(lead, "node"); + if (node != null) { + if (getBoolean(lead, "expanded", true)) { + selectItem(component, node, "node", "node"); + setLead(component, lead, node); + } + else { + setBoolean(lead, "expanded", true, true); + selectItem(component, lead, "node", "node"); + validate(component); + invoke(component, "expand"); //lead + } + return true; + } + } + return processList(component, shiftdown, controldown, keychar, keycode, "node", "node"); + } + else if ("menubar" == classname) { + Object previous = null; Object last = null; + for (Object i = get(component, "popupmenu"); + i != null; i = get(i, "popupmenu")) { + previous = last; last = i; + } + Object selected = get(last, "selected"); + Object hotpopup = ((selected != null) || (previous == null)) ? + last : previous; + if ((selected == null) && (previous != null)) { + selected = get(previous, "selected"); + } + + if ((keycode == KeyEvent.VK_UP) || (keycode == KeyEvent.VK_DOWN)) { + set(hotpopup, "selected", null); + popup(hotpopup, "popupmenu"); + selected = getMenu(hotpopup, + selected, keycode == KeyEvent.VK_DOWN, true); + set(hotpopup, "selected", selected); + repaint(hotpopup); + } + else if (keycode == KeyEvent.VK_LEFT) { + if (previous != null) { + selected = get(previous, "selected"); + set(previous, "selected", null); + popup(previous, "popupmenu"); + set(previous, "selected", selected); + repaint(previous); // , selected + } + else { + selected = getMenu(component, get(component, "selected"), false, false); + set(component, "selected", selected); + Object popup = popup(component, "menubar"); + set(popup, "selected", getMenu(popup, null, true, true)); + repaint(component); // , selected + } + } + else if (keycode == KeyEvent.VK_RIGHT) { + if ((previous != null) && (selected == null)) { + set(last, "selected", get(get(last, "menu"), "menu")); + repaint(last); // , selected + } + else if ((selected != null) && (getClass(selected) == "menu")) { + Object popup = popup(last, "popupmenu"); + set(popup, "selected", get(get(popup, "menu"), "menu")); + } + else { + selected = getMenu(component, get(component, "selected"), true, false); + set(component, "selected", selected); + Object popup = popup(component, "menubar"); + set(popup, "selected", getMenu(popup, null, true, true)); + repaint(component); // , selected + } + } + else if ((keycode == KeyEvent.VK_ENTER) || + (keychar == KeyEvent.VK_SPACE) || (keycode == KeyEvent.VK_ESCAPE)) { + if ((keycode != KeyEvent.VK_ESCAPE) && + getBoolean(selected, "enabled", true)) { + if ((selected != null) && (getClass(selected) == "checkboxmenuitem")) { + changeCheck(selected, false); + } + else invoke(selected, "action"); + } + closeup(component); + } + else return false; + return true; + } + return false; + } + + /** + * + */ + private boolean changeCheck(Object component, boolean box) { + String group = getString(component, "group", null); + if (group != null) { + if (getBoolean(component, "selected", false)) { return false; } + for (Object comp = get(getParent(component), + box ? "component" : "menu"); comp != null; comp = get(comp, ":next")) { + if (comp == component) { + setBoolean(component, "selected", true); + } + else if (group.equals(get(comp, "group")) && + getBoolean(comp, "selected", false)) { + setBoolean(comp, "selected", false); + if (box) { repaint(comp); } //checkbox only + } + } + } + else { + setBoolean(component, "selected", + !getBoolean(component, "selected", false), false); + } + invoke(component, "action"); + return true; + } + + /** + * + */ + private Object getMenu(Object component, Object part, + boolean forward, boolean popup) { + if (forward) { + if (part != null) { part = get(part, ":next"); } + if (part == null) { + part = get(popup ? get(component, "menu") : component, "menu"); + } + } + else { + Object prev = get(popup ? get(component, "menu") : component, "menu"); + for (Object next = get(prev, ":next"); + (next != null) && (next != part); next = get(next, ":next")) { + prev = next; + } + part = prev; + } + return (getClass(part) == "separator") ? + getMenu(component, part, forward, popup) : part; + } + + /** + * + */ + /*private boolean processKeyRelease(Object component, KeyEvent e, int keycode) { + return true; + }*/ + + /** + * + */ + private boolean processField(Object component, + boolean shiftdown, boolean controldown, int modifiers, + int keychar, int keycode, boolean multiline, boolean hidden) { + String text = getString(component, "text", ""); + int start = getInteger(component, "start", 0); + int end = getInteger(component, "end", 0); + boolean editable = getBoolean(component, "editable", true); + + int istart = start; + int iend = end; + String insert = null; + //midp if (editable && (keychar != 0)) { + if (editable && (keychar != 0) && //java + ((modifiers == 0) || (modifiers == InputEvent.SHIFT_MASK))) { //java + insert = String.valueOf((char) keychar); + } + else if (multiline && editable && (keycode == KeyEvent.VK_ENTER)) { + insert = "\n"; + } + else if (editable && (keycode == KeyEvent.VK_BACK_SPACE)) { + insert = ""; + if (start == end) { istart -= 1; } + } + else if (keycode == KeyEvent.VK_END) { + iend = text.length(); + if (!shiftdown) { istart = iend; } + } + else if (keycode == KeyEvent.VK_HOME) { + iend = 0; + if (!shiftdown) { istart = iend; } + } + else if (keycode == KeyEvent.VK_LEFT) { + //java> + if (controldown) { + for (int i = 0; i < 2; i++) { + while ((iend > 0) && ((i != 0) == + Character.isLetterOrDigit(text.charAt(iend - 1)))) { iend--; } + } + } else { + iend -= 1; + } + //KeyEvent.VK_RIGHT) { + //java> + if (controldown) { + for (int i = 0; i < 2; i++) { + while ((iend < text.length()) && ((i == 0) == + Character.isLetterOrDigit(text.charAt(iend)))) { iend++; } + } + } else { + iend += 1; + } + //KeyEvent.VK_DELETE)) { + insert = ""; + if (start == end) { iend += 1; } + } + else if (controldown && + ((keycode == KeyEvent.VK_A) || (keycode == 0xBF))) { + istart = 0; // KeyEvent.VK_SLASH + iend = text.length(); + } + else if (controldown && (keycode == 0xDC)) { + istart = iend = text.length(); // KeyEvent.VK_BACK_SLASH + } + else if ((editable && !hidden && controldown && (keycode == KeyEvent.VK_X)) || + (!hidden && controldown && (keycode == KeyEvent.VK_C))) { + if (start != end) { + clipboard = text.substring( + Math.min(start, end), Math.max(start, end)); + //java> + try { + /* Personal Basis Profile doesn't contain datatransfer package + Toolkit toolkit = getToolkit(); + Object systemclipboard = toolkit.getClass().getMethod("getSystemClipboard", null).invoke(toolkit, null); + Class selectionclass = Class.forName("java.awt.datatransfer." + "StringSelection"); + Object selection = selectionclass.getConstructor(new Class[] { String.class }). + newInstance(new Object[] { clipboard }); + systemclipboard.getClass().getMethod("setContents", new Class[] { + Class.forName("java.awt.datatransfer." + "Transferable"), + Class.forName("java.awt.datatransfer." + "ClipboardOwner") }). + invoke(systemclipboard, new Object[] { selection, null });*/ + getToolkit().getSystemClipboard().setContents( + new StringSelection(clipboard), null); + } catch (Exception exc) {} + //KeyEvent.VK_X) { insert = ""; } + } + } + else if (editable && controldown && (keycode == KeyEvent.VK_V)) { + //java> + try { + /* no datatransfer package in PBP + Toolkit toolkit = getToolkit(); + Object systemclipboard = toolkit.getClass().getMethod("getSystemClipboard", null).invoke(toolkit, null); + Object contents = systemclipboard.getClass().getMethod("getContents", new Class[] { Object.class }). + invoke(systemclipboard, new Object[] { this }); + Class dataflavor = Class.forName("java.awt.datatransfer." + "DataFlavor"); + insert = (String) (contents.getClass().getMethod("getTransferData", new Class[] { dataflavor }). + invoke(contents, new Object[] { dataflavor.getField("stringFlavor").get(null) }));*/ + insert = (String) getToolkit().getSystemClipboard(). + getContents(this).getTransferData(DataFlavor.stringFlavor); + } catch (Exception exc) { + insert = clipboard; + } + // 0x1f) && (ckey < 0x7f)) || + ((ckey > 0x9f) && (ckey < 0xffff)) || + (multiline && (ckey == '\n'))) { + filtered.append(ckey); + } + } + if (filtered.length() != insert.length()) { + insert = filtered.toString(); + } + } + return changeField(component, text, insert, istart, iend, start, end); + } + + /** + * + */ + private boolean changeField(Object component, String text, String insert, + int movestart, int moveend, int start, int end) { + if ((insert == null) && (start == movestart) && (end == moveend)) { + return false; + } + movestart = Math.max(0, Math.min(movestart, text.length())); + moveend = Math.max(0, Math.min(moveend, text.length())); + if (insert != null) { + int min = Math.min(movestart, moveend); + set(component, "text", text.substring(0, min) + insert + + text.substring(Math.max(movestart, moveend))); + movestart = moveend = min + insert.length(); + invoke(component, "action"); + } + if (start != movestart) { setInteger(component, "start", movestart, 0); } + if (end != moveend) { setInteger(component, "end", moveend, 0); } + if ((insert != null) || (start != movestart) || (end != moveend)) { + validate(component); + } + return true; + } + + /** + * + */ + private boolean processList(Object component, boolean shiftdown, boolean controldown, + int keychar, int keycode, String itemname, String leafname) { + if ((keycode == KeyEvent.VK_UP) || + (keycode == KeyEvent.VK_DOWN) || (keycode == KeyEvent.VK_PAGE_UP) || + (keycode == KeyEvent.VK_PAGE_DOWN) || + (keycode == KeyEvent.VK_HOME) || (keycode == KeyEvent.VK_END)) { + Object lead = get(component, "lead"); + Object row = getListItem(component, component, + keycode, lead, itemname, leafname); + if (row != null) { + String selection = getString(component, "selection", "single"); + if (shiftdown && (selection != "single") && (lead != null)) { + extend(component, lead, row, itemname, leafname); + } + else if (!controldown) { + selectItem(component, row, itemname, leafname); + } + setLead(component, lead, row); + Rectangle r = getRectangle(row, "bounds"); + scrollToVisible(component, r.x, r.y, 0, r.height - 1); + return true; + } + } + else if (keychar == KeyEvent.VK_SPACE) { + select(component, get(component, "lead"), + itemname, leafname, shiftdown, controldown); //... + return true; + } + else if (controldown) { + if (((keycode == KeyEvent.VK_A) || (keycode == 0xBF)) && //KeyEvent.VK_SLASH + (getString(component, "selection", "single") != "single")) { + selectAll(component, true, itemname, leafname); + return true; + } + else if (keycode == 0xDC) { //KeyEvent.VK_BACK_SLASH + selectAll(component, false, itemname, leafname); + return true; + } + } + return false; + } + + /** + * + */ + private Object getListItem(Object component, Object scrollpane, + int keycode, Object lead, String itemname, String leafname) { + Object row = null; + if (keycode == KeyEvent.VK_UP) { + for (Object prev = get(component, itemname); prev != lead; + prev = getNextItem(component, prev, leafname)) { + row = prev; // component -> getParent(lead) + } + } + else if (keycode == KeyEvent.VK_DOWN) { + row = (lead == null) ? get(component, itemname) : + getNextItem(component, lead, leafname); + } + else if ((keycode == KeyEvent.VK_PAGE_UP) || + (keycode == KeyEvent.VK_PAGE_DOWN)) { + Rectangle view = getRectangle(scrollpane, ":view"); + Rectangle port = getRectangle(scrollpane, ":port"); + Rectangle rl = (lead != null) ? getRectangle(lead, "bounds") : null; + int vy = (keycode == KeyEvent.VK_PAGE_UP) ? + view.y : (view.y + port.height - 2); + if ((keycode == KeyEvent.VK_PAGE_UP) && + (rl != null) && (rl.y <= view.y)) { + vy -= port.height - 2; + } + if ((keycode == KeyEvent.VK_PAGE_DOWN) && + (rl != null) && (rl.y + rl.height >= view.y + port.height - 2)) { + vy += port.height - 2; + } + for (Object item = get(component, itemname); item != null; + item = getNextItem(component, item, leafname)) { + Rectangle r = getRectangle(item, "bounds"); + if (keycode == KeyEvent.VK_PAGE_UP) { + row = item; + if (r.y + r.height > vy) { break; } + } else { + if (r.y > vy) { break; } + row = item; + } + } + } + else if (keycode == KeyEvent.VK_HOME) { + row = get(component, itemname); + } + else if (keycode == KeyEvent.VK_END) { + for (Object last = lead; last != null; + last = getNextItem(component, last, leafname)) { + row = last; + } + } + return row; + } + + /** + * + */ + private void selectAll(Object component, + boolean selected, String itemname, String leafname) { + boolean changed = false; + for (Object item = get(component, itemname); + item != null; item = getNextItem(component, item, leafname)) { + if (setBoolean(item, "selected", selected, false)) { + repaint(component, null, item); changed = true; + } + } + set(component, "anchor", null); + if (changed) {invoke(component, "action"); } + } + + /** + * + */ + private void selectItem(Object component, + Object row, String itemname, String leafname) { + boolean changed = false; + for (Object item = get(component, itemname); + item != null; item = getNextItem(component, item, leafname)) { + if (setBoolean(item, "selected", (item == row), false)) { + repaint(component, null, item); changed = true; + } + } + set(component, "anchor", null); + if (changed) { invoke(component, "action"); } + } + + /** + * + */ + private void extend(Object component, Object lead, + Object row, String itemname, String leafname) { + Object anchor = get(component, "anchor"); + if (anchor == null) { set(component, "anchor", anchor = lead); } + char select = 'n'; boolean changed = false; + for (Object item = get(component, itemname); // anchor - row + item != null; item = getNextItem(component, item, leafname)) { + if (item == anchor) select = (select == 'n') ? 'y' : 'r'; + if (item == row) select = (select == 'n') ? 'y' : 'r'; + if (setBoolean(item, "selected", (select != 'n'), false)) { + repaint(component, null, item); changed = true; + } + if (select == 'r') select = 'n'; + } + if (changed) { invoke(component, "action"); } + } + + /** + * + */ + private void setLead(Object component, Object oldlead, Object lead) { + if (oldlead != lead) { //? + if (oldlead != null) { repaint(component, null, oldlead); } + set(component, "lead", lead); + repaint(component, null, lead); + } + } + + /*public void repaint(int x, int y, int width, int height) { + System.out.println("repaint(" + x + ", " + y + ", " + width + ", " + height + ")"); + super.repaint(x, y, width, height); + }*/ + + /** + * + */ + private void handleMouseEvent(int x, int y, int clickcount, + boolean shiftdown, boolean controldown, boolean popuptrigger, + int id, Object component, Object part) { + if (id == MouseEvent.MOUSE_ENTERED) { + setTimer(750L); + } + else if (id == MouseEvent.MOUSE_EXITED) { + hideTip(); + } + if (!getBoolean(component, "enabled", true)) { return; } + String classname = getClass(component); + if (("button" == classname) || ("checkbox" == classname)) { + if ((id == MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED) || + (id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_RELEASED)) { + if (id == MouseEvent.MOUSE_PRESSED) { + setFocus(component); + } + else if ((id == MouseEvent.MOUSE_RELEASED) && + (mouseinside == component)) { + if ("checkbox" == classname) { + changeCheck(component, true); + } + else invoke(component, "action"); + } + repaint(component); + } + } + else if ("combobox" == classname) { + boolean editable = getBoolean(component, "editable", true); + if (editable && (part == null)) { + Image icon = null; + int left = ((id == MouseEvent.MOUSE_PRESSED) && + ((icon = getIcon(component, "icon", null)) != null)) ? + icon.getWidth(this) : 0; + processField(x, y, clickcount, id, component, part, false, false, left); + } + else if (part != "icon") { // part = "down" + if (((id == MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED)) && (mousepressed == null)) { + if (editable) { repaint(component, "combobox", part); } + else { repaint(component); } + } + else if (id == MouseEvent.MOUSE_PRESSED) { + Object combolist = get(component, "combolist"); + if (combolist == null) { + setFocus(component); + repaint(component); + popup(component, classname); + } else { + closeup(component, combolist, null); + } + } + else if (id == MouseEvent.MOUSE_RELEASED) { + if (mouseinside != component) { + Object combolist = get(component, "combolist"); + closeup(component, combolist, + (mouseinside == combolist) ? insidepart : null); + } else { + repaint(component); + } + } + } + } + else if ("combolist" == classname) { + if (!processScroll(x, y, id, component, part)) { + if ((id == MouseEvent.MOUSE_ENTERED) || (id == DRAG_ENTERED)) { + if (part != null) { + // repaint previous inside + set(component, "inside", part); + repaint(component, classname, part); + } + } + else if ((id == MouseEvent.MOUSE_EXITED) || (id == DRAG_EXITED)) { + if (part != null) { + set(component, "inside", null); + repaint(component, classname, part); + } + } + else if (id == MouseEvent.MOUSE_RELEASED) { + closeup(get(component, "combobox"), component, part); + } + } + } + else if (("textfield" == classname) || ("passwordfield" == classname)) { + processField(x, y, clickcount, id, component, part, + false, ("passwordfield" == classname), 0); + } + else if ("textarea" == classname) { + if (!processScroll(x, y, id, component, part)) { + processField(x, y, clickcount, id, component, part, true, false, 0); + } + } + //java> + else if ("desktop" == classname) { + if (id == MouseEvent.MOUSE_ENTERED) { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + } + else if (id == MouseEvent.MOUSE_EXITED) { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + //MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED) || + (id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_RELEASED)) { + if (id == MouseEvent.MOUSE_PRESSED) { + setFocus(component); + if (processSpin(component, part)) { setTimer(375L); } + //settext: start end selection, parse exception... + } + else { + if (id == MouseEvent.MOUSE_RELEASED) { + setTimer(0L); + } + } + repaint(component, classname, part); + } + } + } + else if ("tabbedpane" == classname) { + if ((id == MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED)) { + if ((part != null) && getBoolean(part, "enabled", true) && + (getInteger(component, "selected", 0) != getIndex(component, "tab", part))) { + repaint(component, "tabbedpane", part); + } + } + else if ((part != null) && (id == MouseEvent.MOUSE_PRESSED) && + getBoolean(part, "enabled", true)) { + int selected = getInteger(component, "selected", 0); + int current = getIndex(component, "tab", part); + if (selected == current) { + setFocus(component); + repaint(component, "tabbedpane", part); + } + else { + setInteger(component, "selected", current, 0); + //Object tabcontent = getItemImpl(component, "component", current); + //setFocus((tabcontent != null) ? tabcontent : component); + setNextFocusable(component, false); + repaint(component); + invoke(component, "action"); + } + } + } + else if ("slider" == classname) { + if ((id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_DRAGGED)) { + if (id == MouseEvent.MOUSE_PRESSED) { + setReference(component, block / 2, block / 2); + setFocus(component); + } + int minimum = getInteger(component, "minimum", 0); + int maximum = getInteger(component, "maximum", 100); + int value = getInteger(component, "value", 50); + Rectangle bounds = getRectangle(component, "bounds"); + boolean horizontal = ("vertical" != get(component, "orientation")); + int newvalue = minimum + + (horizontal ? (mousex - referencex) : (mousey - referencey)) * + (maximum - minimum) / + ((horizontal ? bounds.width : bounds.height) - block); //... +0.5 + newvalue = Math.max(minimum, Math.min(newvalue, maximum)); + if (value != newvalue) { + setInteger(component, "value", newvalue, 50); + invoke(component, "action"); + } + if ((value != newvalue) || (id == MouseEvent.MOUSE_PRESSED)) { + repaint(component); + } + } + } + else if ("splitpane" == classname) { + if (id == MouseEvent.MOUSE_PRESSED) { + setReference(component, 2, 2); + } + else if (id == MouseEvent.MOUSE_DRAGGED) { + int divider = getInteger(component, "divider", -1); + boolean horizontal = ("vertical" != get(component, "orientation")); + int moveto = horizontal ? (mousex - referencex) : + (mousey - referencey); + Rectangle bounds = getRectangle(component, "bounds"); + moveto = Math.max(0, Math.min(moveto, + Math.abs(horizontal ? bounds.width : bounds.height) - 5)); + if (divider != moveto) { + setInteger(component, "divider", moveto, -1); + validate(component); + } + } + //java> + else if ((id == MouseEvent.MOUSE_ENTERED) && (mousepressed == null)) { + boolean horizontal = ("vertical" != get(component, "orientation")); + setCursor(Cursor.getPredefinedCursor(horizontal ? + Cursor.E_RESIZE_CURSOR : Cursor.S_RESIZE_CURSOR)); + } + else if (((id == MouseEvent.MOUSE_EXITED) && (mousepressed == null)) || + ((id == MouseEvent.MOUSE_RELEASED) && (mouseinside != component))) { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + //MouseEvent.MOUSE_PRESSED)|| + ((id == MouseEvent.MOUSE_DRAGGED) && + !shiftdown && !controldown)) && + !popuptrigger) { // e.getClickCount() + Rectangle view = getRectangle(component, ":view"); + Rectangle viewport = getRectangle(component, ":port"); + int my = mousey + view.y - referencey; + String itemname = ("list" == classname) ? "item" : + (("table" == classname) ? "row" : "node"); + String subitem = ("tree" == classname) ? "node" : null; + for (Object item = get(component, itemname); item != null;) { + Rectangle r = getRectangle(item, "bounds"); + if (my < r.y + r.height) { + if (id == MouseEvent.MOUSE_DRAGGED) { //!!! + scrollToVisible(component, r.x, r.y, 0, r.height - 1); + } + else if ("tree" == classname) { + int mx = mousex + view.x - referencex; + if (mx < r.x) { + if ((mx >= r.x - block) && (get(item, "node") != null)) { + boolean expanded = getBoolean(item, "expanded", true); + setBoolean(item, "expanded", !expanded, true); + selectItem(component, item, "node", "node"); + setLead(component, get(component, "lead"), item); + setFocus(component); + validate(component); + invoke(component, expanded ? "collapse" : "expand"); //item + } + break; + } + } + if ((id != MouseEvent.MOUSE_DRAGGED) || + !getBoolean(item, "selected", false)) { + select(component, item, itemname, subitem, shiftdown, controldown); + if (id != MouseEvent.MOUSE_DRAGGED) { + if (setFocus(component)) { repaint(component, classname, item); } //? + } + } + break; + } + item = getNextItem(component, item, subitem); + } + } + } + } + else if ("menubar" == classname) { + Object selected = get(component, "selected"); + if (((id == MouseEvent.MOUSE_ENTERED) || (id == MouseEvent.MOUSE_EXITED)) && + (part != null) && (selected == null)) { + repaint(component, classname, part); + } + else if ((part != null) && ((selected == null) ? + (id == MouseEvent.MOUSE_PRESSED) : + ((id == MouseEvent.MOUSE_ENTERED) || (id == DRAG_ENTERED)))) { + set(component, "selected", part); + popup(component, classname); + repaint(component, classname, part); + } + else if ((id == MouseEvent.MOUSE_PRESSED) && (selected != null)) { + closeup(component); + } + else if (id == MouseEvent.MOUSE_RELEASED) { + if ((part != insidepart) && + ((insidepart == null) || (getClass(insidepart) != "menu"))) { + if ((insidepart != null) && getBoolean(insidepart, "enabled", true)) { + if (getClass(insidepart) == "checkboxmenuitem") { + changeCheck(insidepart, false); + } + else invoke(insidepart, "action"); + } + closeup(component); + } + } + } + else if ("popupmenu" == classname) { + if (part != null) { + if ((id == MouseEvent.MOUSE_ENTERED) || (id == DRAG_ENTERED)) { + set(component, "selected", part); + popup(component, classname); + repaint(component, classname, part); + } + else if (id == MouseEvent.MOUSE_RELEASED) { + if ((insidepart == null) || (getClass(insidepart) != "menu")) { + Object menubar = part; + do { + menubar = getParent(menubar); + } while (getClass(menubar) != "menubar"); + if ((insidepart != null) && getBoolean(insidepart, "enabled", true)) { + if (getClass(insidepart) == "checkboxmenuitem") { + changeCheck(insidepart, false); + } + else invoke(insidepart, "action"); + } + closeup(menubar); + } + } + else if ((id == MouseEvent.MOUSE_EXITED) || (id == DRAG_EXITED)) { + if (getClass(part) != "menu") { + set(component, "selected", null); + } + repaint(component, classname, part); + } + } + } + else if ("dialog" == classname) { + if (part == "header") { + if (id == MouseEvent.MOUSE_PRESSED) { + referencex = mousex; referencey = mousey; + if (!getBoolean(component, "modal", false) && + (get(content, "component") != component)) { + removeItemImpl(content, "component", component); + insertItem(content, "component", component, 0); + set(component, ":parent", content); + repaint(component); + } + } + else if (id == MouseEvent.MOUSE_DRAGGED) { + Rectangle bounds = getRectangle(component, "bounds"); + int dx = mousex - referencex; int dy = mousey - referencey; + repaint(component, + bounds.x + Math.min(0, dx), bounds.y + Math.min(0, dy), + bounds.width + Math.abs(dx), bounds.height + Math.abs(dy)); + bounds.x += dx; bounds.y += dy; + referencex = mousex; referencey = mousey; + } + } + } + } + + /** + * + */ + private void setReference(Object component, int x, int y) { + referencex = x; referencey = y; + for (; component != null; component = getParent(component)) { + Rectangle bounds = getRectangle(component, "bounds"); + referencex += bounds.x; referencey += bounds.y; + } + } + + /** + * + */ + private void select(Object component, Object row, String first, + String child, boolean shiftdown, boolean controldown) { + String selection = getString(component, "selection", "single"); + Object lead = null; + if (shiftdown && (selection != "single") && + ((lead = get(component, "lead")) != null)) { + extend(component, lead, row, first, child); + } + else { + if (controldown && (selection == "multiple")) { + setBoolean(row, "selected", + !getBoolean(row, "selected", false), false); + repaint(component, null, row); + invoke(component, "action"); + set(component, "anchor", null); + } + else if (controldown && getBoolean(row, "selected", false)) { + for (Object item = row; + item != null; item = getNextItem(component, item, child)) { + if (setBoolean(item, "selected", false, false)) { + repaint(component, null, item); + } + } + invoke(component, "action"); + set(component, "anchor", null); + } + else { + selectItem(component, row, first, child); + } + } + setLead(component, (lead != null) ? lead : get(component, "lead"), row); + } + + /** + * + */ + private Object getNextItem(Object component, + Object item, String subitem) { + if (subitem == null) { return get(item, ":next"); } + Object next = get(item, subitem); + if ((next == null) || !getBoolean(item, "expanded", true)) { + while ((item != component) && ((next = get(item, ":next")) == null)) { + item = getParent(item); + } + } + return next; + } + + /** + * + */ + private void processField(int x, int y, int clickcount, + int id, Object component, + Object part, boolean multiline, boolean hidden, int left) { + if (id == MouseEvent.MOUSE_PRESSED) { + setReference(component, 2 + left, 2); + int mx = x - referencex; + int my = 0; + if (!multiline) { + mx += getInteger(component, "offset", 0); + } else { + Rectangle view = getRectangle(component, ":view"); + mx += view.x - 1; + my = y - referencey + view.y - 1; + } + int caretstart = getCaretLocation(component, mx, my, hidden); + int caretend = caretstart; + //java> + if (clickcount > 1) { + String text = getString(component, "text", ""); + while ((caretstart > 0) && ((clickcount == 2) ? + Character.isLetterOrDigit(text.charAt(caretstart - 1)) : + (text.charAt(caretstart - 1) != '\n'))) { caretstart--; } + while ((caretend < text.length()) && ((clickcount == 2) ? + Character.isLetterOrDigit(text.charAt(caretend)) : + (text.charAt(caretend) != '\n'))) { caretend++; } + } + //MouseEvent.MOUSE_DRAGGED) { + int mx = x - referencex; + int my = 0; + if (!multiline) { + mx += getInteger(component, "offset", 0); + } else { + Rectangle view = getRectangle(component, ":view"); + mx += view.x - 1; + my = y - referencey + view.y - 1; + } + int dragcaret = getCaretLocation(component, mx, my, hidden); + if (dragcaret != getInteger(component, "end", 0)) { + setInteger(component, "end", dragcaret, 0); + validate(component); // caret check only + } + } + //java> + else if ((id == MouseEvent.MOUSE_ENTERED) && (mousepressed == null)) { + setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); + } + else if (((id == MouseEvent.MOUSE_EXITED) && (mousepressed == null)) || + ((id == MouseEvent.MOUSE_RELEASED) && + ((mouseinside != component) || (insidepart != null)))) { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + //FontMetrics fm = getFontMetrics(getFont()); + for (int i = 0, j = 0; true; i = j + 1) { + j = text.indexOf('\n', i); + if ((j == -1) || y < fm.getHeight()) { + if (j == -1) { j = text.length(); } + for (int k = i; k < j; k++) { + int charwidth = fm.charWidth(hidden ? '*' : text.charAt(k)); + if (x <= (charwidth / 2)) { + return k; + } + x -= charwidth; + } + return j; + } + y -= fm.getHeight(); + } + } + + /** + * + */ + private boolean processScroll(int x, int y, + int id, Object component, Object part) { + if ((part == "up") || (part == "down") || + (part == "left") || (part == "right")) { + if ((id == MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED) || + (id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_RELEASED)) { + if (id == MouseEvent.MOUSE_PRESSED) { + if (processScroll(component, part)) { + setTimer(300L); return true; + } + } + else { + if (id == MouseEvent.MOUSE_RELEASED) { setTimer(0L); } + repaint(component, null, part); + } + } + } + else if ((part == "uptrack") || (part == "downtrack") || + (part == "lefttrack") || (part == "righttrack")) { + if (id == MouseEvent.MOUSE_PRESSED) { + if (processScroll(component, part)) { + setTimer(300L); + } + } + else if (id == MouseEvent.MOUSE_RELEASED) { + setTimer(0L); + } + } + else if ((part == "vknob") || (part == "hknob")) { + if (id == MouseEvent.MOUSE_PRESSED) { + Rectangle port = getRectangle(component, ":port"); + Rectangle view = getRectangle(component, ":view"); + if (part == "hknob") { + referencex = x - + view.x * (port.width - 2 * block) / view.width; + } else { + referencey = y - + view.y * (port.height - 2 * block) / view.height; + } + } + else if (id == MouseEvent.MOUSE_DRAGGED) { + Rectangle port = getRectangle(component, ":port"); + Rectangle view = getRectangle(component, ":view"); + if (part == "hknob") { + int viewx = (x - referencex) * + view.width / (port.width - 2 * block); + viewx = Math.max(0, Math.min(viewx, view.width - port.width + 2)); + if (view.x != viewx) { + view.x = viewx; + repaint(component, null, "horizontal"); + } + } else { + int viewy = (y - referencey) * + view.height / (port.height - 2 * block); + viewy = Math.max(0, Math.min(viewy, view.height - port.height + 2)); + if (view.y != viewy) { + view.y = viewy; + repaint(component, null, "vertical"); + } + } + } + } + else if (part == "corner") { + part = "corner"; // compiler bug + } + else { + if (id == MouseEvent.MOUSE_PRESSED) { + Rectangle port = getRectangle(component, ":port"); + setReference(component, port.x + 1, port.y + 1); + } + return false; + } + return true; + } + + /** + * + */ + private boolean processScroll(Object component, Object part) { + Rectangle view = getRectangle(component, ":view"); + Rectangle port = ((part == "left") || (part == "up")) ? null : + getRectangle(component, ":port"); + int dx = 0; int dy = 0; + if (part == "left") { dx = -10; } + else if (part == "lefttrack") { dx = -port.width; } + else if (part == "right") { dx = 10; } + else if (part == "righttrack") { dx = port.width; } + else if (part == "up") { dy = -10; } + else if (part == "uptrack") { dy = -port.height; } + else if (part == "down") { dy = 10; } + else if (part == "downtrack") { dy = port.height; } + if (dx != 0) { + dx = (dx < 0) ? Math.max(-view.x, dx) : + Math.min(dx, view.width - port.width + 2 - view.x); + } + else if (dy != 0) { + dy = (dy < 0) ? Math.max(-view.y, dy) : + Math.min(dy, view.height - port.height + 2 - view.y); + } + else return false; + view.x += dx; view.y += dy; + repaint(component, null, (dx != 0) ? "horizontal" : "vertical"); + return (((part == "left") || (part == "lefttrack")) && (view.x > 0)) || + (((part == "right") || (part == "righttrack")) && + (view.x < view.width - port.width + 2)) || + (((part == "up") || (part == "uptrack")) && (view.y > 0)) || + (((part == "down") || (part == "downtrack")) && + (view.y < view.height - port.height + 2)); + } + + /** + * + */ + private boolean processSpin(Object component, Object part) { + String text = getString(component, "text", null); + if (text != null) { + try { + String value = String.valueOf( + Integer.parseInt(text) + ((part == "up") ? 1 : -1)); + setString(component, "text", value, null); + setInteger(component, "start", value.length(), 0); + setInteger(component, "end", 0, 0); + repaint(component, "spinbox", null); + invoke(component, "action"); + return true; + } catch (NumberFormatException nfe) {} + } + return false; + } + + //java> + /*public void setEventHandler(Object component, Object eventhandler) { + set(component, ":handler", eventhandler); + }*/ + + /** + * + */ + private void invoke(Object component, String event) { + Method method = (Method) get(component, event); + if (method != null) { + try { + method.invoke(this, null); + } catch (InvocationTargetException ite) { + ite.getTargetException().printStackTrace(); + } catch (Exception exc) { + exc.printStackTrace(); + } + } + } + //Rectangle bounds = getRectangle(component, "bounds"); + if ((bounds == null) || !(bounds.contains(x, y))) { return false; } //java + //midp if ((bounds == null) || (x < bounds.x) || (x - bounds.x >= bounds.width) || + //midp (y < bounds.y) || (y - bounds.y >= bounds.height)) { return false; } + mouseinside = component; + x -= bounds.x; y -= bounds.y; + String classname = getClass(component); + + if ("combobox" == classname) { + if (getBoolean(component, "editable", true) && (x <= bounds.width - block)) { + Image icon = getIcon(component, "icon", null); + insidepart = ((icon != null) && (x <= 2 + icon.getWidth(this))) ? + "icon" : null; + } else { + insidepart = "down"; + } + } + else if ("combolist" == classname) { + if (!findScrollPane(component, x, y, bounds)) { + y += getRectangle(component, ":view").y; + for (Object choice = get(get(component, "combobox"), "choice"); + choice != null; choice = get(choice, ":next")) { + Rectangle r = getRectangle(choice, "bounds"); + if ((y >= r.y) && (y < r.y + r.height)) { + insidepart = choice; break; + } + } + } + } + else if ("textarea" == classname) { + findScrollPane(component, x, y, bounds); + } + else if ("tabbedpane" == classname) { + Object tabcontent = getItemImpl(component, + "component", getInteger(component, "selected", 0)); + if ((tabcontent == null) || !findComponent(tabcontent, x, y)) { + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Rectangle r = getRectangle(comp, "bounds"); + if (r.contains(x, y)) { //java + //midp if ((x >= r.x) && (x - r.x < r.width) && (y >= r.y) && (y - r.y < r.height)) { + insidepart = comp; break; + } + } + } + } + else if (("panel" == classname) || ("desktop" == classname) || + ("dialog" == classname)) { + if (("dialog" == classname) && + (y < 4 + getInteger(component, "titleheight", 0))) { + insidepart = "header"; + } else { + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if (findComponent(comp, x, y)) { break; } + if (("desktop" == classname) && + getBoolean(comp, "modal", false)) { break; } // && dialog + } + } + } + else if ("spinbox" == classname) { + insidepart = (x <= bounds.width - block) ? null : + ((y <= bounds.height / 2) ? "up" : "down"); + } + else if ("splitpane" == classname) { + Object comp1 = get(component, "component"); + if (comp1 != null) { + if (!findComponent(comp1, x, y)) { + Object comp2 = get(comp1, ":next"); + if (comp2 != null) { + findComponent(comp2, x, y); + } + } + } + } + else if ("list" == classname) { + findScrollPane(component, x, y, bounds); + } + else if ("table" == classname) { + findScrollPane(component, x, y, bounds); + } + else if ("tree" == classname) { + findScrollPane(component, x, y, bounds); + } + else if ("menubar" == classname) { + for (Object menu = get(component, "menu"); + menu != null; menu = get(menu, ":next")) { + Rectangle r = getRectangle(menu, "bounds"); + if ((x >= r.x) && (x < r.x + r.width)) { + insidepart = menu; break; + } + } + } + else if ("popupmenu" == classname) { + for (Object menu = get(get(component, "menu"), "menu"); + menu != null; menu = get(menu, ":next")) { + Rectangle r = getRectangle(menu, "bounds"); + if ((y >= r.y) && (y < r.y + r.height)) { + insidepart = menu; break; + } + } + } + return true; + } + + /** + * + */ + private boolean findScrollPane(Object component, + int x, int y, Rectangle bounds) { + Rectangle port = getRectangle(component, ":port"); + if ((x < port.x) || (y < port.y) || + ((x >= port.x + port.width) && (y >= port.y + port.height))) { + insidepart = "corner"; + } + else if ((x >= port.x + port.width) || (y >= port.y + port.height)) { + boolean horizontal = (y >= port.y + port.height); + int p = horizontal ? (x - port.x) : (y - port.y); + int portsize = horizontal ? port.width : port.height; + int button = Math.min(block, portsize / 2); + if (p < button) { + insidepart = horizontal ? "left" : "up"; + } + else if (p >= portsize - button) { + insidepart = horizontal ? "right" : "down"; + } + else { + Rectangle view = getRectangle(component, ":view"); + int viewp = horizontal ? view.x : view.y; + int viewsize = horizontal ? view.width : view.height; + int track = portsize - (2 * button); + int knob = Math.min(track, + Math.max(track * (portsize - 2) / viewsize, 6)); + int decrease = viewp * (track - knob) / (viewsize - portsize + 2); + if (p < button + decrease) { + insidepart = horizontal ? "lefttrack" : "uptrack"; + } + else if (p < button + decrease + knob) { + insidepart = horizontal ? "hknob" : "vknob"; + } + else { + insidepart = horizontal ? "righttrack" : "downtrack"; + } + } + } + else { return false; } + return true; + } + + /** + * + */ + private void repaint(Object component, Object classname, Object part) { + Rectangle b = getRectangle(component, "bounds"); + if ((classname == "combobox") || (classname == "spinbox")) { + boolean down = (part == "up") || (part == "down"); // else text + repaint(component, down ? (b.x + b.width - block) : b.x, b.y, + down ? block : (b.width - block), b.height); + } + //else if (classname == "dialog") {} + //int titleheight = getInteger(component, "titleheight", 0); + //else if (classname == "splitpane") {} + else if ((classname == "tabbedpane") || + (classname == "menubar") || (classname == "popupmenu")) { + Rectangle r = getRectangle(part, "bounds"); + repaint(component, b.x + r.x, b.y + r.y, + (classname == "popupmenu") ? b.width : r.width, r.height); + } + else //if ((classname == "combolist") || (classname == "textarea") || + {//(classname == "list") || (classname == "table") || (classname == "tree")) { + Rectangle port = getRectangle(component, ":port"); + if (part == "left") { + repaint(component, b.x + port.x, b.y + b.height - block, block, block); + } + else if (part == "right") { + repaint(component, b.x + port.x + port.width - block, b.y + b.height - block, block, block); + } + else if (part == "up") { + repaint(component, b.x + b.width - block, b.y + port.y, block, block); + } + else if (part == "down") { + repaint(component, b.x + b.width - block, b.y + port.y + port.height - block, block, block); + } + else if (part == "horizontal") { // horizontaly center part + repaint(component, b.x + port.x, b.y, port.width, b.height); + } + else if (part == "vertical") { + repaint(component, b.x, b.y + port.y, b.width, port.height); + } + else if (part == "text") { //textarea + repaint(component, b.x + port.x, b.y + port.y, port.width, port.height); + } + else { + Rectangle view = getRectangle(component, ":view"); + Rectangle r = getRectangle(part, "bounds"); + if ((r.y + r.height >= view.y) && (r.y <= view.y + port.height)) { + repaint(component, b.x + port.x, b.y + port.y - view.y + 1 + r.y, + port.width, r.height); + //? need cut item rectangle above/bellow viewport + } + } + } + } + + /** + * + */ + private void validate(Object component) { + repaint(component); + Rectangle bounds = getRectangle(component, "bounds"); + bounds.width = -1 * Math.abs(bounds.width); + } + + /** + * + */ + private void repaint(Object component) { + Rectangle bounds = getRectangle(component, "bounds"); + if (bounds != null) { + repaint(component, bounds.x, bounds.y, bounds.width, bounds.height); + } + } + + /** + * + */ + private void repaint(Object component, int x, int y, int width, int height) { + while ((component = getParent(component)) != null) { + Rectangle bounds = getRectangle(component, "bounds"); + x += bounds.x; + y += bounds.y; + } + repaint(x, y, width, height); + } + + /*private void clip(Graphics g, + Rectangle clip, int x, int y, int width, int height) { + int x1 = Math.max(clip.x, x); + int y1 = Math.max(clip.y, y); + int x2 = Math.min(clip.x + clip.width, x + width); + int y2 = Math.min(clip.y + clip.height, y + height); + g.setClip(x1, y1, x2 - x1, y2 - y1); + }*/ + + /** + * + */ + public boolean requestFocus(Object component) { + if (checkFocusable(component, true)) { + setFocus(component); return true; + } + return false; + } + + /** + * + */ + private boolean setFocus(Object component) { + if (!focusinside) { //java + requestFocus(); //java + } //java + if (focusowner != component) { + Object focused = focusowner; + focusowner = component; + if (focused != null) { + //mouseEvent(null, FocusEvent.FOCUS_LOST, focused, null, null); + repaint(focused); + //focusGained(component); + } + return true; + } + return false; + } + + /** + * @return next focusable component is found (not the first of the desktop/dialog) + */ + private boolean setNextFocusable(Object current, boolean outgo) { + boolean consumed = true; + for (Object next = null, component = current; true; component = next) { + next = get(component, "component"); // check first subcomponent + if (next == null) { next = get(component, ":next"); } // check next component + while (next == null) { // find the next of the parents, or the topmost + component = getParent(component); // current is not on the desktop + if (component == null) { return false; } + if ((component == content) || ((getClass(component) == "dialog") && + (!outgo || getBoolean(component, "modal", false)))) { + consumed = false; // find next focusable but does not consume event + next = component; // the topmost (desktop or modal dialog) + } + else { + next = get(component, ":next"); + } + } + if (next == current) { return false; } // one fucusable, no loop + if (checkFocusable(next, false)) { + setFocus(next); + return consumed; + } + } + } + + //java> + /** + * @return previous focusable component is found (not the last of the desktop/dialog) + */ + private boolean setPreviousFocusable(Object component, boolean outgo) { + for (int i = 0; i < 2; i++) { // 0 is backward direction + Object previous = getPreviousFocusable(component, null, true, false, (i == 0), outgo); + if (previous != null) { + setFocus(previous); + return (i == 0); + } + } + return false; + } + + /** + * For the starting component search its parent direction for a focusable component, and then + * its next component (if not search backward from the component).
+ * For its parent components check its first component, the current one, and its parent direction + * (backward search), or its parent, then next component (forward direction).
+ * For the rest components check the next, then the first subcomponent direction, and finally + * check whether the component is focusable. + */ + private Object getPreviousFocusable(Object component, + Object block, boolean start, boolean upward, boolean backward, boolean outgo) { + Object previous = null; + if ((component != null) && (component != block)) { + boolean go = ((getClass(component) != "dialog") || + (outgo && !getBoolean(component, "modal", false))); + if (!start && !upward && go) { + previous = getPreviousFocusable(get(component, ":next"), block, false, false, backward, outgo); + } + if ((previous == null) && ((upward && backward) || (!start && !upward))) { + previous = getPreviousFocusable(get(component, "component"), block, false, false, backward, outgo); + if ((previous == null) && checkFocusable(component, false)) { + previous = component; + } + } + if ((previous == null) && (start || upward) && go) { + previous = getPreviousFocusable(getParent(component), component, false, true, backward, outgo); + } + if ((previous == null) && (start || upward) && !backward && go) { + previous = getPreviousFocusable(get(component, ":next"), block, false, false, backward, outgo); + } + } + return previous; + } + // " + path + " " + inputstream); + } catch (Throwable e) {} //java + //if (inputstream == null) { // applet code + // inputstream = new URL(getCodeBase(), path).openStream(); + //} + return parse(inputstream); //, Object handler + } + + /** + * + */ + public Object parse(InputStream inputstream) throws Exception { + return parse(inputstream, true); + } + + /** + * + */ + protected void parseXML(InputStream inputstream) throws Exception { + parse(inputstream, false); + } + + /** + * + */ + protected void startElement(String name, Hashtable attributelist) {} + + /** + * + */ + protected void characters(String text) {} + + /** + * + */ + protected void endElement() {} + + /** + * + */ + private Object parse(InputStream inputstream, boolean validate) throws Exception { + BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream)); //java + //midp InputStreamReader reader = new InputStreamReader(inputstream); + Object[] parentlist = null; + Object current = null; + Hashtable attributelist = null; + StringBuffer text = new StringBuffer(); + for (int c = reader.read(); c != -1;) { + if (c == '<') { + if ((c = reader.read()) == '/') { //endtag + if (text.length() > 0) { + if (text.charAt(text.length() - 1) == ' ') { + text.setLength(text.length() - 1); + } + if (!validate) { + characters(text.toString()); + }// else { + //addContent(current, text.toString()); + //} + text.setLength(0); + } + String tagname = (String) parentlist[2]; //getClass(current); + for (int i = 0; i < tagname.length(); i++) { // current-tag + if ((c = reader.read()) != tagname.charAt(i)) { + throw new IllegalArgumentException(tagname); + } + } + while (" \t\n\r".indexOf(c = reader.read()) != -1); // whitespace + if (c != '>') throw new IllegalArgumentException(); // '>' + c = reader.read(); + if (!validate) { endElement(); } + if (parentlist[0] == null) { + reader.close(); + return current; + } + current = parentlist[0]; + parentlist = (Object[]) parentlist[1]; + } + else { //start or standalone tag + boolean instruction = (c == '?'); // Processing Instructions + if (c == '!') { while ((c = reader.read()) != '>'); continue; } // DOCTYPE + if (instruction) { c = reader.read(); } + text.setLength(0); + boolean iscomment = false; + while (">/ \t\n\r".indexOf(c) == -1) { + text.append((char) c); + if ((text.length() == 3) && (text.charAt(0) == '!') && + (text.charAt(1) == '-') && (text.charAt(2) == '-')) { + int m = 0; + while (true) { + c = reader.read(); + if (c == '-') { m++; } + else if ((c == '>') && (m >= 2)) { break; } + else { m = 0; } + } + iscomment = true; + } + c = reader.read(); + } + if (iscomment) { continue; } + if (!instruction) { + String tagname = text.toString(); + parentlist = new Object[] { current, parentlist, tagname }; + if (validate) { + current = (current != null) ? + addElement(current, tagname) : create(tagname); + } else { + current = tagname; + } + } + text.setLength(0); + while (true) { + boolean whitespace = false; + while (" \t\n\r".indexOf(c) != -1) { + c = reader.read(); + whitespace = true; + } + if (c == '>') { + if (instruction) throw new IllegalArgumentException(); // '?>' + if (!validate) { + startElement((String) current, attributelist); attributelist = null; + } + c = reader.read(); + break; + } + else if (c == '/') { + if (instruction) throw new IllegalArgumentException(); // '?>' + if ((c = reader.read()) != '>') { + throw new IllegalArgumentException(); // '>' + } + if (!validate) { + startElement((String) current, attributelist); attributelist = null; + endElement(); + } + if (parentlist[0] == null) { + reader.close(); + return current; + } + current = parentlist[0]; + parentlist = (Object[]) parentlist[1]; + c = reader.read(); + break; + } + else if (instruction && (c == '?')) { + if ((c = reader.read()) != '>') { + throw new IllegalArgumentException(); // '>' + } + c = reader.read(); + break; + } + else if (whitespace) { + while ("= \t\n\r".indexOf(c) == -1) { + text.append((char) c); + c = reader.read(); + } + String key = text.toString(); + text.setLength(0); + while (" \t\n\r".indexOf(c) != -1) c = reader.read(); + if (c != '=') throw new IllegalArgumentException(); + while (" \t\n\r".indexOf(c = reader.read()) != -1); + char quote = (char) c; + if ((c != '\"') && (c != '\'')) throw new IllegalArgumentException(); + while (quote != (c = reader.read())) { + if (c == '&') { + StringBuffer eb = new StringBuffer(); + while (';' != (c = reader.read())) { eb.append((char) c); } + String entity = eb.toString(); + if ("lt".equals(entity)) { text.append('<'); } + else if ("gt".equals(entity)) { text.append('>'); } + else if ("amp".equals(entity)) { text.append('&'); } + else if ("quot".equals(entity)) { text.append('"'); } + else if ("apos".equals(entity)) { text.append('\''); } + else if (entity.startsWith("#")) { + text.append((char) Integer.parseInt(entity.substring(1))); + } + else throw new IllegalArgumentException("unknown " + "entity " + entity); + } + else text.append((char) c); + } + if (!instruction) { + if (validate) { + addAttribute(current, key, text.toString()); + } else { + if (attributelist == null) { attributelist = new Hashtable(); } + attributelist.put(key, text.toString()); + } + } + text.setLength(0); + c = reader.read(); + } + else throw new IllegalArgumentException(); + } + } + } + else { + if (" \t\n\r".indexOf(c) != -1) { + if ((text.length() > 0) && (text.charAt(text.length() - 1) != ' ')) { + text.append(' '); + } + } + else { + text.append((char) c); + } + c = reader.read(); + } + } + throw new IllegalArgumentException(); + } + + /** + * Convert entities. + */ + private static String convert(StringBuffer text) { + return null; + } + + /*private InputStream inputreader; + private byte[] data; + private int inputfrom = 0, inputto = 0; + private int read() throws Exception { + if (data == null) { data = new byte[1024]; } + if (inputfrom >= inputto) { + inputfrom = 0; + inputto = inputreader.read(data); + } + inputfrom++; + return data[inputfrom - 1]; + }*/ + + /** + * + */ + private void addImpl(Object parent, Object component, int index) { + String parentclass = getClass(parent); + String classname = getClass(component); + //System.out.println("add " + classname + " -> " + parentclass); + if ((("combobox" == parentclass) && ("choice" == classname)) || + (("tabbedpane" == parentclass) && ("tab" == classname)) || + (("list" == parentclass) && ("item" == classname)) || + (("table" == parentclass) && (("column" == classname) || ("row" == classname))) || + (("row" == parentclass) && ("cell" == classname)) || + ((("tree" == parentclass) || ("node" == parentclass)) && ("node" == classname)) || + (("menubar" == parentclass) && ("menu" == classname))) { + classname = classname; // compiler bug + } + else if (("menu" == parentclass) && (("menu" == classname) || ("menuitem" == classname) || + ("checkboxmenuitem" == classname) || ("separator" == classname))) { + classname = "menu"; + } + else if (("panel" == parentclass) || ("desktop" == parentclass) || + ("splitpane" == parentclass) || ("dialog" == parentclass) || + ("tabbedpane" == parentclass)) { + while ("component" != classname) { + String extendclass = null; + for (int i = 0; i < dtd.length; i += 3) { + if (classname == dtd[i]) { + extendclass = (String) dtd[i + 1]; break; + } + } + if (extendclass == null) throw new IllegalArgumentException(classname + " not component"); + classname = extendclass; + } + } + else throw new IllegalArgumentException(classname + " add " + parentclass); + insertItem(parent, (String) classname, component, index); + set(component, ":parent", parent); + //if (parent == content) System.out.println(getClass(parent) + ".add(" + getClass(component) + ") : " + classname); + } + + /** + * + */ + private Object addElement(Object parent, String name) { + //System.out.println("create '" + name + "'"); + Object component = create(name); + addImpl(parent, component, -1); + return component; + } + + /** + * + */ + private void addAttribute(Object component, String key, String value) { + //System.out.println("attribute '" + key + "'='" + value + "'"); + Object[] definition = getDefinition(component, key, null); + key = (String) definition[1]; + if ("string" == definition[0]) { + setString(component, key, value, (String) definition[3]); + } + else if ("choice" == definition[0]) { + String[] values = (String[]) definition[3]; + setChoice(component, key, value, values, values[0]); + } + else if ("boolean" == definition[0]) { + if ("true".equals(value)) { + if (definition[3] == Boolean.FALSE) { + set(component, key, Boolean.TRUE); + } + } + else if ("false".equals(value)) { + if (definition[3] == Boolean.TRUE) { + set(component, key, Boolean.FALSE); + } + } + else throw new IllegalArgumentException(value); + } + else if ("integer" == definition[0]) { + set(component, key, Integer.valueOf(value)); + } + else if ("icon" == definition[0]) { + set(component, key, getIcon(value)); + } + else if ("method" == definition[0]) { + try { //java + set(component, key, getClass().getMethod(value, null)); //java + } catch (Exception exc) { System.err.println(value); exc.printStackTrace(); } //java + //midp setMethod(component, key, value); + } + //java> + else if ("bean" == definition[0]) { + try { + set(component, key, (Component) Class.forName(value).newInstance()); + } catch (Exception exc) { System.err.println(value); exc.printStackTrace(); } + } + //Image icon) { + Object[] definition = getDefinition(component, key, "icon"); + if (set(component, (String) definition[1], icon)) { + update(component, definition[2]); + } + } + + /** + * + */ + public Image getIcon(Object component, String key) { + Object[] definition = getDefinition(component, key, "icon"); + return getIcon(component, (String) definition[1], (Image) definition[3]); + } + + /** + * + */ + public void setMethod(Object component, String key, Method method) { //java + //midp public void setMethod(Object component, String key, String method) { + Object[] definition = getDefinition(component, key, "method"); + if (set(component, (String) definition[1], method)) { + update(component, definition[2]); + } + } + + /** + * + */ + public Method getMethod(Object component, String key) { //java + //midp public String getMethod(Object component, String key) { + Object[] definition = getDefinition(component, key, "method"); + return (Method) get(component, (String) definition[1]); //java + //midp return (String) get(component, (String) definition[1]); + } + + /** + * + */ + private void update(Object component, Object mode) { + if ("parent" == mode) { + component = getParent(component); + mode = "validate"; + } + boolean firstpaint = true; + int x = 0; int y = 0; int width = 0; int height = 0; + while (component != null) { + if (!getBoolean(component, "visible", true)) { break; } + if ("paint" == mode) {//|| (firstpaint && (component == content)) + Rectangle bounds = getRectangle(component, "bounds"); + if (bounds == null) { return; } + if (firstpaint) { + x = bounds.x; y = bounds.y; + width = Math.abs(bounds.width); height = bounds.height; + firstpaint = false; + } else { + x += bounds.x; y += bounds.y; + } + if (component == content) { + repaint(x, y, width, height); + } + } + Object parent = getParent(component); + String classname = getClass(parent); + if ("combobox" == classname) { + parent = get(parent, "combolist"); + } + else if ("menu" == classname) { + parent = get(parent, "popupmenu"); + } + else if (("paint" == mode) && ("tabbedpane" == classname)) { + if (getItemImpl(parent, "component", + getInteger(parent, "selected", 0)) != component) { break; } + } + if (("layout" == mode) || (("validate" == mode) && + (("list" == classname) || ("table" == classname) || + ("tree" == classname) || ("dialog" == classname) || (parent == content)))) { + Rectangle bounds = getRectangle(parent, "bounds"); + if (bounds == null) { return; } + bounds.width = -1 * Math.abs(bounds.width); + mode = "paint"; + } + component = parent; + } + } + + // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + + /** + * + */ + private boolean setString(Object component, + String key, String value, String defaultvalue) { + /*boolean changed = set(component, key, value); + if (changed && ("name" == key)) { + //for (Class cls = getClass(); cls != null; cls = cls.getSuperclass()) { + Field[] fields = getClass().getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + if ((fields[i].getType() == Object.class) && + fields[i].getName().equals(value)) { + try { + fields[i].set(this, component); + return true; + } catch (IllegalAccessException iae) {} + } + } + //} + try { + getClass().getField(value).set(this, component); + } catch (Exception exc) {} + } + return changed;*/ + return set(component, key, value); + } + + /** + * + */ + private String getString(Object component, + String key, String defaultvalue) { + Object value = get(component, key); + return (value == null) ? defaultvalue : (String) value; + } + + /** + * + */ + private boolean setChoice(Object component, + String key, String value, String[] values, String defaultvalue) { + if (value == null) { + return set(component, key, defaultvalue); + } + for (int i = 0; i < values.length; i++) { + if (value.equals(values[i])) { + return set(component, key, values[i]); + } + } + throw new IllegalArgumentException("unknown " + value + " for " + key); + } + + /** + * + */ + private boolean setIcon(Object component, + String key, String path, Image defaultvalue) { + return set(component, key, (path != null) ? getIcon(path) : defaultvalue); + } + + /** + * + */ + private Image getIcon(Object component, String key, Image defaultvalue) { + Object value = get(component, key); + return (value == null) ? defaultvalue : (Image) value; + } + + /** + * + */ + private boolean setBoolean(Object component, + String key, boolean value, boolean defaultvalue) { + return set(component, key, (value == defaultvalue) ? null : + (value ? Boolean.TRUE : Boolean.FALSE)); + } + + /** + * + */ + private boolean getBoolean(Object component, + String key, boolean defaultvalue) { + Object value = get(component, key); + return (value == null) ? defaultvalue : ((Boolean) value).booleanValue(); + } + + /** + * + */ + private boolean setInteger(Object component, + String key, int value, int defaultvalue) { + return set(component, key, (value == defaultvalue) ? null : new Integer(value)); + } + + /** + * + */ + private int getInteger(Object component, String key, int defaultvalue) { + Object value = get(component, key); + return (value == null) ? defaultvalue : ((Integer) value).intValue(); + } + + /** + * + */ + private void setRectangle(Object component, + String key, int x, int y, int width, int height) { + Rectangle rectangle = getRectangle(component, key); + if (rectangle != null) { + rectangle.x = x; rectangle.y = y; + rectangle.width = width; rectangle.height = height; + } + else { + set(component, key, new Rectangle(x, y, width, height)); //java + //midp set(component, key, new int[] { width, height, x, y }); + } + } + + /** + * + */ + private Rectangle getRectangle(Object component, String key) { + return (Rectangle) get(component, key); //java + //midp return (int[]) get(component, key); + } + + // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + + /** + * + */ + public Image getIcon(String path) { + return getIcon(path, true); + } + + /** + * + */ + public Image getIcon(String path, boolean preload) { + if ((path == null) || (path.length() == 0)) { + return null; + } + Image image = null; //(Image) imagepool.get(path); + //midp try { + //midp image = Image.createImage(path); + //midp } catch (IOException ioe) {} + //java> + try { + image = Toolkit.getDefaultToolkit().getImage(getClass().getResource(path)); + //image = Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource(path)); + } catch (Throwable e) {} + if (image == null) { + try { + InputStream is = getClass().getResourceAsStream(path); + //InputStream is = ClassLoader.getSystemResourceAsStream(path); + if (is != null) { + byte[] data = new byte[is.available()]; + is.read(data, 0, data.length); + image = getToolkit().createImage(data); + is.close(); + } + } catch (Throwable e) {} + } + //if (image == null) { // applet code + // try { + // image = getImage(getCodeBase(), path); + // } catch (Throwable e) {} + //} + if (preload && (image != null)) { + MediaTracker mediatracker = new MediaTracker(this); + mediatracker.addImage(image, 1); + try { + mediatracker.waitForID(1, 50); + } catch (InterruptedException ie) { } + //imagepool.put(path, image); + } + //foo(int)} + * {@link #foo(int)} * {@link #foo()} * {@link #i(int)} */ diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See3.java index f5e465172ba3..121b6bf585e5 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See3.java @@ -1,6 +1,6 @@ class Test { /** - * @see #perform(int) + * @see #perform(int) */ public void i() {} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Vararg.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Vararg.java index 604c85627cc2..5192745c27da 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Vararg.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Vararg.java @@ -1,7 +1,7 @@ public class Test { /** * @see Test#test(String, int...) - * @see Test#test(String, long...) + * @see Test#test(String, long...) **/ void foo() {} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java index 24d1dae563da..fcd58fccc0fc 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java @@ -1,10 +1,10 @@ package pkg; /** - * @see #method(B1.C) - * @see #method(B1.C[][]) - * @see #method(B1.C..) - * @see #method(B1.C[) + * @see #method(B1.C) + * @see #method(B1.C[][]) + * @see #method(B1.C..) + * @see #method(B1.C[) */ class A1 { public void method(B1.C[] c) { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java index f14d2102e2a0..5bbdb484f3c6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java @@ -1,7 +1,7 @@ // "Add Method Body" "true" class a { void f() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java index 36cbcd775bd5..844bc3b1b2ba 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java @@ -1,7 +1,7 @@ // "Add Method Body" "true" class a { String f() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java index 93d757e462dc..6cd2bdc785c6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java @@ -1,7 +1,7 @@ // "Add Method Body" "true" class a { a() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java index 36cbcd775bd5..844bc3b1b2ba 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java @@ -1,7 +1,7 @@ // "Add Method Body" "true" class a { String f() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java index 38d6440e5fc3..709c0645ae5b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java @@ -7,7 +7,7 @@ class Test { class Inner { public Inner(String a) { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java index 06dcc5d95612..8a94eda2675e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java @@ -5,6 +5,6 @@ public class Test { } private void test() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java index 06dcc5d95612..8a94eda2675e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java @@ -5,6 +5,6 @@ public class Test { } private void test() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java index 06dcc5d95612..8a94eda2675e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java @@ -5,6 +5,6 @@ public class Test { } private void test() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java index 4fa03f9052c9..16607155d34b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java @@ -6,6 +6,6 @@ public class Test { } private void test() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java index a795db622a21..ed3f5ed75de0 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java @@ -5,6 +5,6 @@ public class Test { } private void bar(T t1, T t2) { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java index b8ae9abff9a1..0500941b771e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java @@ -5,6 +5,6 @@ public class Test { } private boolean test() { - return false; //To change body of created methods use File | Settings | File Templates. + return false; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java index 721f359ff734..adbac37a0b03 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java @@ -6,6 +6,6 @@ class A { } private String bar() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java index 6c031ec0864d..785fac52e671 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java @@ -8,7 +8,7 @@ public class Test { } private boolean someMethod(Object o) { - return false; //To change body of created methods use File | Settings | File Templates. + return false; //To change body of created methods use File | Settings | File Templates. } }; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java index 4c8e7720ee23..603006986104 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java @@ -10,6 +10,6 @@ class A { } class B { public static void f(Runnable runnable) { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java index 9df64fc0ad6a..750224836f10 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java @@ -5,7 +5,7 @@ public class A { } private static int f() { - return 0; //To change body of created methods use File | Settings | File Templates. + return 0; //To change body of created methods use File | Settings | File Templates. } public A(int i) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java index fe993f4a50ad..163161258c36 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java @@ -1,7 +1,7 @@ // "Create Method 'get'" "true" class Generic { public T get() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java index 1834689ef58d..138b06a54542 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java @@ -4,7 +4,7 @@ interface Int { class A1 implements Int { public void foo(Int c) { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java index 990d292d8d3a..dd4899a82635 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java @@ -8,7 +8,7 @@ class R implements Comparable { class A1 { public T foo() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef.java b/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef.java new file mode 100644 index 000000000000..f807afcfe63c --- /dev/null +++ b/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef.java @@ -0,0 +1,11 @@ +public class RefactorBug { + public static void something(int a, float b) { + } + + /** + * @see #something(int, float) + */ + public static void somethingElse() { + + } +} diff --git a/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef_after.java b/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef_after.java new file mode 100644 index 000000000000..3fb1fc23599d --- /dev/null +++ b/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef_after.java @@ -0,0 +1,11 @@ +public class RefactorBug { + public static void bar(int a, float b) { + } + + /** + * @see #bar(int, float) + */ + public static void somethingElse() { + + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy index 00e1a2a41cf0..fe9ced59cc21 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy @@ -1,3 +1,18 @@ +/* + * 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.codeInsight; @@ -14,7 +29,7 @@ xxx } public void testEmpty() { - doTest '', "txt", '\n' + doTest '', "txt", '' } private void doTest(String before, @NonNls String ext, String after) { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java index fe1994669a27..45277b05641e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java @@ -1,3 +1,18 @@ +/* + * 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.codeInsight.daemon; import com.intellij.codeInsight.daemon.impl.HighlightInfo; @@ -11,17 +26,13 @@ import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.impl.source.tree.injected.JavaConcatenationInjectorManager; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl; import com.intellij.util.ThrowableRunnable; -import org.jetbrains.annotations.NonNls; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.List; public class LightAdvHighlightingPerformanceTest extends LightDaemonAnalyzerTestCase { @@ -74,9 +85,12 @@ public class LightAdvHighlightingPerformanceTest extends LightDaemonAnalyzerTest } } + private String getFilePath(final String suffix) { + return LightAdvHighlightingTest.BASE_PATH + "/" + getTestName(true) + suffix + ".java"; + } + private List doTest(final int maxMillis) throws Exception { - @NonNls String filePath = LightAdvHighlightingTest.BASE_PATH + "/" + getTestName(false) + ".java"; - configureByFile(filePath); + configureByFile(getFilePath("")); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); getFile().getText(); //to load text @@ -92,32 +106,23 @@ public class LightAdvHighlightingPerformanceTest extends LightDaemonAnalyzerTest infos.addAll(h); } }).cpuBound().usesAllCPUCores().assertTiming(); + return DaemonAnalyzerTestCase.filter(infos, HighlightSeverity.ERROR); } - public void testaThinlet() throws Exception { + public void testAThinlet() throws Exception { List errors = doTest(Math.max(10000, 24000 - JobSchedulerImpl.CORES_COUNT * 1000)); - dump("thinlet", errors); - assertEquals(1230, errors.size()); + if (1226 != errors.size()) { + doTest(getFilePath("_hl"), false, false); + fail("Actual: " + errors.size()); + } } - private static void dump(String msg, List errors) { - if (true) return; - Collections.sort(errors, new Comparator() { - @Override - public int compare(HighlightInfo o1, HighlightInfo o2) { - return o1.toString().compareTo(o2.toString()); - } - }); - final String s = StringUtil.join(errors, StringUtil.createToStringFunction(HighlightInfo.class), "\n"); - System.out.println(msg+":\n-----------------------------------------"); - System.out.println(s); - System.out.println("\n--------------------------------------------"); - } - - public void testaClassLoader() throws Exception { + public void testAClassLoader() throws Exception { List errors = doTest(Math.max(1000, 10000 - JobSchedulerImpl.CORES_COUNT * 1000)); - dump("classloader", errors); - assertEquals(178, errors.size()); + if (173 != errors.size()) { + doTest(getFilePath("_hl"), false, false); + fail("Actual: " + errors.size()); + } } } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java index 585216da1f8e..d551d0ea8580 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java @@ -53,6 +53,10 @@ public class RenameMembersInplaceTest extends LightCodeInsightTestCase { public void testClassWithMultipleConstructors() throws Exception { doTestInplaceRename("Bar"); } + + public void testMethodWithJavadocRef() throws Exception { + doTestInplaceRename("bar"); + } public void testConflictingMethodName() throws Exception { try { diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java index 54cf9b45539a..8438576d3790 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java @@ -82,7 +82,7 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa protected void doTestConfiguredFile(boolean checkWarnings, boolean checkInfos, @Nullable String filePath) { getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE); - ExpectedHighlightingData data = new ExpectedHighlightingData(getEditor().getDocument(),checkWarnings, checkInfos); + ExpectedHighlightingData data = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkInfos); checkHighlighting(data, composeLocalPath(filePath)); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java index dbe6eecef318..8070a4a9f556 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java @@ -1,5 +1,6 @@ package org.jetbrains.jps.incremental; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.jps.idea.OwnServiceLoader; import java.util.*; @@ -65,6 +66,10 @@ public class BuilderRegistry { return Collections.unmodifiableList(myModuleLevelBuilders.get(category)); // todo } + public List getAllModuleLevelBuilders() { + return ContainerUtil.concat(myModuleLevelBuilders.values()); + } + public List getProjectLevelBuilders() { return myProjectLevelBuilders; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java new file mode 100644 index 000000000000..8a10c1a2f14e --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java @@ -0,0 +1,109 @@ +package org.jetbrains.jps.incremental; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.Module; +import org.jetbrains.jps.ModuleChunk; +import org.jetbrains.jps.incremental.fs.RootDescriptor; + +import java.io.File; +import java.util.*; + +/** + * @author nik + */ +public class CompilerEncodingConfiguration { + private final Map myFilePathToCharset; + private final ModuleRootsIndex myRootsIndex; + private Map> myModuleCharsetMap; + + public CompilerEncodingConfiguration(Map filePathToCharset, ModuleRootsIndex rootsIndex) { + myFilePathToCharset = filePathToCharset; + myRootsIndex = rootsIndex; + } + + public Map> getModuleCharsetMap() { + if (myModuleCharsetMap == null) { + myModuleCharsetMap = computeModuleCharsetMap(); + } + return myModuleCharsetMap; + } + + private Map> computeModuleCharsetMap() { + final Map> map = new THashMap>(); + final List builders = BuilderRegistry.getInstance().getAllModuleLevelBuilders(); + for (Map.Entry entry : myFilePathToCharset.entrySet()) { + final String filePath = entry.getKey(); + final String charset = entry.getValue(); + File file = new File(FileUtil.toSystemDependentName(filePath)); + if (charset == null || (!file.isDirectory() && !shouldHonorEncodingForCompilation(builders, file))) continue; + + final RootDescriptor rootDescriptor = myRootsIndex.getModuleAndRoot(file); + if (rootDescriptor == null) continue; + + final String module = rootDescriptor.module; + Set set = map.get(module); + if (set == null) { + set = new LinkedHashSet(); + map.put(module, set); + + final File sourceRoot = rootDescriptor.root; + File current = FileUtil.getParentFile(file); + String parentCharset = null; + while (current != null) { + final String currentCharset = myFilePathToCharset.get(FileUtil.toSystemIndependentName(current.getAbsolutePath())); + if (currentCharset != null) { + parentCharset = currentCharset; + } + if (FileUtil.filesEqual(current, sourceRoot)) { + break; + } + current = FileUtil.getParentFile(current); + } + if (parentCharset != null) { + set.add(parentCharset); + } + } + set.add(charset); + } + + return map; + } + + private static boolean shouldHonorEncodingForCompilation(List builders, File file) { + for (ModuleLevelBuilder builder : builders) { + if (builder.shouldHonorFileEncodingForCompilation(file)) { + return true; + } + } + return false; + } + + @Nullable + public String getPreferredModuleChunkEncoding(@NotNull ModuleChunk moduleChunk) { + for (Module module : moduleChunk.getModules()) { + final Set encodings = getModuleCharsetMap().get(module.getName()); + final String encoding = ContainerUtil.getFirstItem(encodings, null); + if (encoding != null) { + return encoding; + } + } + return moduleChunk.getProject().getProjectCharset(); + } + + @NotNull + public Set getAllModuleChunkEncodings(@NotNull ModuleChunk moduleChunk) { + final Map> map = getModuleCharsetMap(); + Set encodings = new HashSet(); + for (Module module : moduleChunk.getModules()) { + final Set moduleEncodings = map.get(module.getName()); + if (moduleEncodings != null) { + encodings.addAll(moduleEncodings); + } + } + return encodings; + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index dc99c6ca0217..0d84546cf4f3 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -221,31 +221,6 @@ public class IncProjectBuilder { context.processMessage(new ProgressMessage("Running 'after' tasks")); runTasks(context, myBuilderRegistry.getAfterTasks()); - final JavaBuilderLogger logger = context.getLoggingManager().getJavaBuilderLogger(); - - if (logger.isEnabled()) { - final File flag = new File(Utils.getSystemRoot() + File.separator + "dumpSnapshot"); - - if (flag.exists()) { - final Mappings mappings = myProjectDescriptor.dataManager.getMappings(); - final String fileName = - Utils.getSystemRoot() + File.separator + "snapshot-" + new SimpleDateFormat("dd-MM-yy(hh:mm:ss)").format(new Date()) + ".log"; - - try { - final PrintStream stream = new PrintStream(fileName); - - stream.println("Mappings:"); - mappings.toStream(stream); - stream.println("End Of Mappings"); - - stream.close(); - } - catch (FileNotFoundException e) { - e.printStackTrace(); - } - } - } - context.processMessage(new ProgressMessage("Finished, saving caches...")); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java index 014c9ff487f3..f480fde5b38f 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java @@ -41,6 +41,10 @@ public abstract class ModuleLevelBuilder extends Builder { public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException; + public boolean shouldHonorFileEncodingForCompilation(File file) { + return false; + } + public final BuilderCategory getCategory() { return myCategory; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 38f7516f288c..635a2edb3e9e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -38,7 +38,8 @@ import org.jetbrains.jps.incremental.storage.BuildDataManager; import org.jetbrains.jps.incremental.storage.SourceToFormMapping; import org.jetbrains.jps.javac.*; -import javax.tools.*; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; import java.io.*; import java.net.MalformedURLException; import java.net.ServerSocket; @@ -223,6 +224,11 @@ public class JavaBuilder extends ModuleLevelBuilder { } } + @Override + public boolean shouldHonorFileEncodingForCompilation(File file) { + return JAVA_SOURCES_FILTER.accept(file) || FORM_SOURCES_FILTER.accept(file); + } + @Nullable private static File getBoundSource(File srcRoot, File formFile) throws IOException { final String boundClassName = FormsParsing.readBoundClassName(formFile); @@ -484,20 +490,22 @@ public class JavaBuilder extends ModuleLevelBuilder { } private static int convertToNumber(final String ver) { - final String prefix = "1."; - if (ver.startsWith(prefix)) { - final String versionNumberString; - final int dotIndex = ver.indexOf(".", prefix.length()); - if (dotIndex > 0) { - versionNumberString = ver.substring(prefix.length(), dotIndex); - } - else { - versionNumberString = ver.substring(prefix.length()); - } - try { - return Integer.parseInt(versionNumberString); - } - catch (NumberFormatException ignored) { + if (ver != null) { + final String prefix = "1."; + if (ver.startsWith(prefix)) { + final String versionNumberString; + final int dotIndex = ver.indexOf(".", prefix.length()); + if (dotIndex > 0) { + versionNumberString = ver.substring(prefix.length(), dotIndex); + } + else { + versionNumberString = ver.substring(prefix.length()); + } + try { + return Integer.parseInt(versionNumberString); + } + catch (NumberFormatException ignored) { + } } } return 0; @@ -579,7 +587,7 @@ public class JavaBuilder extends ModuleLevelBuilder { private static List getCompilationVMOptions(CompileContext context) { List cached = JAVAC_VM_OPTIONS.get(context); if (cached == null) { - loadJavacOptions(context); + loadCommonJavacOptions(context); cached = JAVAC_VM_OPTIONS.get(context); } return cached; @@ -588,10 +596,28 @@ public class JavaBuilder extends ModuleLevelBuilder { private static List getCompilationOptions(CompileContext context, ModuleChunk chunk) { List cached = JAVAC_OPTIONS.get(context); if (cached == null) { - loadJavacOptions(context); + loadCommonJavacOptions(context); cached = JAVAC_OPTIONS.get(context); } + final List options = new ArrayList(cached); + if (!isEncodingSet(options)) { + final CompilerEncodingConfiguration config = context.getProjectDescriptor().getEncodingConfiguration(); + final String encoding = config.getPreferredModuleChunkEncoding(chunk); + if (config.getAllModuleChunkEncodings(chunk).size() > 1) { + final StringBuilder msgBuilder = new StringBuilder(); + msgBuilder.append("Multiple encodings set for module chunk ").append(getChunkPresentableName(chunk)); + if (encoding != null) { + msgBuilder.append("\n\"").append(encoding).append("\" will be used by compiler"); + } + context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, msgBuilder.toString())); + } + if (encoding != null) { + options.add("-encoding"); + options.add(encoding); + } + } + final String langlevel = chunk.getModules().iterator().next().getLanguageLevel(); if (!StringUtil.isEmpty(langlevel)) { options.add("-source"); @@ -639,6 +665,16 @@ public class JavaBuilder extends ModuleLevelBuilder { return options; } + private static boolean isEncodingSet(List options) { + for (String option : options) { + if ("-encoding".equals(option)) { + return true; + } + } + return false; + } + + private static int getCompilerSdkVersion(CompileContext context) { final Integer cached = JAVA_COMPILER_VERSION_KEY.get(context); if (cached != null) { @@ -668,7 +704,7 @@ public class JavaBuilder extends ModuleLevelBuilder { return config.getProjectBytecodeTarget(); } - private static void loadJavacOptions(CompileContext context) { + private static void loadCommonJavacOptions(CompileContext context) { final List options = new ArrayList(); final List vmOptions = new ArrayList(); @@ -689,7 +725,6 @@ public class JavaBuilder extends ModuleLevelBuilder { } final String customArgs = javacOpts.get("ADDITIONAL_OPTIONS_STRING"); - boolean isEncodingSet = false; if (customArgs != null) { final StringTokenizer tokenizer = new StringTokenizer(customArgs, " \t\r\n"); while (tokenizer.hasMoreTokens()) { @@ -703,17 +738,9 @@ public class JavaBuilder extends ModuleLevelBuilder { else { options.add(token); } - if ("-encoding".equals(token)) { - isEncodingSet = true; - } } } - if (!isEncodingSet && !StringUtil.isEmpty(project.getProjectCharset())) { - options.add("-encoding"); - options.add(project.getProjectCharset()); - } - JAVAC_OPTIONS.set(context, options); JAVAC_VM_OPTIONS.set(context, vmOptions); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java index e62b7c878921..c0fa5acbc087 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java +++ b/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java @@ -5,6 +5,7 @@ import org.jetbrains.jps.Module; import org.jetbrains.jps.Project; import org.jetbrains.jps.Sdk; import org.jetbrains.jps.incremental.BuildLoggingManager; +import org.jetbrains.jps.incremental.CompilerEncodingConfiguration; import org.jetbrains.jps.incremental.ModuleRootsIndex; import org.jetbrains.jps.incremental.fs.BuildFSState; import org.jetbrains.jps.incremental.storage.BuildDataManager; @@ -27,6 +28,7 @@ public final class ProjectDescriptor { public ModuleRootsIndex rootsIndex; private int myUseCounter = 1; private Set myProjectJavaSdks; + private CompilerEncodingConfiguration myEncodingConfiguration; public ProjectDescriptor(Project project, BuildFSState fsState, @@ -40,6 +42,7 @@ public final class ProjectDescriptor { myLoggingManager = loggingManager; this.rootsIndex = new ModuleRootsIndex(project); myProjectJavaSdks = new HashSet(); + myEncodingConfiguration = new CompilerEncodingConfiguration(project.getFilePathToCharset(), rootsIndex); for (Module module : project.getModules().values()) { final Sdk sdk = module.getSdk(); if (sdk instanceof JavaSdk && !myProjectJavaSdks.contains(sdk)) { @@ -51,6 +54,10 @@ public final class ProjectDescriptor { } } + public CompilerEncodingConfiguration getEncodingConfiguration() { + return myEncodingConfiguration; + } + public Set getProjectJavaSdks() { return myProjectJavaSdks; } diff --git a/jps/model/src/org/jetbrains/jps/Project.groovy b/jps/model/src/org/jetbrains/jps/Project.groovy index d08da5c5ed64..bc330008cf39 100644 --- a/jps/model/src/org/jetbrains/jps/Project.groovy +++ b/jps/model/src/org/jetbrains/jps/Project.groovy @@ -22,6 +22,7 @@ class Project { final IgnoredFilePatterns ignoredFilePatterns = new IgnoredFilePatterns() String projectCharset; // contains project charset, if not specified default charset will be used (used by compilers) + Map filePathToCharset = [:]; def Project() { } diff --git a/jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy b/jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy index 697e3ac7e1bc..897f5fd9c47e 100644 --- a/jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy +++ b/jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy @@ -30,7 +30,7 @@ class FacetLoader { } } - private static FacetTypeService findFacetType(String typeId) { + private static synchronized FacetTypeService findFacetType(String typeId) { if (facetTypes == null) { facetTypes = [:] facetTypeLoader.each {FacetTypeService type -> diff --git a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy index a500b889211d..d40e9cc91e9b 100644 --- a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy +++ b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy @@ -340,6 +340,10 @@ public class IdeaProjectLoader { if ("PROJECT".equals(url)) { project.projectCharset = charset; } + else { + def path = projectMacroExpander.expandMacros(IdeaProjectLoadingUtil.pathFromUrl(url)); + project.filePathToCharset[path] = charset; + } } } diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index bdedb7ec2194..8e14a3bb733d 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -24,6 +24,7 @@ import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressIndicatorProvider; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.UserDataHolderBase; @@ -40,8 +41,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import org.picocontainer.*; +import org.picocontainer.defaults.*; import org.picocontainer.defaults.CachingComponentAdapter; -import org.picocontainer.defaults.ConstructorInjectionComponentAdapter; import java.lang.reflect.Array; import java.util.ArrayList; @@ -443,13 +444,14 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements try { final Class interfaceClass = Class.forName(config.getInterfaceClass(), true, loader); - final Class implementationClass = Class.forName(config.getImplementationClass(), true, loader); + final Class implementationClass = Comparing.equal(config.getInterfaceClass(), config.getImplementationClass()) ? + interfaceClass : Class.forName(config.getImplementationClass(), true, loader); if (myInterfaceToClassMap.get(interfaceClass) != null) { throw new Error("ComponentSetup for component " + interfaceClass.getName() + " already registered"); } - getPicoContainer().registerComponent(new ComponentConfigComponentAdapter(config)); + getPicoContainer().registerComponent(new ComponentConfigComponentAdapter(config, implementationClass)); myInterfaceToClassMap.put(interfaceClass, implementationClass); myComponentClassToConfig.put(implementationClass, config); myComponentInterfaces.add(interfaceClass); @@ -559,12 +561,57 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements private class ComponentConfigComponentAdapter implements ComponentAdapter { private final ComponentConfig myConfig; - private ComponentAdapter myDelegate; + private final ComponentAdapter myDelegate; private boolean myInitialized = false; private boolean myInitializing = false; - public ComponentConfigComponentAdapter(final ComponentConfig config) { + public ComponentConfigComponentAdapter(final ComponentConfig config, Class implementationClass) { myConfig = config; + final String componentKey = config.getInterfaceClass(); + myDelegate = new CachingComponentAdapter(new ConstructorInjectionComponentAdapter(componentKey, implementationClass, null, true)) { + @Override + public Object getComponentInstance(PicoContainer picoContainer) throws PicoInitializationException, PicoIntrospectionException { + Object componentInstance = null; + try { + long startTime = myInitialized ? 0 : System.nanoTime(); + componentInstance = super.getComponentInstance(picoContainer); + + if (!myInitialized) { + if (myInitializing) { + if (myConfig.pluginDescriptor != null) { + LOG.error(new PluginException("Cyclic component initialization: " + componentKey, myConfig.pluginDescriptor.getPluginId())); + } + else { + LOG.error(new Throwable("Cyclic component initialization: " + componentKey)); + } + } + myInitializing = true; + myComponentsRegistry.registerComponentInstance(componentInstance); + initComponent(componentInstance); + long endTime = System.nanoTime(); + long ms = (endTime - startTime) / 1000000; + if (ms > 10) { + if (logSlowComponents()) { + LOG.info(componentInstance.getClass().getName() + " initialized in " + ms + " ms"); + } + } + myInitializing = false; + myInitialized = true; + } + } + catch (ProcessCanceledException e) { + throw e; + } + catch (StateStorageException e) { + throw e; + } + catch (Throwable t) { + handleInitComponentError(t, componentInstance == null, componentKey); + } + return componentInstance; + } + }; + } @Override @@ -594,92 +641,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements } private ComponentAdapter getDelegate() { - if (myDelegate == null) { - final Object componentKey = getComponentKey(); - - ClassLoader loader = myConfig.getClassLoader(); - - Class implementationClass = null; - - try { - implementationClass = Class.forName(myConfig.getImplementationClass(), true, loader); - } - catch (Exception e) { - @NonNls final String message = "Error while registering component: " + myConfig; - - if (myConfig.pluginDescriptor != null) { - LOG.error(message, new PluginException(e, myConfig.pluginDescriptor.getPluginId())); - } - else { - LOG.error(message, e); - } - } - catch (Error e) { - if (myConfig.pluginDescriptor != null) { - LOG.error(new PluginException(e, myConfig.pluginDescriptor.getPluginId())); - } - else { - throw e; - } - } - - assert implementationClass != null; - - myDelegate = new CachingComponentAdapter(new ConstructorInjectionComponentAdapter(componentKey, implementationClass, null, true)) { - @Override - public Object getComponentInstance(PicoContainer picoContainer) throws PicoInitializationException, PicoIntrospectionException { - Object componentInstance = null; - try { - long startTime = myInitialized ? 0 : System.nanoTime(); - componentInstance = super.getComponentInstance(picoContainer); - - if (!myInitialized) { - if (myInitializing) { - if (myConfig.pluginDescriptor != null) { - LOG.error(new PluginException("Cyclic component initialization: " + componentKey, myConfig.pluginDescriptor.getPluginId())); - } - else { - LOG.error(new Throwable("Cyclic component initialization: " + componentKey)); - } - } - myInitializing = true; - myComponentsRegistry.registerComponentInstance(componentInstance); - initComponent(componentInstance); - long endTime = System.nanoTime(); - long ms = (endTime - startTime) / 1000000; - if (ms > 10) { - if (logSlowComponents()) { - LOG.info(componentInstance.getClass().getName() + " initialized in " + ms + " ms"); - } - } - myInitializing = false; - myInitialized = true; - } - } - catch (ProcessCanceledException e) { - throw e; - } - catch (StateStorageException e) { - throw e; - } - catch (Throwable t) { - handleInitComponentError(t, componentInstance == null, componentKey.toString()); - } - return componentInstance; - } - }; - } - return myDelegate; } } - - public final int hashCode() { - return super.hashCode(); - } - - @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"}) - public final boolean equals(Object obj) { - return super.equals(obj); - } } diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java new file mode 100644 index 000000000000..9e760fb751be --- /dev/null +++ b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java @@ -0,0 +1,44 @@ +/* + * 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.ui.popup.util; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 5/9/12 + * Time: 5:34 AM + * To change this template use File | Settings | File Templates. + */ +public interface DetailView { + void updateWithItem(ItemWrapper wrapper); + + Editor getEditor(); + + void navigateInPreviewEditor(VirtualFile file, LogicalPosition positionToNavigate); + + JPanel getDetailPanel(); + + void setDetailPanel(@Nullable JPanel panel); + + void clearEditor(); +} diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java new file mode 100644 index 000000000000..6fffcc017028 --- /dev/null +++ b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java @@ -0,0 +1,48 @@ +/* + * 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.ui.popup.util; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.ui.ColoredListCellRenderer; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:05 AM +* To change this template use File | Settings | File Templates. +*/ +public interface ItemWrapper { + void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected); + void updateMnemonicLabel(JLabel label); + + void execute(Project project, JBPopup popup); + + String speedSearchText(); + + @Nullable + String footerText(); + + void updateDetailView(DetailView panel); + + boolean allowedToRemove(); + + void removed(Project project); +} diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java b/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java new file mode 100644 index 000000000000..c4e1917bc439 --- /dev/null +++ b/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java @@ -0,0 +1,82 @@ +/* + * 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.ui.popup.util; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.ui.ColoredListCellRenderer; + +import javax.swing.*; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 11.05.12 + * Time: 21:55 + * To change this template use File | Settings | File Templates. + */ +public class SplitterItem implements ItemWrapper { + + private String myText; + + public SplitterItem(String text) { + myText = text; + } + + public String getText() { + return myText; + } + + @Override + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void updateMnemonicLabel(JLabel label) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void execute(Project project, JBPopup popup) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String speedSearchText() { + return ""; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String footerText() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void updateDetailView(DetailView panel) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean allowedToRemove() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void removed(Project project) { + //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/platform/lang-impl/src/com/intellij/analysis/BaseAnalysisActionDialog.java b/platform/lang-impl/src/com/intellij/analysis/BaseAnalysisActionDialog.java index d6948196e6a1..9c503fd61774 100644 --- a/platform/lang-impl/src/com/intellij/analysis/BaseAnalysisActionDialog.java +++ b/platform/lang-impl/src/com/intellij/analysis/BaseAnalysisActionDialog.java @@ -90,7 +90,7 @@ public class BaseAnalysisActionDialog extends DialogWrapper { myAnalysisOptions.ANALYZE_TEST_SOURCES = scope.isAnalyzeTestsByDefault(); } myProject = project; - myFileName = scope.getShortenName(); + myFileName = scope.getScopeType() == AnalysisScope.PROJECT || scope.getScopeType() == AnalysisScope.MODULE ? null : scope.getShortenName(); myModuleName = moduleName; myRememberScope = rememberScope; myAnalysisNoon = analysisNoon; @@ -141,8 +141,12 @@ public class BaseAnalysisActionDialog extends DialogWrapper { myChangeLists.setVisible(hasVCS); //file/package/directory/module scope - myFileButton.setText(myFileName); - myFileButton.setMnemonic(myFileName.charAt(getSelectedScopeMnemonic())); + if (myFileName != null) { + myFileButton.setText(myFileName); + myFileButton.setMnemonic(myFileName.charAt(getSelectedScopeMnemonic())); + } else { + myFileButton.setVisible(false); + } VirtualFile file = PsiUtilBase.getVirtualFile(myContext); ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); @@ -165,9 +169,10 @@ public class BaseAnalysisActionDialog extends DialogWrapper { myScopeCombo.init(myProject, searchInLib, true, preselect); //correct selection - myProjectButton.setSelected(myRememberScope && myAnalysisOptions.SCOPE_TYPE == AnalysisScope.PROJECT); - myFileButton.setSelected(!myRememberScope || - myAnalysisOptions.SCOPE_TYPE != AnalysisScope.PROJECT && !useModuleScope && myAnalysisOptions.SCOPE_TYPE != AnalysisScope.CUSTOM && !useUncommitedFiles); + myProjectButton.setSelected(myRememberScope && myAnalysisOptions.SCOPE_TYPE == AnalysisScope.PROJECT || myFileName == null); + myFileButton.setSelected(myFileName != null && + (!myRememberScope || + myAnalysisOptions.SCOPE_TYPE != AnalysisScope.PROJECT && !useModuleScope && myAnalysisOptions.SCOPE_TYPE != AnalysisScope.CUSTOM && !useUncommitedFiles)); myScopeCombo.setEnabled(myCustomScopeButton.isSelected()); diff --git a/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java index 27625060354f..e00ecc273227 100644 --- a/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java +++ b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java @@ -165,7 +165,7 @@ public class InitialConfigurationDialog extends DialogWrapper { private void createUIComponents() { myColorPreviewPanel = new AbstractTitledSeparatorWithIcon(IconLoader.getIcon("/general/comboArrowRight.png"), IconLoader.getIcon("/general/comboArrowDown.png"), - "Click to preview", true, false) { + "Click to preview") { private int myAddedWidth; diff --git a/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java b/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java index 13a16c6fd8f2..d1ffbf31d23d 100644 --- a/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java +++ b/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java @@ -65,6 +65,8 @@ public abstract class RunManagerEx extends RunManager { @NotNull public abstract List getBeforeRunTasks(RunConfiguration settings); + public abstract void setBeforeRunTasks(RunConfiguration runConfiguration, List tasks, boolean addEnabledTemplateTasksIfAbsent); + @NotNull public abstract List getBeforeRunTasks(RunConfiguration settings, Key taskProviderID); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java index cc09148e22af..2b9637df0b3e 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java @@ -256,7 +256,6 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, checkRecentsLimit(); mySharedConfigurations.put(newId, shared); - getTemplateBeforeRunTask(configuration); setBeforeRunTasks(configuration, tasks, addEnabledTemplateTasksIfAbsent); if (existingSettings == settings) { @@ -830,10 +829,10 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, if (tasks != null) { return getCopies(tasks); } - return getTemplateBeforeRunTask(settings); + return getTemplateBeforeRunTasks(settings); } - private List getTemplateBeforeRunTask(RunConfiguration settings) { + private List getTemplateBeforeRunTasks(RunConfiguration settings) { final RunnerAndConfigurationSettings template = getConfigurationTemplate(settings.getFactory()); final List templateTasks = myConfigurationToBeforeTasksMap.get(template.getConfiguration()); if (templateTasks != null) { @@ -879,7 +878,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, public final void setBeforeRunTasks(final RunConfiguration runConfiguration, @NotNull List tasks, boolean addEnabledTemplateTasksIfAbsent) { List result = new ArrayList(tasks); if (addEnabledTemplateTasksIfAbsent) { - List templates = getTemplateBeforeRunTask(runConfiguration); + List templates = getTemplateBeforeRunTasks(runConfiguration); Set> idsToSet = new HashSet>(); for (BeforeRunTask task : tasks) { idsToSet.add(task.getProviderId()); @@ -902,7 +901,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, } public void addConfiguration(final RunnerAndConfigurationSettings settings, final boolean isShared) { - addConfiguration(settings, isShared, new ArrayList(), false); + addConfiguration(settings, isShared, getTemplateBeforeRunTasks(settings.getConfiguration()), false); } public static RunManagerImpl getInstanceImpl(final Project project) { diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java index 70beed4ea9a2..e7e923128667 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java @@ -53,10 +53,6 @@ public class @Override protected void paintLastGhost(Graphics2D g2d) {} - public boolean isGhostsAlwaysVisible() { - return false; - } - protected void doPaintInactive(Graphics2D g2d, boolean leftGhostExists, TabLabel label, diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index b3519b762f96..1b6198e808e6 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -258,7 +258,10 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac Disposer.register((Disposable)myRunnerUi, manager); manager.getComponent(); } else { - DockManager.getInstance(myProject).register(this); + final DockManager dockManager = DockManager.getInstance(myProject); + if (dockManager != null) { //default project + dockManager.register(this); + } } } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java new file mode 100644 index 000000000000..621e50bb4da5 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java @@ -0,0 +1,131 @@ +/* + * 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.ide.bookmarks; + +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.markup.EffectType; +import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.openapi.vcs.FileStatusManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.FileColorManager; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.ui.popup.util.ItemWrapper; + +import javax.swing.*; +import java.awt.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:06 AM +* To change this template use File | Settings | File Templates. +*/ +public class BookmarkItem implements ItemWrapper { + private final Bookmark myBookmark; + + public BookmarkItem(Bookmark bookmark) { + myBookmark = bookmark; + } + + public Bookmark getBookmark() { + return myBookmark; + } + + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + VirtualFile file = myBookmark.getFile(); + + PsiManager psiManager = PsiManager.getInstance(project); + + PsiElement fileOrDir = file.isDirectory() ? psiManager.findDirectory(file) : psiManager.findFile(file); + if (fileOrDir != null) { + renderer.setIcon(fileOrDir.getIcon(Iconable.ICON_FLAG_CLOSED)); + } + + + FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(file); + TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); + renderer.append(file.getName(), SimpleTextAttributes.fromTextAttributes(attributes)); + if (myBookmark.getLine() >= 0) { + renderer.append(":", SimpleTextAttributes.GRAYED_ATTRIBUTES); + renderer.append(String.valueOf(myBookmark.getLine() + 1), SimpleTextAttributes.GRAYED_ATTRIBUTES); + } + + if (!selected) { + FileColorManager colorManager = FileColorManager.getInstance(project); + if (fileOrDir instanceof PsiFile) { + Color color = colorManager.getRendererBackground((PsiFile)fileOrDir); + if (color != null) { + renderer.setBackground(color); + } + } + } + + String description = myBookmark.getDescription(); + if (description != null) { + renderer.append(" " + description, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); + } + } + + public void updateMnemonicLabel(JLabel label) { + final char mnemonic = myBookmark.getMnemonic(); + if (mnemonic != 0) { + label.setText(Character.toString(mnemonic) + '.'); + } + else { + label.setText(""); + } + } + + public String speedSearchText() { + return myBookmark.getFile().getName() + " " + myBookmark.getDescription(); + } + + public void execute(Project project, JBPopup popup) { + myBookmark.navigate(); + } + + public String footerText() { + return myBookmark.getFile().getPresentableUrl(); + } + + @Override + public void updateDetailView(final DetailView panel) { + VirtualFile file = myBookmark.getFile(); + LogicalPosition positionToNavigate = new LogicalPosition(myBookmark.getLine(), 0); + + panel.navigateInPreviewEditor(file, positionToNavigate); + } + + @Override + public boolean allowedToRemove() { + return true; + } + + @Override + public void removed(Project project) { + BookmarkManager.getInstance(project).removeBookmark(getBookmark()); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java index 53c9d8c4e43a..c69805161528 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java @@ -20,58 +20,30 @@ package com.intellij.ide.bookmarks.actions; import com.intellij.ide.bookmarks.Bookmark; +import com.intellij.ide.bookmarks.BookmarkItem; import com.intellij.ide.bookmarks.BookmarkManager; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.highlighter.EditorHighlighter; -import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; -import com.intellij.openapi.editor.markup.EffectType; -import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.InputValidator; -import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.ui.popup.PopupChooserBuilder; -import com.intellij.openapi.util.IconLoader; -import com.intellij.openapi.util.Iconable; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; -import com.intellij.ui.*; import com.intellij.ui.components.JBList; +import com.intellij.ui.popup.util.MasterDetailPopupBuilder; import com.intellij.ui.speedSearch.FilteringListModel; -import com.intellij.util.Alarm; -import com.intellij.util.Function; -import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import java.awt.*; -import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; -import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; // TODO: remove duplication with BaseShowRecentFilesAction, there's quite a bit of it -public class BookmarksAction extends AnAction implements DumbAware { - private static final Color BORDER_COLOR = Gray._135; - - private final Alarm myPreviewUpdateAlarm = new Alarm(); +public class BookmarksAction extends AnAction implements DumbAware, MasterDetailPopupBuilder.Delegate { @Override public void update(AnActionEvent e) { @@ -89,177 +61,44 @@ public class BookmarksAction extends AnAction implements DumbAware { final DefaultListModel model = buildModel(project); - - final JLabel pathLabel = new JLabel(" "); - pathLabel.setHorizontalAlignment(SwingConstants.RIGHT); - - final Font font = pathLabel.getFont(); - pathLabel.setFont(font.deriveFont((float)10)); - final JBList list = new JBList(model); list.getEmptyText().setText("No Bookmarks"); - final PreviewPanel previewPanel = new PreviewPanel(project); - - list.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - private String getTitle2Text(String fullText) { - int labelWidth = pathLabel.getWidth(); - if (fullText == null || fullText.length() == 0) return " "; - while (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) { - int sep = fullText.indexOf(File.separatorChar, 4); - if (sep < 0) return fullText; - fullText = "..." + fullText.substring(sep); - } - - return fullText; - } - - public void valueChanged(final ListSelectionEvent e) { - //noinspection SSBasedInspection - SwingUtilities.invokeLater(new Runnable() { - public void run() { - updatePathLabel(); - } - }); - } - - private void updatePreviewPanel(final ItemWrapper wrapper) { - myPreviewUpdateAlarm.cancelAllRequests(); - myPreviewUpdateAlarm.addRequest(new Runnable() { - public void run() { - previewPanel.updateWithItem(wrapper); - } - }, 300); - } - - private void updatePathLabel() { - final Object[] values = list.getSelectedValues(); - if (values != null && values.length == 1) { - ItemWrapper wrapper = (ItemWrapper)values[0]; - pathLabel.setText(getTitle2Text(wrapper.footerText())); - updatePreviewPanel(wrapper); - } - else { - updatePreviewPanel(null); - pathLabel.setText(" "); - } - } - }); - - Runnable runnable = new Runnable() { - public void run() { - IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() { - public void run() { - Object[] values = list.getSelectedValues(); - - if (values.length == 1) { - ((ItemWrapper)values[0]).execute(project); - } - else { - for (Object value : values) { - if (value instanceof BookmarkItem) { - ((BookmarkItem)value).execute(project); - } - } - } - } - }); - } - }; - - if (list.getModel().getSize() == 0) { - list.clearSelection(); - } - - list.setCellRenderer(new ItemRenderer(project)); - - - JPanel footerPanel = new JPanel(new BorderLayout()) { - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - g.setColor(BORDER_COLOR); - g.drawLine(0, 0, getWidth(), 0); - } - }; - - footerPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); - footerPanel.add(pathLabel); - - DefaultActionGroup actions = new DefaultActionGroup(); EditBookmarkDescriptionAction editDescriptionAction = new EditBookmarkDescriptionAction(project, list); + DefaultActionGroup actions = new DefaultActionGroup(); actions.add(editDescriptionAction); actions.add(new DeleteBookmarkAction(project, list)); actions.add(new MoveBookmarkUpAction(project, list)); actions.add(new MoveBookmarkDownAction(project, list)); - ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("", actions, true); - actionToolbar.setReservePlaceAutoPopupIcon(false); - actionToolbar.setMinimumButtonSize(new Dimension(20, 20)); - final JComponent toolBar = actionToolbar.getComponent(); - toolBar.setOpaque(false); - - final JBPopup popup = new PopupChooserBuilder(list). - setTitle("Bookmarks"). - setMovable(true). - setAutoselectOnMouseMove(false). - setSettingButton(toolBar). - setSouthComponent(footerPanel). - setEastComponent(previewPanel). - setItemChoosenCallback(runnable). - setMayBeParent(true). - setFilteringEnabled(new Function() { - public String fun(Object o) { - return ((ItemWrapper)o).speedSearchText(); - } - }).createPopup(); - - list.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_DELETE) { - int index = list.getSelectedIndex(); - if (index == -1 || index >= list.getModel().getSize()) { - return; - } - Object[] values = list.getSelectedValues(); - for (Object value : values) { - if (value instanceof BookmarkItem) { - BookmarkItem item = (BookmarkItem)value; - model.removeElement(item); - if (model.getSize() > 0) { - if (model.getSize() == index) { - list.setSelectedIndex(model.getSize() - 1); - } - else if (model.getSize() > index) { - list.setSelectedIndex(index); - } - } - else { - list.clearSelection(); - } - BookmarkManager.getInstance(project).removeBookmark(item.myBookmark); - } - } - } - else if (e.getModifiersEx() == 0) { - char mnemonic = e.getKeyChar(); - final Bookmark bookmark = BookmarkManager.getInstance(project).findBookmarkForMnemonic(mnemonic); - if (bookmark != null) { - popup.cancel(); - IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() { - public void run() { - bookmark.navigate(); - } - }); - } - } - } - }); + final JBPopup popup = new MasterDetailPopupBuilder(project). + setActionsGroup(actions). + setList(list). + setDelegate(this).createMasterDetailPopup(); editDescriptionAction.setPopup(popup); popup.showCenteredInCurrentWindow(project); } + @Override + public String getTitle() { + return "Bookmarks"; + } + + @Override + public void handleMnemonic(KeyEvent e, Project project, JBPopup popup) { + char mnemonic = e.getKeyChar(); + final Bookmark bookmark = BookmarkManager.getInstance(project).findBookmarkForMnemonic(mnemonic); + if (bookmark != null) { + popup.cancel(); + IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() { + public void run() { + bookmark.navigate(); + } + }); + } + } + private static DefaultListModel buildModel(Project project) { final DefaultListModel model = new DefaultListModel(); @@ -270,157 +109,8 @@ public class BookmarksAction extends AnAction implements DumbAware { return model; } - private interface ItemWrapper { - void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected); - void updateMnemonicLabel(JLabel label); - - void execute(Project project); - - String speedSearchText(); - - @Nullable - String footerText(); - - void updatePreviewPanel(PreviewPanel panel); - } - - private static class BookmarkItem implements ItemWrapper { - private final Bookmark myBookmark; - - private BookmarkItem(Bookmark bookmark) { - myBookmark = bookmark; - } - - public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { - VirtualFile file = myBookmark.getFile(); - - PsiManager psiManager = PsiManager.getInstance(project); - - PsiElement fileOrDir = file.isDirectory() ? psiManager.findDirectory(file) : psiManager.findFile(file); - if (fileOrDir != null) { - renderer.setIcon(fileOrDir.getIcon(Iconable.ICON_FLAG_CLOSED)); - } - - - FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(file); - TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); - renderer.append(file.getName(), SimpleTextAttributes.fromTextAttributes(attributes)); - if (myBookmark.getLine() >= 0) { - renderer.append(":", SimpleTextAttributes.GRAYED_ATTRIBUTES); - renderer.append(String.valueOf(myBookmark.getLine() + 1), SimpleTextAttributes.GRAYED_ATTRIBUTES); - } - - if (!selected) { - FileColorManager colorManager = FileColorManager.getInstance(project); - if (fileOrDir instanceof PsiFile) { - Color color = colorManager.getRendererBackground((PsiFile)fileOrDir); - if (color != null) { - renderer.setBackground(color); - } - } - } - - String description = myBookmark.getDescription(); - if (description != null) { - renderer.append(" " + description, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); - } - } - - public void updateMnemonicLabel(JLabel label) { - final char mnemonic = myBookmark.getMnemonic(); - if (mnemonic != 0) { - label.setText(Character.toString(mnemonic) + '.'); - } - else { - label.setText(""); - } - } - - public String speedSearchText() { - return myBookmark.getFile().getName() + " " + myBookmark.getDescription(); - } - - public void execute(Project project) { - myBookmark.navigate(); - } - - public String footerText() { - return myBookmark.getFile().getPresentableUrl(); - } - - public void updatePreviewPanel(final PreviewPanel panel) { - VirtualFile file = myBookmark.getFile(); - Document document = FileDocumentManager.getInstance().getDocument(file); - Project project = panel.myProject; - - if (document != null) { - if (panel.myEditor == null || panel.myEditor.getDocument() != document) { - panel.cleanup(); - panel.myEditor = EditorFactory.getInstance().createViewer(document, project); - EditorHighlighter highlighter = EditorHighlighterFactory.getInstance() - .createEditorHighlighter(file, EditorColorsManager.getInstance().getGlobalScheme(), project); - ((EditorEx)panel.myEditor).setHighlighter(highlighter); - ((EditorEx)panel.myEditor).setFile(file); - - panel.myEditor.getSettings().setAnimatedScrolling(false); - panel.myEditor.getSettings().setRefrainFromScrolling(false); - panel.myEditor.getSettings().setLineNumbersShown(true); - panel.myEditor.getSettings().setFoldingOutlineShown(false); - - panel.add(panel.myEditor.getComponent(), BorderLayout.CENTER); - } - - panel.myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(myBookmark.getLine(), 0)); - panel.validate(); - panel.myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); - } - else { - panel.cleanup(); - - JLabel label = new JLabel("Navigate to selected " + (file.isDirectory() ? "directory " : "file ") + "in Project View"); - label.setHorizontalAlignment(JLabel.CENTER); - panel.add(label); - } - } - } - - private static class ItemRenderer extends JPanel implements ListCellRenderer { - private final Project myProject; - private final ColoredListCellRenderer myRenderer; - - private ItemRenderer(Project project) { - super(new BorderLayout()); - myProject = project; - - setBackground(UIUtil.getListBackground()); - - final JLabel label = new JLabel(); - label.setFont(Bookmark.MNEMONIC_FONT); - - label.setPreferredSize(new JLabel("W.").getPreferredSize()); - label.setOpaque(false); - - if (BookmarkManager.getInstance(project).hasBookmarksWithMnemonics()) { - add(label, BorderLayout.WEST); - } - - myRenderer = new ColoredListCellRenderer() { - @Override - protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { - if (value instanceof ItemWrapper) { - final ItemWrapper wrapper = (ItemWrapper)value; - wrapper.setupRenderer(this, myProject, selected); - wrapper.updateMnemonicLabel(label); - } - } - }; - add(myRenderer, BorderLayout.CENTER); - } - - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - myRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - return this; - } + public boolean hasItemsWithMnemonic(Project project) { + return BookmarkManager.getInstance(project).hasBookmarksWithMnemonics(); } protected static class BookmarkInContextInfo { @@ -476,53 +166,12 @@ public class BookmarksAction extends AnAction implements DumbAware { } } - private static class PreviewPanel extends JPanel { - private final Project myProject; - private Editor myEditor; - private ItemWrapper myWrapper; - - public PreviewPanel(Project project) { - super(new BorderLayout()); - myProject = project; - setPreferredSize(new Dimension(600, 400)); - } - - public void updateWithItem(ItemWrapper wrapper) { - if (myWrapper != wrapper) { - myWrapper = wrapper; - if (wrapper != null) { - wrapper.updatePreviewPanel(this); - } - else { - cleanup(); - repaint(); - } - - revalidate(); - } - } - - private void cleanup() { - removeAll(); - if (myEditor != null) { - EditorFactory.getInstance().releaseEditor(myEditor); - myEditor = null; - } - } - - @Override - public void removeNotify() { - super.removeNotify(); - cleanup(); - } - } - - private static List getSelectedBookmarks(JList list) { + static List getSelectedBookmarks(JList list) { List answer = new ArrayList(); for (Object value : list.getSelectedValues()) { if (value instanceof BookmarkItem) { - answer.add(((BookmarkItem)value).myBookmark); + answer.add(((BookmarkItem)value).getBookmark()); } else { return Collections.emptyList(); @@ -532,135 +181,10 @@ public class BookmarksAction extends AnAction implements DumbAware { return answer; } - private static class EditBookmarkDescriptionAction extends AnAction { - private final JList myList; - private final Project myProject; - private JBPopup myPopup; - - private EditBookmarkDescriptionAction(Project project, JList list) { - super("Edit Description", "Assign short description for the bookmark to be shown along the file name", IconLoader.getIcon("/actions/properties.png")); - myProject = project; - myList = list; - registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta ENTER" : "control ENTER")), list); - } - - @Override - public void update(AnActionEvent e) { - e.getPresentation().setEnabled(getSelectedBookmarks(myList).size() == 1); - } - - @Override - public void actionPerformed(AnActionEvent e) { - Bookmark b = getSelectedBookmarks(myList).get(0); - myPopup.setUiVisible(false); - - String description = Messages - .showInputDialog(myProject, "Enter short bookmark description", "Bookmark Description", Messages.getQuestionIcon(), b.getDescription(), - new InputValidator() { - public boolean checkInput(String inputString) { - return true; - } - - public boolean canClose(String inputString) { - return true; - } - }); - - BookmarkManager.getInstance(myProject).setDescription(b, description); - - myPopup.setUiVisible(true); - myPopup.setSize(myPopup.getContent().getPreferredSize()); - } - - public void setPopup(JBPopup popup) { - myPopup = popup; - } - } - - private static class DeleteBookmarkAction extends AnAction { - private final Project myProject; - private final JList myList; - - private DeleteBookmarkAction(Project project, JList list) { - super("Delete", "Delete current bookmark", IconLoader.getIcon("/general/remove.png")); - myProject = project; - myList = list; - registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke("DELETE")), list); - } - - @Override - public void update(AnActionEvent e) { - e.getPresentation().setEnabled(getSelectedBookmarks(myList).size() > 0); - } - - @Override - public void actionPerformed(AnActionEvent e) { - List bookmarks = getSelectedBookmarks(myList); - ListUtil.removeSelectedItems(myList); - - for (Bookmark bookmark : bookmarks) { - BookmarkManager.getInstance(myProject).removeBookmark(bookmark); - } - } - } - - private static boolean notFiltered(JList list) { + static boolean notFiltered(JList list) { if (!(list.getModel() instanceof FilteringListModel)) return true; final FilteringListModel model = (FilteringListModel)list.getModel(); return model.getOriginalModel().getSize() == model.getSize(); } - private static class MoveBookmarkUpAction extends AnAction { - private final Project myProject; - private final JList myList; - - private MoveBookmarkUpAction(Project project, JList list) { - super("Up", "Move current bookmark up", IconLoader.getIcon("/actions/previousOccurence.png")); - myProject = project; - myList = list; - registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta UP" : "control UP")), list); - } - - @Override - public void update(AnActionEvent e) { - e.getPresentation().setEnabled(notFiltered(myList) && getSelectedBookmarks(myList).size() == 1 && myList.getSelectedIndex() > 0); - } - - @Override - public void actionPerformed(AnActionEvent e) { - ListUtil.moveSelectedItemsUp(myList); - BookmarkManager.getInstance(myProject).moveBookmarkUp(getSelectedBookmarks(myList).get(0)); - } - } - - private static class MoveBookmarkDownAction extends AnAction { - private final Project myProject; - private final JList myList; - - private MoveBookmarkDownAction(Project project, JList list) { - super("Down", "Move current bookmark down", IconLoader.getIcon("/actions/nextOccurence.png")); - myProject = project; - myList = list; - registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta DOWN" : "control DOWN")), list); - } - - @Override - public void update(AnActionEvent e) { - int modelSize = myList.getModel().getSize(); - if (modelSize == 0 || !notFiltered(myList)) { - e.getPresentation().setEnabled(false); - } - else { - int lastIndex = modelSize - 1; - if (!(myList.getModel().getElementAt(lastIndex) instanceof BookmarkItem)) lastIndex--; - e.getPresentation().setEnabled(getSelectedBookmarks(myList).size() == 1 && myList.getSelectedIndex() < lastIndex); - } - } - - @Override - public void actionPerformed(AnActionEvent e) { - ListUtil.moveSelectedItemsDown(myList); - BookmarkManager.getInstance(myProject).moveBookmarkDown(getSelectedBookmarks(myList).get(0)); - } - } } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/DeleteBookmarkAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/DeleteBookmarkAction.java new file mode 100644 index 000000000000..4bf704ff34d6 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/DeleteBookmarkAction.java @@ -0,0 +1,62 @@ +/* + * 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.ide.bookmarks.actions; + +import com.intellij.ide.bookmarks.Bookmark; +import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; +import com.intellij.ui.ListUtil; + +import javax.swing.*; +import java.util.List; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:09 AM +* To change this template use File | Settings | File Templates. +*/ +class DeleteBookmarkAction extends AnAction { + private final Project myProject; + private final JList myList; + + DeleteBookmarkAction(Project project, JList list) { + super("Delete", "Delete current bookmark", IconLoader.getIcon("/general/remove.png")); + myProject = project; + myList = list; + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke("DELETE")), list); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(BookmarksAction.getSelectedBookmarks(myList).size() > 0); + } + + @Override + public void actionPerformed(AnActionEvent e) { + List bookmarks = BookmarksAction.getSelectedBookmarks(myList); + ListUtil.removeSelectedItems(myList); + + for (Bookmark bookmark : bookmarks) { + BookmarkManager.getInstance(myProject).removeBookmark(bookmark); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java new file mode 100644 index 000000000000..87203dd12c70 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java @@ -0,0 +1,83 @@ +/* + * 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.ide.bookmarks.actions; + +import com.intellij.ide.bookmarks.Bookmark; +import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.InputValidator; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:08 AM +* To change this template use File | Settings | File Templates. +*/ +class EditBookmarkDescriptionAction extends AnAction { + private final JList myList; + private final Project myProject; + private JBPopup myPopup; + + EditBookmarkDescriptionAction(Project project, JList list) { + super("Edit Description", "Assign short description for the bookmark to be shown along the file name", IconLoader + .getIcon("/actions/properties.png")); + myProject = project; + myList = list; + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta ENTER" : "control ENTER")), list); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(BookmarksAction.getSelectedBookmarks(myList).size() == 1); + } + + @Override + public void actionPerformed(AnActionEvent e) { + Bookmark b = BookmarksAction.getSelectedBookmarks(myList).get(0); + myPopup.setUiVisible(false); + + String description = Messages + .showInputDialog(myProject, "Enter short bookmark description", "Bookmark Description", Messages.getQuestionIcon(), + b.getDescription(), new InputValidator() { + public boolean checkInput(String inputString) { + return true; + } + + public boolean canClose(String inputString) { + return true; + } + }); + + BookmarkManager.getInstance(myProject).setDescription(b, description); + + myPopup.setUiVisible(true); + myPopup.setSize(myPopup.getContent().getPreferredSize()); + } + + public void setPopup(JBPopup popup) { + myPopup = popup; + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkDownAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkDownAction.java new file mode 100644 index 000000000000..fd43d4207c07 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkDownAction.java @@ -0,0 +1,66 @@ +/* + * 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.ide.bookmarks.actions; + +import com.intellij.ide.bookmarks.BookmarkItem; +import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.ListUtil; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:09 AM +* To change this template use File | Settings | File Templates. +*/ +class MoveBookmarkDownAction extends AnAction { + private final Project myProject; + private final JList myList; + + MoveBookmarkDownAction(Project project, JList list) { + super("Down", "Move current bookmark down", IconLoader.getIcon("/actions/nextOccurence.png")); + myProject = project; + myList = list; + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta DOWN" : "control DOWN")), list); + } + + @Override + public void update(AnActionEvent e) { + int modelSize = myList.getModel().getSize(); + if (modelSize == 0 || !BookmarksAction.notFiltered(myList)) { + e.getPresentation().setEnabled(false); + } + else { + int lastIndex = modelSize - 1; + if (!(myList.getModel().getElementAt(lastIndex) instanceof BookmarkItem)) lastIndex--; + e.getPresentation().setEnabled(BookmarksAction.getSelectedBookmarks(myList).size() == 1 && myList.getSelectedIndex() < lastIndex); + } + } + + @Override + public void actionPerformed(AnActionEvent e) { + ListUtil.moveSelectedItemsDown(myList); + BookmarkManager.getInstance(myProject).moveBookmarkDown(BookmarksAction.getSelectedBookmarks(myList).get(0)); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkUpAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkUpAction.java new file mode 100644 index 000000000000..16d86518bc11 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkUpAction.java @@ -0,0 +1,58 @@ +/* + * 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.ide.bookmarks.actions; + +import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.ListUtil; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:09 AM +* To change this template use File | Settings | File Templates. +*/ +class MoveBookmarkUpAction extends AnAction { + private final Project myProject; + private final JList myList; + + MoveBookmarkUpAction(Project project, JList list) { + super("Up", "Move current bookmark up", IconLoader.getIcon("/actions/previousOccurence.png")); + myProject = project; + myList = list; + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta UP" : "control UP")), list); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled( + BookmarksAction.notFiltered(myList) && BookmarksAction.getSelectedBookmarks(myList).size() == 1 && myList.getSelectedIndex() > 0); + } + + @Override + public void actionPerformed(AnActionEvent e) { + ListUtil.moveSelectedItemsUp(myList); + BookmarkManager.getInstance(myProject).moveBookmarkUp(BookmarksAction.getSelectedBookmarks(myList).get(0)); + } +} diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index d6015a1ed694..9439abe27109 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -252,11 +252,9 @@ public abstract class InplaceRefactoring { if (oldDocument != myEditor.getDocument()) { final int exitCode = Messages.showYesNoCancelDialog(myProject, e.getMessage(), getCommandName(), "Navigate to Started", "Cancel Started", "Cancel", Messages.getErrorIcon()); - if (exitCode == -1 || exitCode == Messages.CANCEL) return true; - //todo ann: //if (exitCode == Messages.YES ) { - navigateToAlreadyStarted(oldDocument, exitCode); - return true; - //} + if (exitCode == Messages.CANCEL) return true; + navigateToAlreadyStarted(oldDocument, exitCode); + return true; } else { revertState(); diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java index 216165ab7fcc..45d74ff03420 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java @@ -57,7 +57,7 @@ public class MemberInplaceRenameHandler extends VariableInplaceRenameHandler { final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(elementToRename); if (processor.isInplaceRenameSupported()) { final StartMarkAction startMarkAction = StartMarkAction.canStart(elementToRename.getProject()); - if (startMarkAction == null) { + if (startMarkAction == null || processor.substituteElementToRename(elementToRename, editor) == elementToRename) { processor.substituteElementToRename(elementToRename, editor, new Pass() { @Override public void pass(PsiElement element) { diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java index baa446d0025f..52894500489f 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java @@ -24,6 +24,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; @@ -237,7 +238,10 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { @Override protected void revertStateOnFinish() { - ((EditorImpl)InjectedLanguageUtil.getTopLevelEditor(myEditor)).startDumb(); + final Editor editor = InjectedLanguageUtil.getTopLevelEditor(myEditor); + if (editor == FileEditorManager.getInstance(myProject).getSelectedTextEditor()) { + ((EditorImpl)editor).startDumb(); + } revertState(); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index a1c1c2a7fd32..8894c2cc7c71 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -44,7 +44,6 @@ import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.TextOccurrencesUtil; import com.intellij.usageView.UsageInfo; -import com.intellij.usageView.UsageViewUtil; import com.intellij.util.PairProcessor; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; @@ -260,8 +259,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring { LOG.error(myElementToRename); return "Rename"; } - return RefactoringBundle.message("renaming.0.1.to.2", UsageViewUtil.getType(variable), UsageViewUtil.getDescriptiveName(variable), - variable.getName()); + return RefactoringBundle.message("renaming.command.name", myInitialName); } @Override diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java new file mode 100644 index 000000000000..1ea83d4a2972 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -0,0 +1,171 @@ +/* + * 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.ui.popup.util; + +import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.highlighter.EditorHighlighter; +import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.components.JBScrollPane; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:04 AM +* To change this template use File | Settings | File Templates. +*/ +public class DetailViewImpl extends JPanel implements DetailView { + private final Project myProject; + private Editor myEditor; + private ItemWrapper myWrapper; + private JPanel myDetailPanel; + + private JBScrollPane myDetailScrollPanel; + private JPanel myDetailPanelWrapper; + private JLabel myNothingToShow = new JLabel("Nothing to show"); + private JLabel myNothingToShowInEditor = new JLabel("Nothing to show"); + + public DetailViewImpl(Project project) { + super(new BorderLayout()); + myProject = project; + setPreferredSize(new Dimension(600, 400)); + myNothingToShow.setHorizontalAlignment(JLabel.CENTER); + myNothingToShowInEditor.setHorizontalAlignment(JLabel.CENTER); + } + + @Override + public void updateWithItem(ItemWrapper wrapper) { + if (myWrapper != wrapper) { + myWrapper = wrapper; + if (wrapper != null) { + wrapper.updateDetailView(this); + } + else { + clearEditor(); + repaint(); + } + + revalidate(); + } + } + + @Override + public void clearEditor() { + if (getEditor() != null) { + remove(getEditor().getComponent()); + EditorFactory.getInstance().releaseEditor(getEditor()); + setEditor(null); + add(myNothingToShowInEditor, BorderLayout.CENTER); + repaint(); + } + } + + @Override + public void removeNotify() { + super.removeNotify(); + clearEditor(); + } + + @Override + public Editor getEditor() { + return myEditor; + } + + public void setEditor(Editor editor) { + myEditor = editor; + } + + @Override + public void navigateInPreviewEditor(VirtualFile file, LogicalPosition positionToNavigate) { + Document document = FileDocumentManager.getInstance().getDocument(file); + Project project = myProject; + + if (document != null) { + if (getEditor() == null || getEditor().getDocument() != document) { + clearEditor(); + remove(myNothingToShowInEditor); + setEditor(EditorFactory.getInstance().createViewer(document, project)); + EditorHighlighter highlighter = EditorHighlighterFactory.getInstance() + .createEditorHighlighter(file, EditorColorsManager.getInstance().getGlobalScheme(), project); + ((EditorEx)getEditor()).setHighlighter(highlighter); + ((EditorEx)getEditor()).setFile(file); + + getEditor().getSettings().setAnimatedScrolling(false); + getEditor().getSettings().setRefrainFromScrolling(false); + getEditor().getSettings().setLineNumbersShown(true); + getEditor().getSettings().setFoldingOutlineShown(false); + + add(getEditor().getComponent(), BorderLayout.CENTER); + } + + getEditor().getCaretModel().moveToLogicalPosition(positionToNavigate); + validate(); + getEditor().getScrollingModel().scrollToCaret(ScrollType.CENTER); + } + else { + clearEditor(); + + JLabel label = new JLabel("Navigate to selected " + (file.isDirectory() ? "directory " : "file ") + "in Project View"); + label.setHorizontalAlignment(JLabel.CENTER); + add(label); + } + } + + @Override + public JPanel getDetailPanel() { + return myDetailPanel; + } + + @Override + public void setDetailPanel(@Nullable final JPanel panel) { + if (panel == myDetailPanel) return; + + if (panel != null) { + if (myDetailScrollPanel == null) { + myDetailPanelWrapper = new JPanel(new GridLayout(1, 1)); + myDetailPanelWrapper.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); + myDetailPanelWrapper.add(panel); + + myDetailScrollPanel = + new JBScrollPane(myDetailPanelWrapper, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) { + @Override + public Dimension getPreferredSize() { + final Dimension size = panel.getPreferredSize(); + return new Dimension(size.width, size.height + 10); + } + }; + add(myDetailScrollPanel, BorderLayout.SOUTH); + } else { + myDetailPanelWrapper.removeAll(); + myDetailPanelWrapper.add(panel); + } + } + else { + myDetailPanelWrapper.removeAll(); + myDetailPanelWrapper.add(myNothingToShow); + } + myDetailPanel = panel; + } +} diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java new file mode 100644 index 000000000000..b89274533ef5 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -0,0 +1,356 @@ +/* + * 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.ui.popup.util; + +import com.intellij.ide.bookmarks.Bookmark; +import com.intellij.ide.bookmarks.BookmarkItem; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.ActionToolbar; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.PopupChooserBuilder; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.Gray; +import com.intellij.ui.TitledSeparator; +import com.intellij.ui.components.JBList; +import com.intellij.ui.speedSearch.FilteringListModel; +import com.intellij.util.Alarm; +import com.intellij.util.Function; +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.io.File; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 5/6/12 + * Time: 2:06 PM + * To change this template use File | Settings | File Templates. + */ +public class MasterDetailPopupBuilder { + + private static final Color BORDER_COLOR = Gray._135; + private Project myProject; + private ActionGroup myActions; + private JBList myList; + private Delegate myDelegate; + private boolean myCloseOnEnter; + + public ActionToolbar getActionToolbar() { + return myActionToolbar; + } + + private ActionToolbar myActionToolbar; + + public MasterDetailPopupBuilder(Project project) { + + myProject = project; + } + + + public JBPopup createMasterDetailPopup() { + final JLabel pathLabel = new JLabel(" "); + pathLabel.setHorizontalAlignment(SwingConstants.RIGHT); + + final Font font = pathLabel.getFont(); + pathLabel.setFont(font.deriveFont((float)10)); + + final Alarm updateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + final DetailViewImpl detailView = new DetailViewImpl(myProject); + + myList.setCellRenderer(new ItemRenderer(myProject)); + + final ListSelectionModel selectionModel = myList.getSelectionModel(); + selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + final boolean directionUp[] = new boolean[1]; + + selectionModel.addListSelectionListener(new ListSelectionListener() { + private String getTitle2Text(String fullText) { + int labelWidth = pathLabel.getWidth(); + if (fullText == null || fullText.length() == 0) return " "; + while (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) { + int sep = fullText.indexOf(File.separatorChar, 4); + if (sep < 0) return fullText; + fullText = "..." + fullText.substring(sep); + } + + return fullText; + } + + public void valueChanged(final ListSelectionEvent e) { + //noinspection SSBasedInspection + SwingUtilities.invokeLater(new Runnable() { + public void run() { + updatePathLabel(); + } + }); + } + + private void updatePreviewPanel(final ItemWrapper wrapper) { + updateAlarm.cancelAllRequests(); + updateAlarm.addRequest(new Runnable() { + public void run() { + detailView.updateWithItem(wrapper); + } + }, 100); + } + + private void updatePathLabel() { + final Object[] values = myList.getSelectedValues(); + ItemWrapper wrapper = null; + if (values != null && values.length == 1) { + wrapper = (ItemWrapper)values[0]; + if (wrapper instanceof SplitterItem) { + if (!directionUp[0]) { + final int index = myList.getSelectedIndex(); + if (myList.getItemsCount() >= index + 1) { + myList.setSelectedIndex(index + 1); + } + else { + myList.setSelectedIndex(0); + } + } + else { + final int index = myList.getSelectedIndex(); + if (index - 1 > 0) { + myList.setSelectedIndex(index - 1); + } + else { + myList.setSelectedIndex(myList.getItemsCount() - 1); + } + } + } + pathLabel.setText(getTitle2Text(wrapper.footerText())); + } + else { + pathLabel.setText(" "); + } + updatePreviewPanel(wrapper); + } + }); + final Ref popupRef = Ref.create(null); + + Runnable runnable = new Runnable() { + public void run() { + IdeFocusManager.getInstance(myProject).doWhenFocusSettlesDown(new Runnable() { + public void run() { + Object[] values = myList.getSelectedValues(); + + if (values.length == 1) { + ((ItemWrapper)values[0]).execute(myProject, popupRef.get()); + } + else { + for (Object value : values) { + if (value instanceof BookmarkItem) { + ((ItemWrapper)value).execute(myProject, popupRef.get()); + } + } + } + } + }); + } + }; + + if (myList.getModel().getSize() == 0) { + myList.clearSelection(); + } + + JPanel footerPanel = new JPanel(new BorderLayout()) { + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(BORDER_COLOR); + g.drawLine(0, 0, getWidth(), 0); + } + }; + + footerPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); + footerPanel.add(pathLabel); + + myActionToolbar = ActionManager.getInstance().createActionToolbar("", myActions, true); + myActionToolbar.setReservePlaceAutoPopupIcon(false); + myActionToolbar.setMinimumButtonSize(new Dimension(20, 20)); + final JComponent toolBar = myActionToolbar.getComponent(); + toolBar.setOpaque(false); + + final JBPopup popup = new PopupChooserBuilder(myList). + setTitle(myDelegate.getTitle()). + setMovable(true). + setResizable(true). + setAutoselectOnMouseMove(false). + setSettingButton(toolBar). + setSouthComponent(footerPanel). + setEastComponent(detailView). + setItemChoosenCallback(runnable). + setCloseOnEnter(myCloseOnEnter). + setMayBeParent(true). + setMinSize(new Dimension(-1, 700)). + setFilteringEnabled(new Function() { + public String fun(Object o) { + return ((ItemWrapper)o).speedSearchText(); + } + }).createPopup(); + + popupRef.set(popup); + + myList.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_DELETE) { + removeSelectedItems(MasterDetailPopupBuilder.this.myList, MasterDetailPopupBuilder.this.myProject); + } + else if (e.getKeyCode() == KeyEvent.VK_UP) { + directionUp[0] = true; + } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { + directionUp[0] = false; + } + else if (e.getModifiersEx() == 0) { + myDelegate.handleMnemonic(e, myProject, popup); + } + } + }); + return popup; + } + + public static boolean allowedToRemoveSelectedItem(JBList list, Project project) { + Object[] values = list.getSelectedValues(); + for (Object value : values) { + ItemWrapper item = (ItemWrapper)value; + if (!item.allowedToRemove()) { + return false; + } + } + return values.length > 0; + } + + public static void removeSelectedItems(JBList list, Project project) { + int index = list.getSelectedIndex(); + if (index == -1 || index >= list.getModel().getSize()) { + return; + } + Object[] values = list.getSelectedValues(); + for (Object value : values) { + ItemWrapper item = (ItemWrapper)value; + + DefaultListModel model = list.getModel() instanceof DefaultListModel + ? (DefaultListModel)list.getModel() + : (DefaultListModel)((FilteringListModel)list.getModel()).getOriginalModel(); + if (item.allowedToRemove()) { + model.removeElement(item); + + if (model.getSize() > 0) { + if (model.getSize() == index) { + list.setSelectedIndex(model.getSize() - 1); + } + else if (model.getSize() > index) { + list.setSelectedIndex(index); + } + } + else { + list.clearSelection(); + } + item.removed(project); + } + } + } + + public MasterDetailPopupBuilder setActionsGroup(ActionGroup actions) { + myActions = actions; + return this; + } + + public MasterDetailPopupBuilder setList(JBList list) { + myList = list; + return this; + } + + public MasterDetailPopupBuilder setDelegate(Delegate delegate) { + myDelegate = delegate; + return this; + } + + public MasterDetailPopupBuilder setCloseOnEnter(boolean closeOnEnter) { + myCloseOnEnter = closeOnEnter; + return this; + } + + public interface Delegate { + String getTitle(); + + void handleMnemonic(KeyEvent e, Project project, JBPopup popup); + + boolean hasItemsWithMnemonic(Project project); + } + + public class ItemRenderer extends JPanel implements ListCellRenderer { + private final Project myProject; + private final ColoredListCellRenderer myRenderer; + + private ItemRenderer(Project project) { + super(new BorderLayout()); + myProject = project; + setBackground(UIUtil.getListBackground()); + final JLabel mnemonicLabel = new JLabel(); + mnemonicLabel.setFont(Bookmark.MNEMONIC_FONT); + + mnemonicLabel.setPreferredSize(new JLabel("W.").getPreferredSize()); + mnemonicLabel.setOpaque(false); + + final boolean hasMnemonics = myDelegate.hasItemsWithMnemonic(project); + if (hasMnemonics) { + add(mnemonicLabel, BorderLayout.WEST); + } + + myRenderer = new ColoredListCellRenderer() { + @Override + protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + if (value instanceof ItemWrapper) { + final ItemWrapper wrapper = (ItemWrapper)value; + wrapper.setupRenderer(this, myProject, selected); + if (hasMnemonics) { + wrapper.updateMnemonicLabel(mnemonicLabel); + } + } + } + }; + add(myRenderer, BorderLayout.CENTER); + } + + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value instanceof SplitterItem) { + String label = ((SplitterItem)value).getText(); + final TitledSeparator separator = new TitledSeparator(label); + separator.setBackground(UIUtil.getListBackground()); + separator.setForeground(UIUtil.getListForeground()); + return separator; + } + myRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + myRenderer.revalidate(); + return this; + } + } + +} diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/RevisionsList.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/RevisionsList.java index 21ea7b38aa09..17df7d096bbc 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/RevisionsList.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/RevisionsList.java @@ -394,7 +394,7 @@ public class RevisionsList { @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Graphics2D g2d = (Graphics2D)g.create(); - g2d.setColor(UIUtil.getBorderSeparatorColor()); + g2d.setColor(UIUtil.getBorderColor()); g2d.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[]{1}, 1)); g2d.drawLine(x, y, x + width, y); if (isLast) { diff --git a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java index 06cccde080c3..762ba6c55400 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java @@ -334,9 +334,11 @@ public class ParametersList implements Cloneable { final Application application = ApplicationManager.getApplication(); if (application != null) { final PathMacros pathMacros = PathMacros.getInstance(); - final Set names = pathMacros.getAllMacroNames(); - for (String name : names) { - myMacroMap.put("${" + name + "}", pathMacros.getValue(name)); + for (String name : pathMacros.getUserMacroNames()) { + final String value = pathMacros.getValue(name); + if (value != null) { + myMacroMap.put("${" + name + "}", value); + } } final Map env = EnvironmentUtil.getEnviromentProperties(); for (String name : env.keySet()) { diff --git a/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java b/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java index 2ce8927cb5c3..b2e29f1bc88d 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java @@ -16,6 +16,7 @@ package com.intellij.openapi.diff; import com.intellij.openapi.application.ApplicationNamesInfo; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.vfs.VirtualFile; /** @@ -41,7 +42,7 @@ public class MergeApplication extends ApplicationStarterBase { MergeRequest request = DiffRequestFactory.getInstance() .createMergeRequest(getText(left), getText(right), getText(middle), result, - null, + ProjectManager.getInstance().getDefaultProject(), ActionButtonPresentation.APPLY, ActionButtonPresentation.CANCEL_WITH_PROMPT); request.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java index 8198230777a4..8ac88742c368 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java @@ -18,7 +18,6 @@ package com.intellij.openapi.ui; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.actionSystem.Separator; import com.intellij.openapi.util.Ref; import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.util.ui.AwtVisitor; @@ -28,8 +27,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.*; -import java.util.*; +import java.awt.event.ContainerAdapter; +import java.awt.event.ContainerEvent; import java.util.List; public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider, DataProvider { @@ -145,7 +144,7 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider super.paintComponent(g); if (myToolbar != null && myToolbar.getParent() == this && myContent != null && myContent.getParent() == this) { - g.setColor(UIUtil.getBorderSeparatorColor()); + g.setColor(UIUtil.getBorderColor()); if (myVertical) { final int y = (int)myToolbar.getBounds().getMaxY(); g.drawLine(0, y, getWidth(), y); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java index f82e36b483c3..1d7ddf517976 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java @@ -81,6 +81,7 @@ public class PopupChooserBuilder { private boolean myMayBeParent; private int myAdAlignment = SwingUtilities.LEFT; private boolean myModalContext; + private boolean myCloseOnEnter = true; public PopupChooserBuilder(@NotNull JList list) { myChooserComponent = list; @@ -205,13 +206,28 @@ public class PopupChooserBuilder { @Override public void mouseReleased(MouseEvent e) { if (UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED) && !UIUtil.isSelectionButtonDown(e) && !e.isConsumed()) { - closePopup(true, e, true); + if (myCloseOnEnter) { + closePopup(true, e, true); + } + else { + myItemChosenRunnable.run(); + } } } }); registerClosePopupKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), false); - registerClosePopupKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), true); + if (myCloseOnEnter) { + registerClosePopupKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), true); + } + else { + registerKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + myItemChosenRunnable.run(); + } + }); + } for (KeyStroke keystroke : myAdditionalKeystrokes) { registerClosePopupKeyboardAction(keystroke, true); } @@ -295,14 +311,18 @@ public class PopupChooserBuilder { } private void registerClosePopupKeyboardAction(final KeyStroke keyStroke, final boolean shouldPerformAction) { - myChooserComponent.registerKeyboardAction(new AbstractAction() { + registerPopupKeyboardAction(keyStroke, new AbstractAction() { public void actionPerformed(ActionEvent e) { if (!shouldPerformAction && myChooserComponent instanceof ListWithFilter) { if (((ListWithFilter)myChooserComponent).resetFilter()) return; } closePopup(shouldPerformAction, null, shouldPerformAction); } - }, keyStroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + }); + } + + private void registerPopupKeyboardAction(final KeyStroke keyStroke, AbstractAction action) { + myChooserComponent.registerKeyboardAction(action, keyStroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); } private void closePopup(boolean shouldPerformAction, MouseEvent e, boolean isOk) { @@ -419,6 +439,11 @@ public class PopupChooserBuilder { return this; } + public PopupChooserBuilder setCloseOnEnter(boolean closeOnEnter) { + myCloseOnEnter = closeOnEnter; + return this; + } + private class MyListWrapper extends JBScrollPane implements DataProvider { @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private final JList myList; diff --git a/platform/platform-api/src/com/intellij/ui/TitledSeparator.java b/platform/platform-api/src/com/intellij/ui/TitledSeparator.java index 010a55c960ff..7773ee761c7a 100644 --- a/platform/platform-api/src/com/intellij/ui/TitledSeparator.java +++ b/platform/platform-api/src/com/intellij/ui/TitledSeparator.java @@ -40,7 +40,7 @@ public class TitledSeparator extends JPanel { public TitledSeparator(String text) { setLayout(new GridBagLayout()); - add(myLabel, new GridBagConstraints(0, 0, 1, 1, 0, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + add(myLabel, new GridBagConstraints(0, 0, 1, 1, 0, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0)); add(mySeparator, new GridBagConstraints(1, 0, GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(2, SEPARATOR_LEFT_INSET, 0, SEPARATOR_RIGHT_INSET), 0, 0)); @@ -54,7 +54,7 @@ public class TitledSeparator extends JPanel { public void updateUI() { super.updateUI(); if (myLabel != null) { - myLabel.setFont(UIUtil.getBorderFont(UIUtil.FontSize.SMALL, false)); + myLabel.setFont(UIUtil.getTitledBorderFont()); } } @@ -81,22 +81,4 @@ public class TitledSeparator extends JPanel { public JSeparator getSeparator() { return mySeparator; } - - @Deprecated - public boolean isBoldFont() { - return false; - } - - @Deprecated - public boolean isSmallFont() { - return true; - } - - @Deprecated - public void setBoldFont(boolean boldFont) { - } - - @Deprecated - public void setSmallFont(boolean smallFont) { - } } diff --git a/platform/platform-api/src/com/intellij/ui/components/panels/NonOpaquePanel.java b/platform/platform-api/src/com/intellij/ui/components/panels/NonOpaquePanel.java index a0f0f82019ef..442f94595cd1 100644 --- a/platform/platform-api/src/com/intellij/ui/components/panels/NonOpaquePanel.java +++ b/platform/platform-api/src/com/intellij/ui/components/panels/NonOpaquePanel.java @@ -53,6 +53,7 @@ public class NonOpaquePanel extends Wrapper { @Override public void setOpaque(boolean isOpaque) { super.setOpaque(isOpaque); + setDoubleBuffered(false); if (!isOpaque && UIUtil.isUnderNimbusLookAndFeel()) { if (UIUtil.isUnderNimbusLookAndFeel()) { diff --git a/platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java b/platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java index c263be580500..7e95d62fe9ad 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java @@ -19,7 +19,6 @@ import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.ActiveRunnable; -import com.intellij.openapi.util.Getter; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.switcher.SwitchProvider; import org.jetbrains.annotations.NotNull; @@ -29,8 +28,6 @@ import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import java.util.Comparator; -import java.util.List; public interface JBTabs extends SwitchProvider { @@ -42,21 +39,10 @@ public interface JBTabs extends SwitchProvider { ActionCallback removeTab(@Nullable TabInfo info); - ActionCallback removeTab(@Nullable TabInfo info, @Nullable TabInfo forcedSelectionTranfer); - - ActionCallback removeTab(@Nullable TabInfo info, @Nullable TabInfo forcedSelectionTranfer, boolean transferFocus); - void removeAllTabs(); - @Nullable - ActionGroup getPopupGroup(); - - @Nullable - String getPopupPlace(); - JBTabs setPopupGroup(@NotNull ActionGroup popupGroup, @NotNull String place, final boolean addNavigationGroup); - JBTabs setPopupGroup(@NotNull Getter popupGroup, @NotNull String place, final boolean addNavigationGroup); - + ActionCallback select(@NotNull TabInfo info, boolean requestFocus); @Nullable @@ -65,9 +51,6 @@ public interface JBTabs extends SwitchProvider { @NotNull TabInfo getTabAt(int tabIndex); - @NotNull - List getTabs(); - int getTabCount(); @NotNull @@ -76,31 +59,19 @@ public interface JBTabs extends SwitchProvider { @Nullable DataProvider getDataProvider(); - JBTabs setDataProvider(@NotNull DataProvider dataProvider); - @Nullable TabInfo getTargetInfo(); @NotNull JBTabs addTabMouseListener(@NotNull MouseListener listener); - @NotNull - JBTabs removeTabMouseListener(@NotNull MouseListener listener); - JBTabs addListener(@NotNull TabsListener listener); - JBTabs removeListener(@NotNull TabsListener listener); - JBTabs setSelectionChangeHandler(SelectionChangeHandler handler); @NotNull JComponent getComponent(); - void updateTabActions(boolean validateNow); - - @Nullable - TabInfo findInfo(Component component); - @Nullable TabInfo findInfo(MouseEvent event); @@ -109,11 +80,7 @@ public interface JBTabs extends SwitchProvider { int getIndexOf(@Nullable final TabInfo tabInfo); - void sortTabs(Comparator comparator); - void requestFocus(); - - boolean isEditorTabs(); JBTabs setNavigationActionBinding(String prevActiobId, String nextActionId); JBTabs setNavigationActionsEnabled(boolean enabled); @@ -122,16 +89,10 @@ public interface JBTabs extends SwitchProvider { JBTabs setAdditionalSwitchProviderWhenOriginal(SwitchProvider delegate); - Image getComponentImage(TabInfo info); - void resetDropOver(TabInfo tabInfo); Image startDropOver(TabInfo tabInfo, RelativePoint point); void processDropOver(TabInfo over, RelativePoint point); - boolean isEmptyVisible(); - - int getInterTabSpaceLength(); - interface SelectionChangeHandler { ActionCallback execute(final TabInfo info, final boolean requestFocus, ActiveRunnable doChangeSelection); } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/JBTabsPresentation.java b/platform/platform-api/src/com/intellij/ui/tabs/JBTabsPresentation.java index 33fe1a0064a6..e354fb6d79f9 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/JBTabsPresentation.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/JBTabsPresentation.java @@ -30,14 +30,10 @@ public interface JBTabsPresentation { JBTabsPresentation setPaintBorder(int top, int left, int right, int bottom); JBTabsPresentation setTabSidePaintBorder(int size); - boolean isPaintFocus(); - JBTabsPresentation setPaintFocus(boolean paintFocus); JBTabsPresentation setStealthTabMode(boolean stealthTabMode); - boolean isStealthTabMode(); - JBTabsPresentation setSideComponentVertical(boolean vertical); JBTabsPresentation setSideComponentOnTabs(boolean onTabs); @@ -46,35 +42,18 @@ public interface JBTabsPresentation { boolean isSingleRow(); - boolean isSideComponentVertical(); - - boolean isSideComponentOnTabs(); - JBTabsPresentation setUiDecorator(@Nullable UiDecorator decorator); - boolean isRequestFocusOnLastFocusedComponent(); - JBTabsPresentation setRequestFocusOnLastFocusedComponent(boolean request); void setPaintBlocked(boolean blocked, final boolean takeSnapshot); - void setFocused(boolean focused); - JBTabsPresentation setInnerInsets(Insets innerInsets); - Insets getInnerInsets(); - JBTabsPresentation setGhostsAlwaysVisible(boolean visible); - boolean isGhostsAlwaysVisible(); - - @NotNull - JBTabsPresentation setAdjustBorders(boolean adjust); - JBTabsPresentation setFocusCycle(final boolean root); - boolean isToDrawBorderIfTabsHidden(); - @NotNull JBTabsPresentation setToDrawBorderIfTabsHidden(boolean draw); @@ -96,9 +75,7 @@ public interface JBTabsPresentation { JBTabsPosition getTabsPosition(); JBTabsPresentation setTabDraggingEnabled(boolean enabled); - - boolean isTabDraggingEnabled(); JBTabsPresentation setProvideSwitchTargets(boolean provide); -} \ No newline at end of file +} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionButton.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionButton.java index 3dc1fe1f2b56..431132fffa12 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionButton.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionButton.java @@ -127,10 +127,6 @@ class ActionButton extends IconButton implements ActionListener { } } - public boolean isAutoHide() { - return myAutoHide; - } - public void toggleShowActions(boolean show) { if (myAutoHide) { myButton.setPainting(show); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java index 838a6a1e5095..2d5a66168223 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java @@ -37,15 +37,13 @@ public class ActionPanel extends NonOpaquePanel { private boolean myAutoHide; private boolean myActionsIsVisible = false; - private final int myGap = 2; - public ActionPanel(JBTabsImpl tabs, TabInfo tabInfo, Pass pass) { myTabs = tabs; ActionGroup group = tabInfo.getTabLabelActions() != null ? tabInfo.getTabLabelActions() : new DefaultActionGroup(); AnAction[] children = group.getChildren(null); final NonOpaquePanel wrapper = new NonOpaquePanel(new BorderLayout()); - wrapper.add(Box.createHorizontalStrut(myGap), BorderLayout.WEST); + wrapper.add(Box.createHorizontalStrut(2), BorderLayout.WEST); NonOpaquePanel inner = new NonOpaquePanel(); inner.setLayout(new BoxLayout(inner, BoxLayout.X_AXIS)); wrapper.add(inner, BorderLayout.CENTER); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java index 6e1186198afb..fda9ee1622d0 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java @@ -29,12 +29,12 @@ import java.awt.event.MouseEvent; class DragHelper extends MouseDragHelper { - JBTabsImpl myTabs; - TabInfo myDragSource; - Rectangle myDragOriginalRec; + private final JBTabsImpl myTabs; + private TabInfo myDragSource; + private Rectangle myDragOriginalRec; Rectangle myDragRec; - Dimension myHoldDelta; + private Dimension myHoldDelta; private TabInfo myDragOutSource; private TabLabel myPressedTabLabel; @@ -147,7 +147,7 @@ class DragHelper extends MouseDragHelper { if (targetLabel != null) { Rectangle saved = myDragRec; myDragRec = null; - myTabs.reallocate(myDragSource, targetLabel.getInfo(), true); + myTabs.reallocate(myDragSource, targetLabel.getInfo()); myDragOriginalRec = myTabs.myInfo2Label.get(myDragSource).getBounds(); myDragRec = saved; myTabs.moveDraggedTabLabel(); @@ -251,4 +251,4 @@ class DragHelper extends MouseDragHelper { public TabInfo getDragSource() { return myDragSource; } -} \ No newline at end of file +} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index aed4055b1853..f0623fa5895c 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -19,12 +19,12 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.ui.ShadowAction; import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.*; -import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.ui.CaptionPanel; import com.intellij.ui.ColorUtil; import com.intellij.ui.Gray; @@ -65,12 +65,11 @@ import java.util.concurrent.CopyOnWriteArrayList; public class JBTabsImpl extends JComponent implements JBTabs, PropertyChangeListener, TimerListener, DataProvider, PopupMenuListener, Disposable, JBTabsPresentation, Queryable, QuickActionProvider { - public static DataKey NAVIGATION_ACTIONS_KEY = DataKey.create("JBTabs"); + public static final DataKey NAVIGATION_ACTIONS_KEY = DataKey.create("JBTabs"); - public static final String EDITOR_TABS = "main.editor.tabs"; public static final Color MAC_AQUA_BG_COLOR = Gray._200; - ActionManager myActionManager; + final ActionManager myActionManager; private final List myVisibleInfos = new ArrayList(); private final Map myHiddenInfos = new HashMap(); @@ -83,15 +82,15 @@ public class JBTabsImpl extends JComponent private final List myTabMouseListeners = new CopyOnWriteArrayList(); private final List myTabListeners = new CopyOnWriteArrayList(); - public boolean myFocused; + private boolean myFocused; private Getter myPopupGroup; private String myPopupPlace; TabInfo myPopupInfo; - DefaultActionGroup myNavigationActions; + final DefaultActionGroup myNavigationActions; - PopupMenuListener myPopupListener; + final PopupMenuListener myPopupListener; JPopupMenu myActivePopup; public boolean myHorizontalSide = true; @@ -130,7 +129,7 @@ public class JBTabsImpl extends JComponent private boolean myPaintBlocked; private BufferedImage myImage; private IdeFocusManager myFocusManager; - private boolean myAdjustBorders = true; + private final boolean myAdjustBorders = true; boolean myAddNavigationGroup = true; @@ -177,7 +176,7 @@ public class JBTabsImpl extends JComponent this(project, project); } - public JBTabsImpl(@NotNull Project project, @NotNull Disposable parent) { + private JBTabsImpl(@NotNull Project project, @NotNull Disposable parent) { this(project, ActionManager.getInstance(), IdeFocusManager.getInstance(project), parent); } @@ -331,8 +330,7 @@ public class JBTabsImpl extends JComponent return this; } - @Override - public Image getComponentImage(TabInfo info) { + public static Image getComponentImage(TabInfo info) { JComponent cmp = info.getComponent(); BufferedImage img; @@ -461,7 +459,7 @@ public class JBTabsImpl extends JComponent return myDropInfo != null && myDropInfo == info; } - public void setDropInfoIndex(int dropInfoIndex) { + protected void setDropInfoIndex(int dropInfoIndex) { myDropInfoIndex = dropInfoIndex; } @@ -474,8 +472,7 @@ public class JBTabsImpl extends JComponent public void mouseMoved(final MouseEvent e) { if (!myTabLabelActionsAutoHide) return; - final Point point = SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), JBTabsImpl.this); - myLastOverPoint = point; + myLastOverPoint = SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), JBTabsImpl.this); processMouseOver(); } @@ -590,6 +587,7 @@ public class JBTabsImpl extends JComponent } + @Nullable private JComponent getToFocus() { final TabInfo info = getSelectedInfo(); @@ -637,18 +635,6 @@ public class JBTabsImpl extends JComponent } } - private JBTabsImpl findTabs(Component c) { - Component eachParent = c; - while (eachParent != null) { - if (eachParent instanceof JBTabsImpl) { - return (JBTabsImpl)eachParent; - } - eachParent = eachParent.getParent(); - } - - return null; - } - @NotNull public TabInfo addTab(TabInfo info, int index) { @@ -669,10 +655,7 @@ public class JBTabsImpl extends JComponent myInfo2Label.put(info, label); if (!isDropTarget) { - if (index < 0) { - myVisibleInfos.add(info); - } - else if (index > myVisibleInfos.size() - 1) { + if (index < 0 || index > myVisibleInfos.size() - 1) { myVisibleInfos.add(info); } else { @@ -719,6 +702,7 @@ public class JBTabsImpl extends JComponent return addTab(info, -1); } + @Nullable public ActionGroup getPopupGroup() { return myPopupGroup != null ? myPopupGroup.get() : null; } @@ -847,7 +831,7 @@ public class JBTabsImpl extends JComponent } } - private void fireBeforeSelectionChanged(TabInfo oldInfo, TabInfo newInfo) { + private void fireBeforeSelectionChanged(@Nullable TabInfo oldInfo, TabInfo newInfo) { if (oldInfo != newInfo) { myOldSelection = oldInfo; try { @@ -861,7 +845,7 @@ public class JBTabsImpl extends JComponent } } - private void fireSelectionChanged(TabInfo oldInfo, TabInfo newInfo) { + private void fireSelectionChanged(@Nullable TabInfo oldInfo, TabInfo newInfo) { if (oldInfo != newInfo) { for (TabsListener eachListener : myTabListeners) { if (eachListener != null) { @@ -956,19 +940,6 @@ public class JBTabsImpl extends JComponent myDeferredToRemove.clear(); } - private void printRemoveInfo(final Component each) { - TabInfo removingInfo = null; - final List all = getTabs(); - for (TabInfo eachInfo : all) { - if (eachInfo.getComponent() == each) { - removingInfo = eachInfo; - break; - } - } - - //System.out.println(" - removing " + (removingInfo != null ? " component for " + removingInfo : each)); - } - public void propertyChange(final PropertyChangeEvent evt) { final TabInfo tabInfo = (TabInfo)evt.getSource(); if (TabInfo.ACTION_GROUP.equals(evt.getPropertyName())) { @@ -1322,7 +1293,7 @@ public class JBTabsImpl extends JComponent } } - public boolean isToDrawBorderIfTabsHidden() { + private boolean isToDrawBorderIfTabsHidden() { return myToDrawBorderIfTabsHidden; } @@ -1339,11 +1310,9 @@ public class JBTabsImpl extends JComponent public static class Toolbar extends JPanel { private final JBTabsImpl myTabs; - private final TabInfo myInfo; public Toolbar(JBTabsImpl tabs, TabInfo info) { myTabs = tabs; - myInfo = info; setLayout(new BorderLayout()); @@ -1489,7 +1458,7 @@ public class JBTabsImpl extends JComponent return this; } - public Insets getInnerInsets() { + private Insets getInnerInsets() { return myInnerInsets; } @@ -1542,15 +1511,15 @@ public class JBTabsImpl extends JComponent } - protected int getArcSize() { + private static int getArcSize() { return 4; } - protected int getEdgeArcSize() { + private static int getEdgeArcSize() { return 3; } - public int getGhostTabLength() { + public static int getGhostTabLength() { return 15; } @@ -1622,7 +1591,8 @@ public class JBTabsImpl extends JComponent config.restore(); } - protected Color getActiveTabColor(final Color c) { + @Nullable + protected Color getActiveTabColor(@Nullable final Color c) { final TabInfo info = getSelectedInfo(); if (info == null) { return c; @@ -1857,10 +1827,6 @@ public class JBTabsImpl extends JComponent g2d.drawLine(bottomX - path.deltaX(1), topY + path.deltaY(getArcSize()), bottomX - path.deltaX(1), bottomY - path.deltaY(1)); } - protected SingleRowLayout getSingleRowLayout() { - return mySingleRowLayout; - } - protected void paintLastGhost(Graphics2D g2d) { final ShapeTransform path = getEffectiveLayout().createShapeTransform(mySingleRowLayout.myLastSingRowLayout.lastGhost); @@ -1887,25 +1853,21 @@ public class JBTabsImpl extends JComponent g2d.drawLine(topX, topY + path.deltaY(1), bottomX - path.deltaX(getCurveArc()), topY + path.deltaY(1)); } - protected int getCurveArc() { + private static int getCurveArc() { return 2; } - protected Color getBoundsColor() { + private static Color getBoundsColor() { return Color.gray; } - protected Color getRightBlockColor() { + private static Color getRightBlockColor() { return Color.lightGray; } - protected Color getTopBlockColor() { + private static Color getTopBlockColor() { return Color.white; } - - protected boolean shouldPaintFocus() { - return myPaintFocus; - } private void paintNonSelectedTabs(final Graphics2D g2d, final boolean leftGhostExists, final boolean rightGhostExists) { TabInfo selected = getSelectedInfo(); @@ -1976,18 +1938,6 @@ public class JBTabsImpl extends JComponent protected LayoutPassInfo getLastLayoutPass() { return myLastLayoutPass; } - - protected TabLabel getInfoForLabel(TabInfo info) { - return myInfo2Label.get(info); - } - - protected TableLayout getTableLayout() { - return myTableLayout; - } - - protected DragHelper getDragHelper() { - return myDragHelper; - } @Override public Color getBackground() { @@ -2035,8 +1985,7 @@ public class JBTabsImpl extends JComponent boolean leftFromSelection = selected != null && tabIndex == myVisibleInfos.indexOf(selected) - 1; - Rectangle originalBounds = effectiveBounds; - final ShapeTransform shape = getEffectiveLayout().createShapeTransform(originalBounds); + final ShapeTransform shape = getEffectiveLayout().createShapeTransform(effectiveBounds); int leftX = firstShowing ? shape.getX() : shape.getX() - shape.deltaX(arc + 1); int topY = shape.getY() + shape.deltaY(selectionTabVShift); @@ -2115,7 +2064,7 @@ public class JBTabsImpl extends JComponent g2d.draw(shape.getShape()); } - public int getSelectionTabVShift() { + public static int getSelectionTabVShift() { return 2; } @@ -2189,7 +2138,7 @@ public class JBTabsImpl extends JComponent } - public boolean isStealthModeEffective() { + protected boolean isStealthModeEffective() { return myStealthTabMode && getTabCount() == 1 && (isSideComponentVertical() || !isSideComponentOnTabs()) && getTabsPosition() == JBTabsPosition.top; @@ -2358,16 +2307,8 @@ public class JBTabsImpl extends JComponent return this; } - public ActionCallback removeTab(final JComponent component) { - return removeTab(findInfo(component)); - } - public ActionCallback removeTab(final TabInfo info) { - return removeTab(info, null); - } - - public ActionCallback removeTab(final TabInfo info, @Nullable TabInfo forcedSelectionTransfer) { - return removeTab(info, forcedSelectionTransfer, true); + return removeTab(info, null, true); } public ActionCallback removeTab(final TabInfo info, @Nullable TabInfo forcedSelectionTransfer, boolean transferFocus) { @@ -2442,6 +2383,7 @@ public class JBTabsImpl extends JComponent myLastPaintedSelection = null; } + @Nullable public TabInfo findInfo(Component component) { for (TabInfo each : getTabs()) { if (each.getComponent() == component) return each; @@ -2450,20 +2392,11 @@ public class JBTabsImpl extends JComponent return null; } - public TabInfo findInfo(String text) { - if (text == null) return null; - - for (TabInfo each : getTabs()) { - if (text.equals(each.getText())) return each; - } - - return null; - } - public TabInfo findInfo(MouseEvent event) { return findInfo(event, false); } + @Nullable private TabInfo findInfo(final MouseEvent event, final boolean labelsOnly) { final Point point = SwingUtilities.convertPoint(event.getComponent(), event.getPoint(), this); return _findInfo(point, labelsOnly); @@ -2478,10 +2411,6 @@ public class JBTabsImpl extends JComponent return null; } - public TabInfo findTabLabelBy(final Point point) { - return _findInfo(point, true); - } - @Nullable private TabInfo _findInfo(final Point point, boolean labelsOnly) { Component component = findComponentAt(point); @@ -2509,8 +2438,8 @@ public class JBTabsImpl extends JComponent private static class Max { - Dimension myLabel = new Dimension(); - Dimension myToolbar = new Dimension(); + final Dimension myLabel = new Dimension(); + final Dimension myToolbar = new Dimension(); } private void updateContainer(boolean forced, final boolean layoutNow) { @@ -2539,7 +2468,7 @@ public class JBTabsImpl extends JComponent } } - mySingleRowLayout.scrollSelectionInView(myVisibleInfos); + mySingleRowLayout.scrollSelectionInView(); relayout(forced, layoutNow); } @@ -2569,14 +2498,6 @@ public class JBTabsImpl extends JComponent return myBorder; } - @NotNull - public JBTabs addTabMouseMotionListener(@NotNull MouseMotionListener listener) { - removeListeners(); - myTabMouseListeners.add(listener); - addListeners(); - return this; - } - @NotNull public JBTabs addTabMouseListener(@NotNull MouseListener listener) { removeListeners(); @@ -2594,14 +2515,6 @@ public class JBTabsImpl extends JComponent return false; } - @NotNull - public JBTabs removeTabMouseListener(@NotNull MouseListener listener) { - removeListeners(); - myTabMouseListeners.remove(listener); - addListeners(); - return this; - } - private void addListeners() { for (TabInfo eachInfo : myVisibleInfos) { final TabLabel label = myInfo2Label.get(eachInfo); @@ -2646,20 +2559,12 @@ public class JBTabsImpl extends JComponent return this; } - public JBTabs removeListener(@NotNull final TabsListener listener) { - myTabListeners.remove(listener); - return this; - } - @Override public JBTabs setSelectionChangeHandler(SelectionChangeHandler handler) { mySelectionChangeHandler = handler; return this; } - protected void onPopup(final TabInfo popupInfo) { - } - public void setFocused(final boolean focused) { if (myFocused == focused) return; @@ -2698,16 +2603,10 @@ public class JBTabsImpl extends JComponent return size == -1 ? 1 : size; } - public boolean isPaintFocus() { + private boolean isPaintFocus() { return myPaintFocus; } - @NotNull - public JBTabsPresentation setAdjustBorders(final boolean adjust) { - myAdjustBorders = adjust; - return this; - } - @NotNull public JBTabsPresentation setActiveTabFillIn(@Nullable final Color color) { if (!isChanged(myActiveTabFillIn, color)) return this; @@ -2732,7 +2631,7 @@ public class JBTabsImpl extends JComponent } @Nullable - public Color getActiveTabFillIn() { + protected Color getActiveTabFillIn() { return myActiveTabFillIn; } @@ -2915,7 +2814,6 @@ public class JBTabsImpl extends JComponent return !myHorizontalSide; } - @Override public boolean isSideComponentOnTabs() { return mySideComponentOnTabs; } @@ -2975,7 +2873,7 @@ public class JBTabsImpl extends JComponent relayout(true, false); } - public boolean isRequestFocusOnLastFocusedComponent() { + private boolean isRequestFocusOnLastFocusedComponent() { return myRequestFocusOnLastFocusedComponent; } @@ -3028,7 +2926,7 @@ public class JBTabsImpl extends JComponent } - public boolean isSelectionClick(final MouseEvent e, boolean canBeQuick) { + public static boolean isSelectionClick(final MouseEvent e, boolean canBeQuick) { if (e.getClickCount() == 1 || canBeQuick) { if (!e.isPopupTrigger()) { return e.getButton() == MouseEvent.BUTTON1 && !e.isControlDown() && !e.isAltDown() && !e.isMetaDown(); @@ -3120,25 +3018,16 @@ public class JBTabsImpl extends JComponent return this; } - void reallocate(TabInfo source, TabInfo target, boolean before) { + void reallocate(TabInfo source, TabInfo target) { if (source == target || source == null || target == null) return; final int targetIndex = myVisibleInfos.indexOf(target); - final int sourceIndex = myVisibleInfos.indexOf(source); - - boolean needsValidation = false; myVisibleInfos.remove(source); myVisibleInfos.add(targetIndex, source); - needsValidation = true; - //if (before && targetIndex < sourceIndex || !before && targetIndex > sourceIndex) { - //} - - if (needsValidation) { - invalidate(); - relayout(true, true); - } + invalidate(); + relayout(true, true); } boolean isHorizontalTabs() { @@ -3152,10 +3041,6 @@ public class JBTabsImpl extends JComponent } } - public boolean isUseBufferedPaint() { - return myUseBufferedPaint; - } - public void setUseBufferedPaint(boolean useBufferedPaint) { myUseBufferedPaint = useBufferedPaint; revalidate(); @@ -3280,13 +3165,11 @@ public class JBTabsImpl extends JComponent return myDropInfoIndex; } - @Override public boolean isEmptyVisible() { return myVisibleInfos.isEmpty(); } - @Override - public int getInterTabSpaceLength() { + public static int getInterTabSpaceLength() { return 1; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java index 7dd868299501..d9abba6bb983 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java @@ -23,7 +23,7 @@ import java.util.List; public abstract class LayoutPassInfo { - public List myVisibleInfos; + public final List myVisibleInfos; protected LayoutPassInfo(List visibleInfos) { myVisibleInfos = visibleInfos; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ShapeTransform.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ShapeTransform.java index 3c9c8c5e0557..b7f0777d47ba 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ShapeTransform.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ShapeTransform.java @@ -27,23 +27,18 @@ public abstract class ShapeTransform { private Rectangle myShapeRect; - protected int myXTransform; - protected int myYTransform; - private boolean mySwap; + private final int myXTransform; + private final int myYTransform; + private final boolean mySwap; - public ShapeTransform(Rectangle shapeRect, int xTransform, int yTransform, boolean swap) { + protected ShapeTransform(Rectangle shapeRect, int xTransform, int yTransform, boolean swap) { myShapeRect = shapeRect; myXTransform = xTransform; myYTransform = yTransform; mySwap = swap; } - public ShapeTransform(int XTranform, int YTranform) { - myXTransform = XTranform; - myYTransform = YTranform; - } - - public final Rectangle getShapeRect() { + protected final Rectangle getShapeRect() { return myShapeRect; } @@ -63,22 +58,10 @@ public abstract class ShapeTransform { return deltaY * myYTransform; } - public final T transformX1(T o1, T o2) { - return (mySwap ? myYTransform : myXTransform) == 1 ? o1: o2; - } - - public final T transformX2(T o1, T o2) { - return (mySwap ? myYTransform : myXTransform) == 1 ? o2: o1; - } - public final T transformY1(T o1, T o2) { return (mySwap ? myXTransform : myYTransform) == 1 ? o1: o2; } - public final T transformY2(T o1, T o2) { - return (mySwap ? myXTransform : myYTransform) == 1 ? o2: o1; - } - public abstract Insets transformInsets(Insets insets); public abstract Line2D.Float transformLine(int x1, int y1, int x2, int y2); @@ -136,7 +119,7 @@ public abstract class ShapeTransform { return reset(null); } - public final ShapeTransform reset(Rectangle shapeRec) { + protected final ShapeTransform reset(Rectangle shapeRec) { myPath = new GeneralPath(); if (shapeRec != null) { myShapeRect = shapeRec; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java index ff7c60badee8..0c512c632510 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java @@ -58,16 +58,15 @@ public class TabLabel extends JPanel { protected ActionPanel myActionPanel; private boolean myCentered; - private final Wrapper myLabelPlaceholder = new Wrapper(); + private final Wrapper myLabelPlaceholder = new Wrapper(false); private final JBTabsImpl myTabs; - private BufferedImage myImage; - private BufferedImage myInactiveStateImage; private Rectangle myLastPaintedInactiveImageBounds; - private boolean myStretchedByWidth; public TabLabel(JBTabsImpl tabs, final TabInfo info) { + super(false); + myTabs = tabs; myInfo = info; myLabel.setOpaque(false); @@ -87,7 +86,7 @@ public class TabLabel extends JPanel { addMouseListener(new MouseAdapter() { public void mousePressed(final MouseEvent e) { - if (myTabs.isSelectionClick(e, false) && myInfo.isEnabled()) { + if (JBTabsImpl.isSelectionClick(e, false) && myInfo.isEnabled()) { final TabInfo selectedInfo = myTabs.getSelectedInfo(); if (selectedInfo != myInfo) { myInfo.setPreviousSelection(selectedInfo); @@ -148,29 +147,29 @@ public class TabLabel extends JPanel { if (myTabs.isDropTarget(myInfo)) return; if (myTabs.getSelectedInfo() != myInfo) { - myImage = null; doPaint(g); - } else if (!SystemInfo.isMac) { - myImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); - final Graphics2D lg = myImage.createGraphics(); - doPaint(lg); - lg.dispose(); } } + @Override + public void setBounds(Rectangle r) { + super.setBounds(r); + } + + @Override + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + } + public void paintImage(Graphics g) { final Rectangle b = getBounds(); - if (myImage != null) { - g.drawImage(myImage, b.x, b.y, getWidth(), getHeight(), null); - } else { - final Graphics lG = g.create(b.x, b.y, b.width, b.height); - try { - lG.setColor(Color.red); - doPaint(lG); - } - finally { - lG.dispose(); - } + final Graphics lG = g.create(b.x, b.y, b.width, b.height); + try { + lG.setColor(Color.red); + doPaint(lG); + } + finally { + lG.dispose(); } } @@ -291,7 +290,6 @@ public class TabLabel extends JPanel { myTabs.myActivePopup.addPopupMenuListener(myTabs); myTabs.myActivePopup.show(e.getComponent(), e.getX(), e.getY()); - myTabs.onPopup(myTabs.myPopupInfo); } @@ -350,7 +348,7 @@ public class TabLabel extends JPanel { return hasIcons; } - private void setIcon(final Icon icon, int layer) { + private void setIcon(@Nullable final Icon icon, int layer) { LayeredIcon layeredIcon = getLayeredIcon(); layeredIcon.setIcon(icon, layer); if (hasIcons()) { @@ -366,14 +364,6 @@ public class TabLabel extends JPanel { return myIcon; } - public void setAttraction(boolean enabled) { - getLayeredIcon().setLayerEnabled(1, enabled); - } - - public boolean isAttractionEnabled() { - return getLayeredIcon().isLayerEnabled(1); - } - public TabInfo getInfo() { return myInfo; } @@ -418,10 +408,6 @@ public class TabLabel extends JPanel { myTabs.revalidateAndRepaint(false); } - @Override - protected void processMouseEvent(final MouseEvent e) { - super.processMouseEvent(e); - } private void removeOldActionPanel() { if (myActionPanel != null) { @@ -435,7 +421,7 @@ public class TabLabel extends JPanel { } - private void setAttractionIcon(Icon icon) { + private void setAttractionIcon(@Nullable Icon icon) { if (myIcon.getIcon(0) == null) { setIcon(null, 1); myOverlayedIcon = icon; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLayout.java index 5ced062c8543..321413c79f7c 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLayout.java @@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull; import java.awt.*; public abstract class TabLayout { - private Rectangle myHeaderRect; public ShapeTransform createShapeTransform(Dimension dimension) { return createShapeTransform(new Rectangle(0, 0, dimension.width, dimension.height)); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java index 9cdfd6f61a9d..1d53f9a7b62f 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java @@ -34,12 +34,13 @@ public class TabsBorder { public TabsBorder(JBTabsImpl tabs) { myTabs = tabs; - myBorderSize = new Insets(tabs.getBorder(-1), tabs.getBorder(-1), tabs.getBorder(-1), tabs.getBorder(-1)); - myTabBorderSize = tabs.getBorder(-1); + myBorderSize = new Insets(JBTabsImpl.getBorder(-1), JBTabsImpl.getBorder(-1), JBTabsImpl.getBorder(-1), JBTabsImpl.getBorder(-1)); + myTabBorderSize = JBTabsImpl.getBorder(-1); } public JBTabsPresentation setPaintBorder(int top, int left, int right, int bottom) { - final Insets newBorder = new Insets(myTabs.getBorder(top), myTabs.getBorder(left), myTabs.getBorder(bottom), myTabs.getBorder(right)); + final Insets newBorder = new Insets( + JBTabsImpl.getBorder(top), JBTabsImpl.getBorder(left), JBTabsImpl.getBorder(bottom), JBTabsImpl.getBorder(right)); if (newBorder.equals(myBorderSize)) return myTabs; myBorderSize = newBorder; @@ -52,7 +53,7 @@ public class TabsBorder { } public JBTabsPresentation setTabSidePaintBorder(int size) { - final int newSize = myTabs.getBorder(size); + final int newSize = JBTabsImpl.getBorder(size); if (myTabBorderSize == newSize) return myTabs; myTabBorderSize = newSize; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/ScrollableSingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/ScrollableSingleRowLayout.java index 2dd158059ec7..2f1bc02924e2 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/ScrollableSingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/ScrollableSingleRowLayout.java @@ -65,7 +65,7 @@ public class ScrollableSingleRowLayout extends SingleRowLayout { } @Override - public void scrollSelectionInView(List visibleInfos) { + public void scrollSelectionInView() { myScrollSelectionInViewPending = true; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java index c971bda0306a..8e8956e5bc65 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java @@ -29,15 +29,15 @@ import java.util.List; public class SingleRowLayout extends TabLayout { - JBTabsImpl myTabs; + final JBTabsImpl myTabs; public SingleRowPassInfo myLastSingRowLayout; - final SingleRowLayoutStrategy myTop; - final SingleRowLayoutStrategy myLeft; - final SingleRowLayoutStrategy myBottom; - final SingleRowLayoutStrategy myRight; + private final SingleRowLayoutStrategy myTop; + private final SingleRowLayoutStrategy myLeft; + private final SingleRowLayoutStrategy myBottom; + private final SingleRowLayoutStrategy myRight; - public MoreTabsIcon myMoreIcon = new MoreTabsIcon() { + public final MoreTabsIcon myMoreIcon = new MoreTabsIcon() { @Nullable protected Rectangle getIconRec() { return myLastSingRowLayout != null ? myLastSingRowLayout.moreRect : null; @@ -54,8 +54,8 @@ public class SingleRowLayout extends TabLayout { public JPopupMenu myMorePopup; - public GhostComponent myLeftGhost = new GhostComponent(RowDropPolicy.first, RowDropPolicy.first); - public GhostComponent myRightGhost = new GhostComponent(RowDropPolicy.last, RowDropPolicy.first); + public final GhostComponent myLeftGhost = new GhostComponent(RowDropPolicy.first, RowDropPolicy.first); + public final GhostComponent myRightGhost = new GhostComponent(RowDropPolicy.last, RowDropPolicy.first); private enum RowDropPolicy { first, last @@ -136,7 +136,7 @@ public class SingleRowLayout extends TabLayout { return 0; } - public void scrollSelectionInView(List visibleInfos) { + public void scrollSelectionInView() { } public LayoutPassInfo layoutSingleRow(List visibleInfos) { @@ -202,7 +202,7 @@ public class SingleRowLayout extends TabLayout { data.toFitLength = getStrategy().getToFitLength(data); if (myTabs.isGhostsAlwaysVisible()) { - data.toFitLength -= myTabs.getGhostTabLength() * 2 + (myTabs.getInterTabSpaceLength() * 2); + data.toFitLength -= JBTabsImpl.getGhostTabLength() * 2 + (JBTabsImpl.getInterTabSpaceLength() * 2); } } @@ -218,9 +218,9 @@ public class SingleRowLayout extends TabLayout { private void layoutLabelsAndGhosts(final SingleRowPassInfo data) { if (data.firstGhostVisible || myTabs.isGhostsAlwaysVisible()) { - data.firstGhost = getStrategy().getLayoutRect(data, data.position, myTabs.getGhostTabLength()); + data.firstGhost = getStrategy().getLayoutRect(data, data.position, JBTabsImpl.getGhostTabLength()); myTabs.layout(myLeftGhost, data.firstGhost); - data.position += getStrategy().getLengthIncrement(data.firstGhost.getSize()) + myTabs.getInterTabSpaceLength(); + data.position += getStrategy().getLengthIncrement(data.firstGhost.getSize()) + JBTabsImpl.getInterTabSpaceLength(); } int deltaToFit = 0; @@ -257,9 +257,9 @@ public class SingleRowLayout extends TabLayout { boolean continueLayout = applyTabLayout(data, label, length, deltaToFit); data.position = getStrategy().getMaxPosition(label.getBounds()); - data.position += myTabs.getInterTabSpaceLength(); + data.position += JBTabsImpl.getInterTabSpaceLength(); - totalLength = getStrategy().getMaxPosition(label.getBounds()) - positionStart + myTabs.getInterTabSpaceLength(); + totalLength = getStrategy().getMaxPosition(label.getBounds()) - positionStart + JBTabsImpl.getInterTabSpaceLength(); if (!continueLayout) { layoutStopped = true; } @@ -270,7 +270,7 @@ public class SingleRowLayout extends TabLayout { } if (data.lastGhostVisible || myTabs.isGhostsAlwaysVisible()) { - data.lastGhost = getStrategy().getLayoutRect(data, data.position, myTabs.getGhostTabLength()); + data.lastGhost = getStrategy().getLayoutRect(data, data.position, JBTabsImpl.getGhostTabLength()); myTabs.layout(myRightGhost, data.lastGhost); } } @@ -344,7 +344,7 @@ public class SingleRowLayout extends TabLayout { protected int getRequiredLength(TabInfo eachInfo) { return getStrategy().getLengthIncrement(myTabs.myInfo2Label.get(eachInfo).getPreferredSize()) - + (myTabs.isEditorTabs() ? myTabs.getInterTabSpaceLength() : 0); + + (myTabs.isEditorTabs() ? JBTabsImpl.getInterTabSpaceLength() : 0); } @@ -358,7 +358,7 @@ public class SingleRowLayout extends TabLayout { private GhostComponent(final RowDropPolicy before, final RowDropPolicy after) { addMouseListener(new MouseAdapter() { public void mousePressed(final MouseEvent e) { - if (myTabs.isSelectionClick(e, true) && myInfo != null) { + if (JBTabsImpl.isSelectionClick(e, true) && myInfo != null) { myRowDropPolicy = before; myTabs.select(myInfo, true).doWhenDone(new Runnable() { public void run() { @@ -395,13 +395,13 @@ public class SingleRowLayout extends TabLayout { if (!data.firstGhostVisible && isFirstSide) { data.firstGhostVisible = !myTabs.isEditorTabs(); if (!myTabs.isGhostsAlwaysVisible() && !myTabs.isEditorTabs()) { - data.toFitLength -= myTabs.getGhostTabLength(); + data.toFitLength -= JBTabsImpl.getGhostTabLength(); } } else if (!data.lastGhostVisible && !isFirstSide) { data.lastGhostVisible = !myTabs.isEditorTabs(); if (!myTabs.isGhostsAlwaysVisible() && !myTabs.isEditorTabs()) { - data.toFitLength -= myTabs.getGhostTabLength(); + data.toFitLength -= JBTabsImpl.getGhostTabLength(); } } } @@ -422,7 +422,7 @@ public class SingleRowLayout extends TabLayout { Rectangle firstBounds = first.getBounds(); Rectangle secondBounds = second.getBounds(); - boolean between = false; + final boolean between; boolean horizontal = getStrategy() instanceof SingleRowLayoutStrategy.Horizontal; if (horizontal) { diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java index eef01235bbf2..b136b8e97ca5 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java @@ -25,8 +25,8 @@ import java.awt.*; public abstract class SingleRowLayoutStrategy { private static final int MIN_TAB_WIDTH = 120; - SingleRowLayout myLayout; - JBTabsImpl myTabs; + final SingleRowLayout myLayout; + final JBTabsImpl myTabs; protected SingleRowLayoutStrategy(final SingleRowLayout layout) { myLayout = layout; @@ -59,8 +59,6 @@ public abstract class SingleRowLayoutStrategy { public abstract boolean isToCenterTextWhenStretched(); - public abstract Dimension getCompSizeDelta(SingleRowPassInfo data); - public abstract ShapeTransform createShapeTransform(Rectangle rectangle); public abstract boolean canBeStretched(); @@ -182,7 +180,7 @@ public abstract class SingleRowLayoutStrategy { else { x = data.position + (data.lastGhostVisible ? data.lastGhost.width : 0); } - return new Rectangle(x, data.insets.top + myTabs.getSelectionTabVShift(), + return new Rectangle(x, data.insets.top + JBTabsImpl.getSelectionTabVShift(), data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.height - 1); } @@ -195,7 +193,7 @@ public abstract class SingleRowLayoutStrategy { final int vToolbarWidth = data.vToolbar != null ? data.vToolbar.getPreferredSize().width : 0; final int x = vToolbarWidth > 0 ? vToolbarWidth + 1 : 0; final int hToolbarHeight = !myTabs.isSideComponentOnTabs() && data.hToolbar != null ? data.hToolbar.getPreferredSize().height : 0; - final int y = data.compPosition + myTabs.myHeaderFitSize.height + (myTabs.isEditorTabs() ? 0 : 1) + + final int y = myTabs.myHeaderFitSize.height + (myTabs.isEditorTabs() ? 0 : 1) + (hToolbarHeight > 0 ? hToolbarHeight - 2 : 0); if (data.hToolbar != null) { @@ -218,11 +216,6 @@ public abstract class SingleRowLayoutStrategy { } } } - - public Dimension getCompSizeDelta(SingleRowPassInfo data) { - return new Dimension(); - } - } static class Bottom extends Horizontal { @@ -248,10 +241,6 @@ public abstract class SingleRowLayoutStrategy { data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.height - 1); } - public Dimension getCompSizeDelta(SingleRowPassInfo data) { - return new Dimension(0, -(myTabs.myHeaderFitSize.height + 1)); - } - @Override public ShapeTransform createShapeTransform(Rectangle labelRec) { return new ShapeTransform.Bottom(labelRec); @@ -276,10 +265,6 @@ public abstract class SingleRowLayoutStrategy { return myLayout.myMoreIcon.myIcon.getIconHeight() + 4; } - public Dimension getCompSizeDelta(SingleRowPassInfo data) { - return new Dimension(); - } - @Override public boolean canBeStretched() { return false; @@ -351,7 +336,7 @@ public abstract class SingleRowLayoutStrategy { } public Rectangle getMoreRect(final SingleRowPassInfo data) { - return new Rectangle(data.insets.left + myTabs.getSelectionTabVShift(), + return new Rectangle(data.insets.left + JBTabsImpl.getSelectionTabVShift(), myTabs.getHeight() - data.insets.bottom - data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.width - 1, data.moreRectAxisSize - 1); @@ -391,11 +376,6 @@ public abstract class SingleRowLayoutStrategy { myTabs.myHeaderFitSize.width - 1, data.moreRectAxisSize - 1); } - - @Override - public Dimension getCompSizeDelta(SingleRowPassInfo data) { - return new Dimension(-myTabs.myHeaderFitSize.width, 0); - } } -} \ No newline at end of file +} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowPassInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowPassInfo.java index 62c1b09172cb..25370ed9869d 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowPassInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowPassInfo.java @@ -26,20 +26,18 @@ import java.util.List; public class SingleRowPassInfo extends LayoutPassInfo { final Dimension layoutSize; - int contentCount; + final int contentCount; int position; int requiredLength; int toFitLength; public final List toLayout; public final List toDrop; - int moreRectAxisSize; + final int moreRectAxisSize; public Rectangle moreRect; public JComponent hToolbar; public JComponent vToolbar; - public int compPosition; - public Rectangle firstGhost; public boolean firstGhostVisible; @@ -48,17 +46,16 @@ public class SingleRowPassInfo extends LayoutPassInfo { public Insets insets; - private final JBTabsImpl myTabs; public JComponent comp; public Rectangle tabRectangle; - int scrollOffset; + final int scrollOffset; public SingleRowPassInfo(SingleRowLayout layout, List visibleInfos) { super(visibleInfos); - myTabs = layout.myTabs; - layoutSize = layout.myTabs.getSize(); - contentCount = myTabs.getTabCount(); + JBTabsImpl tabs = layout.myTabs; + layoutSize = tabs.getSize(); + contentCount = tabs.getTabCount(); toLayout = new ArrayList(); toDrop = new ArrayList(); moreRectAxisSize = layout.getStrategy().getMoreRectAxisSize(); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java index f2cdf9b374ef..1326531e2465 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java @@ -56,8 +56,8 @@ public class TableLayout extends TabLayout { eachX = data.toFitRec.x; } myTabs.layout(eachLabel, eachX, 0, size.width, 1); - eachX += size.width + myTabs.getInterTabSpaceLength(); - data.requiredWidth += size.width + myTabs.getInterTabSpaceLength(); + eachX += size.width + JBTabsImpl.getInterTabSpaceLength(); + data.requiredWidth += size.width + JBTabsImpl.getInterTabSpaceLength(); } int selectedRow = -1; @@ -84,7 +84,7 @@ public class TableLayout extends TabLayout { if (myTabs.getSelectedInfo() == eachInfo) { selectedRow = eachRow; } - eachX += size.width + myTabs.getInterTabSpaceLength(); + eachX += size.width + JBTabsImpl.getInterTabSpaceLength(); } else { eachTableRow = new TableRow(data); @@ -161,9 +161,9 @@ public class TableLayout extends TabLayout { label.setAlignmentToCenter(deltaToFit > 0); boolean lastCell = i == eachRow.myColumns.size() - 1; - eachX += width + (lastCell ? 0 : myTabs.getInterTabSpaceLength()); + eachX += width + (lastCell ? 0 : JBTabsImpl.getInterTabSpaceLength()); } - eachY += myTabs.myHeaderFitSize.height - 1 + myTabs.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0); + eachY += myTabs.myHeaderFitSize.height - 1 + JBTabsImpl.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0); row++; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java index d29ced04e289..33623bbd7278 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java @@ -27,15 +27,15 @@ import java.util.List; import java.util.Map; public class TablePassInfo extends LayoutPassInfo { - List table = new ArrayList(); + final List table = new ArrayList(); public Rectangle toFitRec; - Map myInfo2Row = new HashMap(); + final Map myInfo2Row = new HashMap(); int requiredWidth; int requiredRows; int rowToFitMaxX; - JBTabsImpl myTabs; + final JBTabsImpl myTabs; TablePassInfo(final JBTabsImpl tabs, List visibleInfos) { super(visibleInfos); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableRow.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableRow.java index 5cbab8c37389..7c40ed1cf204 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableRow.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableRow.java @@ -17,13 +17,13 @@ package com.intellij.ui.tabs.impl.table; import com.intellij.ui.tabs.TabInfo; -import java.util.List; import java.util.ArrayList; +import java.util.List; class TableRow { - TablePassInfo myData; - List myColumns = new ArrayList(); + private final TablePassInfo myData; + final List myColumns = new ArrayList(); int width; public TableRow(final TablePassInfo data) { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java index 08cc5c2d995f..069c6274969e 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -67,6 +67,7 @@ public class PluginInstaller { Messages.showErrorDialog(pluginNode.getName() + ": " + e.getMessage(), CommonBundle.message("title.error")); } }); + return false; } } return result; diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java index 4d533fc3a724..a074c9363748 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java @@ -300,22 +300,15 @@ public abstract class PluginManagerMain implements Disposable { ProgressManager.getInstance().run(new Task.Backgroundable(null, IdeBundle.message("progress.download.plugins"), true) { @Override public void run(@NotNull ProgressIndicator indicator) { - if (PluginInstaller.prepareToInstall(plugins, allPlugins)) { - ApplicationManager.getApplication().invokeLater(onSuccess); - result[0] = true; + try { + if (PluginInstaller.prepareToInstall(plugins, allPlugins)) { + ApplicationManager.getApplication().invokeLater(onSuccess); + result[0] = true; + } + } + finally { + cleanup.run(); } - } - - @Override - public void onCancel() { - cleanup.run(); - super.onCancel(); - } - - @Override - public void onSuccess() { - super.onSuccess(); - cleanup.run(); } }); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java index 72a05fb0fc29..551d8efcc8d9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java @@ -31,6 +31,7 @@ import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.Nullable; public class DuplicateAction extends EditorAction { public DuplicateAction() { @@ -68,6 +69,7 @@ public class DuplicateAction extends EditorAction { } } + @Nullable static Pair duplicateLinesRange(Editor editor, Document document, VisualPosition rangeStart, VisualPosition rangeEnd) { Pair lines = EditorUtil.calcSurroundingRange(editor, rangeStart, rangeEnd); int offset = editor.getCaretModel().getOffset(); @@ -76,6 +78,9 @@ public class DuplicateAction extends EditorAction { LogicalPosition nextLineStart = lines.second; int start = editor.logicalPositionToOffset(lineStart); int end = editor.logicalPositionToOffset(nextLineStart); + if (end <= start) { + return null; + } String s = document.getCharsSequence().subSequence(start, end).toString(); final int lineToCheck = nextLineStart.line - 1; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java index fc3c86c50aed..2560098f9902 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -40,7 +40,9 @@ public class DuplicateLinesAction extends EditorAction { VisualPosition rangeEnd = editor.offsetToVisualPosition(Math.max(selStart, selEnd)); final Pair copiedRange = DuplicateAction.duplicateLinesRange(editor, editor.getDocument(), rangeStart, rangeEnd); - editor.getSelectionModel().setSelection(copiedRange.first, copiedRange.second); + if (copiedRange != null) { + editor.getSelectionModel().setSelection(copiedRange.first, copiedRange.second); + } } else { VisualPosition caretPos = editor.getCaretModel().getVisualPosition(); diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java b/platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java index 5a061dfef07a..44ef8f368d44 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java @@ -42,9 +42,7 @@ public abstract class AbstractTitledSeparatorWithIcon extends JPanel { public AbstractTitledSeparatorWithIcon(@NotNull final Icon icon, @NotNull final Icon iconOpen, - @NotNull final String text, - final boolean smallFont, - final boolean boldFont) { + @NotNull final String text) { myIcon = icon; myIconOpen = iconOpen; setLayout(new GridBagLayout()); @@ -59,7 +57,7 @@ public abstract class AbstractTitledSeparatorWithIcon extends JPanel { new Insets(3, 0, 0, 0), 0, 0); add(mySeparator, gb); setBorder(IdeBorderFactory.createEmptyBorder(3, 0, 5, 5)); - myLabel.setFont(UIUtil.getBorderFont(smallFont ? UIUtil.FontSize.SMALL : UIUtil.FontSize.NORMAL, boldFont)); + myLabel.setFont(UIUtil.getTitledBorderFont()); myLabel.setForeground(UIUtil.getTitledBorderTitleColor()); originalText = text; myLabel.setText(UIUtil.replaceMnemonicAmpersand(originalText)); diff --git a/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java b/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java index fb3d91012efe..1e9af99d3528 100644 --- a/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java +++ b/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java @@ -29,9 +29,8 @@ import java.awt.*; public abstract class HideableDetailsUnderSeparator extends AbstractTitledSeparatorWithIcon { public HideableDetailsUnderSeparator(@NotNull Icon icon, @NotNull Icon iconOpen, - @NotNull String text, - boolean smallFont, boolean boldFont) { - super(icon, iconOpen, text, smallFont, boldFont); + @NotNull String text) { + super(icon, iconOpen, text); } public void on() { diff --git a/platform/platform-impl/src/com/intellij/ui/HideableTitledPanel.java b/platform/platform-impl/src/com/intellij/ui/HideableTitledPanel.java new file mode 100644 index 000000000000..783c47ca8aec --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/HideableTitledPanel.java @@ -0,0 +1,131 @@ +package com.intellij.ui; + +import com.intellij.openapi.util.IconLoader; +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author evgeny zakrevsky + */ +public class HideableTitledPanel extends JPanel { + Icon OFF_ICON = IconLoader.getIcon("/general/comboArrow.png"); + Icon ON_ICON = IconLoader.getIcon("/general/comboUpPassive.png"); + private TitledSeparatorWithMnemonic myTitledSeparator; + private boolean myOn; + private final JComponent myContent; + private Dimension myPreviousContentSize; + + public HideableTitledPanel(String title, JComponent content, boolean on) { + super(new BorderLayout()); + myContent = content; + add(myContent, BorderLayout.CENTER); + myTitledSeparator = new TitledSeparatorWithMnemonic(title, null); + add(myTitledSeparator, BorderLayout.NORTH); + myTitledSeparator.getLabel().setIcon(OFF_ICON); + + myTitledSeparator.getLabel().addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + if (myOn) { + off(); + } + else { + on(); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + UIUtil.setActionNameAndMnemonic(title, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (myOn) { + off(); + } + else { + on(); + } + } + }); + + setOn(on); + } + + public void setOn(boolean on) { + myOn = on; + if (myOn) { + on(); + } + else { + off(); + } + } + + protected void on() { + myOn = true; + myTitledSeparator.getLabel().setIcon(ON_ICON); + myContent.setVisible(true); + adjustWindow(); + invalidate(); + repaint(); + } + + private void adjustWindow() { + final Window window = SwingUtilities.getWindowAncestor(this); + if (window == null) return; + final Dimension size = window.getSize(); + final Dimension contentSize = myPreviousContentSize != null && myPreviousContentSize.width > 0 && myPreviousContentSize.height > 0 + ? myPreviousContentSize + : myContent.getPreferredSize(); + final Dimension newSize; + if (myOn) { + newSize = new Dimension(Math.max(size.width, myContent.getSize().width), size.height + contentSize.height); + } + else { + newSize = new Dimension(size.width, size.height - contentSize.height); + } + if (!newSize.equals(size)) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (window.isShowing()) { + window.setSize(newSize); + } + } + }); + } + } + + protected void off() { + myOn = false; + myTitledSeparator.getLabel().setIcon(OFF_ICON); + myContent.setVisible(false); + myPreviousContentSize = myContent.getSize(); + adjustWindow(); + invalidate(); + repaint(); + } + + public void setTitle(String title) { + myTitledSeparator.setText(title); + } + + @Override + public void setEnabled(boolean enabled) { + myTitledSeparator.myLabel.setForeground(enabled ? UIUtil.getActiveTextColor() : UIUtil.getInactiveTextColor()); + myContent.setEnabled(enabled); + } +} diff --git a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java index 2b86c4af99a6..8e80795c01c6 100644 --- a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java +++ b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java @@ -47,7 +47,7 @@ public abstract class SplitterWithSecondHideable { public SplitterWithSecondHideable(final boolean vertical, final String separatorText, final JComponent firstComponent, - final OnOffListener listener, final boolean boldFont) { + final OnOffListener listener) { myVertical = vertical; myListener = listener; myFictivePanel = new JPanel(new BorderLayout()); @@ -56,12 +56,13 @@ public abstract class SplitterWithSecondHideable { if (vertical) { icon = IconLoader.getIcon("/general/comboArrow.png"); openIcon = IconLoader.getIcon("/general/comboUpPassive.png"); - } else { + } + else { icon = IconLoader.getIcon("/general/comboArrowRight.png"); openIcon = IconLoader.getIcon("/general/comboArrowRightPassive.png"); } - myTitledSeparator = new AbstractTitledSeparatorWithIcon(icon, openIcon, separatorText, true, true) { + myTitledSeparator = new AbstractTitledSeparatorWithIcon(icon, openIcon, separatorText) { @Override protected RefreshablePanel createPanel() { return createDetails(); @@ -89,7 +90,7 @@ public abstract class SplitterWithSecondHideable { final int firstSize = vertical ? mySplitter.getFirstComponent().getHeight() : mySplitter.getFirstComponent().getWidth(); // !! order is important! first fix mySplitter.fixFirst(); - myListener.on((int) ((1 - proportion) * firstSize / proportion)); + myListener.on((int)((1 - proportion) * firstSize / proportion)); //mySplitter.setProportion(proportion); mySplitter.setSecondComponent(myDetailsComponent.getPanel()); mySplitter.revalidate(); @@ -111,66 +112,67 @@ public abstract class SplitterWithSecondHideable { } }; mySplitter = new PseudoSplitter(vertical) { - { - myTitledSeparator.mySeparator.addMouseListener(new MouseAdapter() { - @Override - public void mouseEntered(MouseEvent e) { - myTitledSeparator.mySeparator - .setCursor(myTitledSeparator.myOn ? new Cursor(Cursor.S_RESIZE_CURSOR) : new Cursor(Cursor.DEFAULT_CURSOR)); - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + { + myTitledSeparator.mySeparator.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + myTitledSeparator.mySeparator + .setCursor(myTitledSeparator.myOn ? new Cursor(Cursor.S_RESIZE_CURSOR) : new Cursor(Cursor.DEFAULT_CURSOR)); + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseExited(MouseEvent e) { - myTitledSeparator.mySeparator.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseExited(MouseEvent e) { + myTitledSeparator.mySeparator.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseClicked(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseClicked(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mousePressed(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mousePressed(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseReleased(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseReleased(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseDragged(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseDragged(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseMoved(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } - }); + @Override + public void mouseMoved(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } + }); - myTitledSeparator.mySeparator.addMouseMotionListener(new MouseMotionListener() { - @Override - public void mouseDragged(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseMotionEvent(e); - } + myTitledSeparator.mySeparator.addMouseMotionListener(new MouseMotionListener() { + @Override + public void mouseDragged(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseMotionEvent(e); + } - @Override - public void mouseMoved(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseMotionEvent(e); - } - }); - } - @Override - protected Divider createDivider() { + @Override + public void mouseMoved(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseMotionEvent(e); + } + }); + } + + @Override + protected Divider createDivider() { mySuperDivider = new MyDivider(); mySuperDivider.add(myTitledSeparator, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, @@ -178,22 +180,22 @@ public abstract class SplitterWithSecondHideable { return mySuperDivider; } - @Override - public int getDividerWidth() { + @Override + public int getDividerWidth() { return vertical ? myTitledSeparator.getHeight() : myTitledSeparator.getWidth(); } - class MyDivider extends Divider { - @Override - public void processMouseMotionEvent(MouseEvent e) { - super.processMouseMotionEvent(e); - } - - @Override - public void processMouseEvent(MouseEvent e) { - super.processMouseEvent(e); - } + class MyDivider extends Divider { + @Override + public void processMouseMotionEvent(MouseEvent e) { + super.processMouseMotionEvent(e); } + + @Override + public void processMouseEvent(MouseEvent e) { + super.processMouseEvent(e); + } + } }; mySplitter.setDoubleBuffered(true); mySplitter.setFirstComponent(firstComponent); @@ -201,7 +203,7 @@ public abstract class SplitterWithSecondHideable { //mySplitter.setShowDividerIcon(false); mySplitter.setProportion(1.0f); } - + public void setText(final String value) { myTitledSeparator.setText(value); } @@ -215,6 +217,7 @@ public abstract class SplitterWithSecondHideable { } protected abstract RefreshablePanel createDetails(); + protected abstract float getSplitterInitialProportion(); public float getUsedProportion() { @@ -224,11 +227,11 @@ public abstract class SplitterWithSecondHideable { public void initOn() { myTitledSeparator.initOn(); } - + public void on() { myTitledSeparator.on(); } - + public void off() { myTitledSeparator.off(); } diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index f9871e1aad9c..8efe3f1f88f3 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -577,6 +577,7 @@ inner.class.0.is.already.defined.in.class.1=Inner class {0} is already defined i class.0.already.exists=Class {0} already exists renaming.something=Renaming something renaming.0.1.to.2=Renaming {0} {1} to {2} +renaming.command.name=Renaming {0} 0.to.be.renamed.to.1.2={0} to be renamed to {1}{2} references.in.code.to.0=References in code to {0} rename.variables.title=Rename Variables diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index f9f1f22f99d2..f881b56a2886 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -118,6 +118,7 @@ debugger.valueTooltipAutoShow.description=Auto show tooltip on mouse over debugger.mayBringFrameToFrontOnBreakpoint=true debugger.breakpoint.message.full.trace=false debugger.breakpoint.message.full.trace.description='Log message to console' breakpoint action will out full stacktrace for the thread that hit the breakpoint +debugger.breakpoint.use.breakpoints.popup=false filesystem.useNative=true diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml index 9653aa92091e..39d5de208ebe 100644 --- a/platform/platform-resources/src/META-INF/xdebugger.xml +++ b/platform/platform-resources/src/META-INF/xdebugger.xml @@ -26,6 +26,9 @@ + + diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java index e06a7aed76b5..fed864a1432f 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java @@ -16,7 +16,6 @@ package com.intellij.openapi.vfs.local; import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.idea.Bombed; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Disposer; @@ -271,7 +270,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } } - @Bombed(user = "roman.shevchenko", year = 2012, month = Calendar.MAY, day = 15) +/* public void testSymlinkAboveWatchRoot() throws Exception { final File topDir = FileUtil.createTempDirectory("top.", null); final File topLink = SymlinkHandlingTest.createTempLink(topDir.getAbsolutePath(), "link"); @@ -299,7 +298,6 @@ public class FileWatcherTest extends PlatformLangTestCase { } } - @Bombed(user = "roman.shevchenko", year = 2012, month = Calendar.MAY, day = 15) public void testSymlinkBelowWatchRoot() throws Exception { final File targetDir = FileUtil.createTempDirectory("top.", null); final File file = FileUtil.createTempFile(targetDir, "test.", ".txt", true, false); @@ -327,6 +325,7 @@ public class FileWatcherTest extends PlatformLangTestCase { delete(targetDir); } } +*/ public void testSubst() throws Exception { if (!SystemInfo.isWindows) { diff --git a/platform/testFramework/src/com/intellij/mock/MockRunManager.java b/platform/testFramework/src/com/intellij/mock/MockRunManager.java index 8cb22fd675be..481ef662723b 100644 --- a/platform/testFramework/src/com/intellij/mock/MockRunManager.java +++ b/platform/testFramework/src/com/intellij/mock/MockRunManager.java @@ -129,6 +129,10 @@ public class MockRunManager extends RunManagerEx { return Collections.emptyList(); } + @Override + public void setBeforeRunTasks(RunConfiguration runConfiguration, List tasks, boolean addEnabledTemplateTasksIfAbsent) { + } + @Override public RunnerAndConfigurationSettings findConfigurationByName(@NotNull String name) { return null; diff --git a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java index 44024054e76d..880746145197 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java +++ b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -36,6 +36,7 @@ import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; @@ -44,15 +45,19 @@ import com.intellij.psi.PsiFile; import com.intellij.rt.execution.junit.FileComparisonFailure; import com.intellij.util.ConstantFunction; import com.intellij.util.Function; +import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; import junit.framework.Assert; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.lang.reflect.Field; import java.util.*; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -72,17 +77,17 @@ public class ExpectedHighlightingData { @NonNls private static final String ANY_TEXT = "*"; private final String myText; - private static class ExpectedHighlightingSet { + public static class ExpectedHighlightingSet { + private final HighlightSeverity severity; private final boolean endOfLine; - final boolean enabled; - final Set infos; - final HighlightSeverity severity; + private final boolean enabled; + private final Set infos; public ExpectedHighlightingSet(@NotNull HighlightSeverity severity, boolean endOfLine, boolean enabled) { + this.severity = severity; this.endOfLine = endOfLine; this.enabled = enabled; infos = new THashSet(); - this.severity = severity; } } @SuppressWarnings("WeakerAccess") @@ -114,10 +119,10 @@ public class ExpectedHighlightingData { myDocument = document; myFile = file; myText = document.getText(); - highlightingTypes = new LinkedHashMap(); + highlightingTypes = new LinkedHashMap(); new WriteCommandAction.Simple(file == null ? null : file.getProject()) { public void run() { - boolean checkWarnings= false; + boolean checkWarnings = false; boolean checkWeakWarnings = false; boolean checkInfos = false; @@ -138,13 +143,13 @@ public class ExpectedHighlightingData { initAdditionalHighlightingTypes(); } }.execute().throwException(); - } + public ExpectedHighlightingData(@NotNull final Document document, final boolean checkWarnings, final boolean checkWeakWarnings, final boolean checkInfos, - PsiFile file) { + @Nullable final PsiFile file) { this(document, file); if (checkWarnings) checkWarnings(); if (checkWeakWarnings) checkWeakWarnings(); @@ -290,6 +295,7 @@ public class ExpectedHighlightingData { TextAttributes forcedAttributes = null; if (foregroundColor != null) { + //noinspection MagicConstant forcedAttributes = new TextAttributes(Color.decode(foregroundColor), Color.decode(backgroundColor), Color.decode(effectColor), EffectType.valueOf(effectType), Integer.parseInt(fontType)); } @@ -334,15 +340,6 @@ public class ExpectedHighlightingData { private static final HighlightInfoType WHATEVER = new HighlightInfoType.HighlightInfoTypeImpl(); - public Collection getExtractedHighlightInfos(){ - final Collection result = new ArrayList(); - final Collection collection = highlightingTypes.values(); - for (ExpectedHighlightingSet set : collection) { - result.addAll(set.infos); - } - return result; - } - public void checkLineMarkers(Collection markerInfos, String text) { String fileName = myFile == null ? "" : myFile.getName() + ": "; String failMessage = ""; @@ -412,7 +409,7 @@ public class ExpectedHighlightingData { checkResult(infos, text, null); } - public void checkResult(Collection infos, String text, String filePath) { + public void checkResult(Collection infos, String text, @Nullable String filePath) { String fileName = myFile == null ? "" : myFile.getName() + ": "; String failMessage = ""; @@ -470,60 +467,84 @@ public class ExpectedHighlightingData { } } - private void compareTexts(Collection infos, String text, String failMessage, String filePath) { - final ArrayList list = new ArrayList(infos); - Collections.sort(list, new Comparator() { // by start offset descending then by end offset ascending + private void compareTexts(Collection infos, String text, String failMessage, @Nullable String filePath) { + String actual = composeText(highlightingTypes, infos, text); + if (filePath != null && !myText.equals(actual)) { + throw new FileComparisonFailure(failMessage, myText, actual, filePath); + } + Assert.assertEquals(failMessage + "\n", myText, actual); + Assert.fail(failMessage); + } + + public static String composeText(final Map types, Collection infos, String text) { + // filter highlighting data and map each highlighting to a tag name + List> list = ContainerUtil.mapNotNull(infos, new NullableFunction>() { @Override - public int compare(HighlightInfo o1, HighlightInfo o2) { - final int start = o2.startOffset - o1.startOffset; - return start != 0 ? start : o1.endOffset - o2.endOffset; + public Pair fun(HighlightInfo info) { + for (Map.Entry entry : types.entrySet()) { + final ExpectedHighlightingSet set = entry.getValue(); + if (set.enabled && set.severity == info.getSeverity() && set.endOfLine == info.isAfterEndOfLine) { + return Pair.create(entry.getKey(), info); + } + } + return null; } }); - StringBuilder sb = new StringBuilder(); + // sort filtered highlighting data by end offset in descending order + Collections.sort(list, new Comparator>() { + @Override + public int compare(Pair o1, Pair o2) { + HighlightInfo i1 = o1.second; + HighlightInfo i2 = o2.second; - int end = text.length(); - HighlightInfo prev = null; - String prevSeverity = null; - for (HighlightInfo info : list) { - for (Map.Entry entry : highlightingTypes.entrySet()) { - final ExpectedHighlightingSet set = entry.getValue(); - if (set.enabled - && set.severity == info.getSeverity() - && set.endOfLine == info.isAfterEndOfLine) { - final String severity = entry.getKey(); + int byEnds = i2.endOffset - i1.endOffset; + if (byEnds != 0) return byEnds; - if (prev != null && info.endOffset > prev.startOffset) { // nested ranges - Assert.assertTrue("Overlapped highlightings: " + info + " and " + prev, - info.endOffset >= prev.endOffset); + int byStarts = i1.startOffset - i2.startOffset; + if (byStarts != 0) return byStarts; - int offset = prevSeverity.length()*2 + 14 + (prev.description != null ? prev.description.length() : 4) + // open and closing tags - prev.endOffset - prev.startOffset + info.endOffset - prev.endOffset; - sb.insert(offset, ""); - sb.insert(0, text.substring(info.startOffset, prev.startOffset)); - sb.insert(0, "<" + severity + " descr=\"" + info.description + "\">"); - } - else { // sequential ranges - sb.insert(0, text.substring(info.endOffset, end)); - sb.insert(0, "<" + severity + " descr=\"" + info.description + "\">" + - text.substring(info.startOffset, info.endOffset) + - ""); - } + int bySeverity = i2.severity.compareTo(i1.severity); + if (bySeverity != 0) return bySeverity; - end = info.startOffset; - prev = info; - prevSeverity = severity; - break; - } + return Comparing.compare(i1.description, i2.description); } - } - sb.insert(0, text.substring(0, end)); + }); - if (filePath != null && !myText.equals(sb.toString())) { - throw new FileComparisonFailure(failMessage, myText, sb.toString(), filePath); + // combine highlighting data with original text + StringBuilder sb = new StringBuilder(); + Pair result = composeText(sb, list, 0, text, text.length(), 0); + sb.insert(0, text.substring(0, result.second)); + return sb.toString(); + } + + private static Pair composeText(StringBuilder sb, + List> list, int index, + String text, int endPos, int startPos) { + int i = index; + while (i < list.size()) { + Pair pair = list.get(i); + HighlightInfo info = pair.second; + if (info.endOffset < startPos) break; + String severity = pair.first; + HighlightInfo prev = i < list.size() - 1 ? list.get(i + 1).second : null; + + sb.insert(0, text.substring(info.endOffset, endPos)); + sb.insert(0, ""); + endPos = info.endOffset; + if (prev != null && prev.endOffset > info.startOffset) { + Pair result = composeText(sb, list, i + 1, text, endPos, info.startOffset); + i = result.first - 1; + endPos = result.second; + } + sb.insert(0, text.substring(info.startOffset, endPos)); + sb.insert(0, "<" + severity + " descr=\"" + info.description + "\">"); + + endPos = info.startOffset; + i++; } - Assert.assertEquals(failMessage + "\n", myText, sb.toString()); - Assert.fail(failMessage); + + return Pair.create(i, endPos); } private static boolean infosContainsExpectedInfo(Collection infos, HighlightInfo expectedInfo) { @@ -559,9 +580,9 @@ public class ExpectedHighlightingData { info.endOffset == expectedInfo.endOffset && info.isAfterEndOfLine == expectedInfo.isAfterEndOfLine && (expectedInfo.type == WHATEVER || expectedInfo.type.equals(info.type)) && - (Comparing.strEqual(ANY_TEXT, expectedInfo.description) || Comparing.strEqual(info.description, expectedInfo.description)) - && (expectedInfo.forcedTextAttributes == null || expectedInfo.getTextAttributes(null, null).equals(info.getTextAttributes(null, null))) - && (expectedInfo.forcedTextAttributesKey == null || expectedInfo.forcedTextAttributesKey.equals(info.forcedTextAttributesKey)) - ; + (Comparing.strEqual(ANY_TEXT, expectedInfo.description) || Comparing.strEqual(info.description, expectedInfo.description)) && + (expectedInfo.forcedTextAttributes == null || Comparing.equal(expectedInfo.getTextAttributes(null, null), + info.getTextAttributes(null, null))) && + (expectedInfo.forcedTextAttributesKey == null || expectedInfo.forcedTextAttributesKey.equals(info.forcedTextAttributesKey)); } } diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 576b80af610b..01fcccbf1368 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -468,7 +468,7 @@ public abstract class UsefulTestCase extends TestCase { } public static T assertInstanceOf(Object o, Class aClass) { - Assert.assertNotNull(o); + Assert.assertNotNull("Expected instance of: " + aClass.getName() + " actual: " + null, o); Assert.assertTrue("Expected instance of: " + aClass.getName() + " actual: " + o.getClass().getName(), aClass.isInstance(o)); return (T)o; } diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java b/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java new file mode 100644 index 000000000000..afcac8ac0cd0 --- /dev/null +++ b/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java @@ -0,0 +1,125 @@ +/* + * 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.testFramework; + +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.lang.annotation.HighlightSeverity; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class ExpectedHighlightingDataTest { + private static Map TYPES; + + @BeforeClass + public static void setUp() throws Exception { + TYPES = new HashMap(); + TYPES.put("err", new ExpectedHighlightingData.ExpectedHighlightingSet(HighlightSeverity.ERROR, false, true)); + TYPES.put("warn", new ExpectedHighlightingData.ExpectedHighlightingSet(HighlightSeverity.WARNING, false, true)); + } + + @AfterClass + public static void tearDown() throws Exception { + TYPES.clear(); + TYPES = null; + } + + @Test + public void empty() throws Exception { + doTest("text", Collections.emptyList(), "text"); + } + + @Test + public void sequential() throws Exception { + doTest("_my text_", + Arrays.asList(error(1, 3, "1"), error(4, 8, "2")), + "_my text_"); + } + + @Test + public void simpleNested() throws Exception { + doTest("[(nested)]", + Arrays.asList(error(1, 9, "1"), error(2, 8, "2")), + "[(nested)]"); + } + + @Test + public void deepNested() throws Exception { + doTest("m1(m2(m3(m4(x))))", + Arrays.asList(error(3, 16, "m1"), error(6, 15, "m2"), error(9, 14, "m3"), error(12, 13, "m4")), + "m1(m2(m3(m4(x))))"); + } + + @Test + public void sameStart() throws Exception { + doTest("same start", + Arrays.asList(error(0, 4, "1"), error(0, 10, "2")), + "same start"); + } + + @Test + public void sameEnd() throws Exception { + doTest("same end", + Arrays.asList(error(0, 8, "1"), error(5, 8, "2")), + "same end"); + } + + @Test + public void sameBothBounds() throws Exception { + doTest("same", + Arrays.asList(error(0, 4, "-"), warning(0, 4, "-")), + "same"); + } + + @Test + public void samePriority() throws Exception { + doTest("same", + Arrays.asList(warning(0, 4, "1"), warning(0, 4, "2")), + "same"); + } + + @Test + public void twoNests() throws Exception { + doTest("(two nests)", + Arrays.asList(error(0, 11, "-"), error(1, 4, "1"), error(5, 10, "2")), + "(two nests)"); + } + + @Test + public void realistic() throws Exception { + doTest("one and (two nests)", + Arrays.asList(error(4, 7, "-"), error(8, 19, "-"), error(9, 12, "1"), error(13, 18, "2")), + "one and (two nests)"); + } + + private static void doTest(String original, Collection highlighting, String expected) { + String text = ExpectedHighlightingData.composeText(TYPES, highlighting, original); + assertEquals(expected, text); + } + + private static HighlightInfo error(int start, int end, String description) { + return new HighlightInfo(HighlightInfoType.ERROR, start, end, description, null); + } + + private static HighlightInfo warning(int start, int end, String description) { + return new HighlightInfo(HighlightInfoType.WARNING, start, end, description, null); + } +} diff --git a/platform/util/src/com/intellij/openapi/ui/Splitter.java b/platform/util/src/com/intellij/openapi/ui/Splitter.java index 8e4b183ed269..a3b37c807ab5 100644 --- a/platform/util/src/com/intellij/openapi/ui/Splitter.java +++ b/platform/util/src/com/intellij/openapi/ui/Splitter.java @@ -244,8 +244,10 @@ public class Splitter extends JPanel { if (isHonorMinimumSize()) { - final double firstMinSize = getOrientation() ? myFirstComponent.getMinimumSize().getHeight() : myFirstComponent.getMinimumSize().getWidth(); - final double secondMinSize = getOrientation() ? mySecondComponent.getMinimumSize().getHeight() : mySecondComponent.getMinimumSize().getWidth(); + final double firstMinSize = + getOrientation() ? myFirstComponent.getMinimumSize().getHeight() : myFirstComponent.getMinimumSize().getWidth(); + final double secondMinSize = + getOrientation() ? mySecondComponent.getMinimumSize().getHeight() : mySecondComponent.getMinimumSize().getWidth(); if (firstComponentSize + secondComponentSize < firstMinSize + secondMinSize) { double proportion = firstMinSize / (firstMinSize + secondMinSize); @@ -269,19 +271,19 @@ public class Splitter extends JPanel { firstComponentSize = Math.floor(firstComponentSize); secondComponentSize = Math.floor(secondComponentSize); - + if (getOrientation()) { // fix flooring - secondComponentSize += (int) (height - firstComponentSize - secondComponentSize - dividerWidth); - + secondComponentSize += (int)(height - firstComponentSize - secondComponentSize - dividerWidth); + firstRect.setBounds(0, 0, (int)width, (int)firstComponentSize); dividerRect.setBounds(0, (int)firstComponentSize, (int)width, (int)dividerWidth); secondRect.setBounds(0, (int)(firstComponentSize + dividerWidth), (int)width, (int)secondComponentSize); } else { // fix flooring - secondComponentSize += (int) (width - firstComponentSize - secondComponentSize - dividerWidth); - + secondComponentSize += (int)(width - firstComponentSize - secondComponentSize - dividerWidth); + firstRect.setBounds(0, 0, (int)firstComponentSize, (int)height); dividerRect.setBounds((int)firstComponentSize, 0, (int)dividerWidth, (int)height); secondRect.setBounds((int)(firstComponentSize + dividerWidth), 0, (int)secondComponentSize, (int)height); @@ -485,16 +487,15 @@ public class Splitter extends JPanel { } Icon glueIcon = IconLoader.getIcon(isVerticalSplit ? "/general/splitGlueV.png" : "/general/splitGlueH.png"); - int leftInsetIcon = 1; - int leftInsetArrow = 0; - int glueFill = isVerticalSplit ? GridBagConstraints.VERTICAL : GridBagConstraints.HORIZONTAL; - add(new JLabel(glueIcon), new GridBagConstraints(0, 0, 1, 1, 0, 0, - GridBagConstraints.CENTER, GridBagConstraints.EAST, - new Insets(0, leftInsetIcon, 0, 0), 0, 0)); + add(new JLabel(glueIcon), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, + new Insets(0, 0, 0, 0), 0, 0)); if (myShowDividerControls && false) { + int glueFill = isVerticalSplit ? GridBagConstraints.VERTICAL : GridBagConstraints.HORIZONTAL; int xMask = isVerticalSplit ? 1 : 0; int yMask = isVerticalSplit ? 0 : 1; + int leftInsetArrow = 0; + int leftInsetIcon = 1; JLabel splitDownlabel = new JLabel(IconLoader.getIcon(isVerticalSplit ? "/general/splitDown.png" : "/general/splitRight.png")); splitDownlabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); @@ -509,7 +510,8 @@ public class Splitter extends JPanel { GridBagConstraints.NONE, new Insets(0, leftInsetArrow, 0, 0), 0, 0)); // add(new JLabel(glueIcon), - new GridBagConstraints(2 * xMask, 2 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, new Insets(0, leftInsetIcon, 0, 0), 0, 0)); + new GridBagConstraints(2 * xMask, 2 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, + new Insets(0, leftInsetIcon, 0, 0), 0, 0)); JLabel splitCenterlabel = new JLabel(IconLoader.getIcon(isVerticalSplit ? "/general/splitCenterV.png" : "/general/splitCenterH.png")); splitCenterlabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); @@ -522,7 +524,8 @@ public class Splitter extends JPanel { add(splitCenterlabel, new GridBagConstraints(3 * xMask, 3 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, leftInsetArrow, 0, 0), 0, 0)); add(new JLabel(glueIcon), - new GridBagConstraints(4 * xMask, 4 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, new Insets(0, leftInsetIcon, 0, 0), 0, 0)); + new GridBagConstraints(4 * xMask, 4 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, + new Insets(0, leftInsetIcon, 0, 0), 0, 0)); // JLabel splitUpLabel = new JLabel(IconLoader.getIcon(isVerticalSplit ? "/general/splitUp.png" : "/general/splitLeft.png")); splitUpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); @@ -539,7 +542,7 @@ public class Splitter extends JPanel { isVerticalSplit ? GridBagConstraints.WEST : GridBagConstraints.SOUTH, glueFill, new Insets(0, leftInsetIcon, 0, 0), 0, 0)); } - + revalidate(); repaint(); } @@ -552,13 +555,17 @@ public class Splitter extends JPanel { float proportion; if (getOrientation()) { if (getHeight() > 0) { - proportion = Math.min(1.0f, Math.max(.0f, Math.min(Math.max(getMinProportion(myFirstComponent), (float)myPoint.y / (float)Splitter.this.getHeight()), 1 - getMinProportion(mySecondComponent)))); + proportion = Math.min(1.0f, Math.max(.0f, Math + .min(Math.max(getMinProportion(myFirstComponent), (float)myPoint.y / (float)Splitter.this.getHeight()), + 1 - getMinProportion(mySecondComponent)))); setProportion(proportion); } } else { if (getWidth() > 0) { - proportion = Math.min(1.0f, Math.max(.0f, Math.min(Math.max(getMinProportion(myFirstComponent), (float)myPoint.x / (float)Splitter.this.getWidth()), 1 - getMinProportion(mySecondComponent)))); + proportion = Math.min(1.0f, Math.max(.0f, Math + .min(Math.max(getMinProportion(myFirstComponent), (float)myPoint.x / (float)Splitter.this.getWidth()), + 1 - getMinProportion(mySecondComponent)))); setProportion(proportion); } } @@ -595,9 +602,10 @@ public class Splitter extends JPanel { public void setResizeEnabled(boolean resizeEnabled) { myResizeEnabled = resizeEnabled; - if (! myResizeEnabled) { + if (!myResizeEnabled) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } else { + } + else { setCursor(getOrientation() ? Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); diff --git a/platform/util/src/com/intellij/util/ui/Centerizer.java b/platform/util/src/com/intellij/util/ui/Centerizer.java index 9b747d9df2cb..4f42ca3352de 100644 --- a/platform/util/src/com/intellij/util/ui/Centerizer.java +++ b/platform/util/src/com/intellij/util/ui/Centerizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -25,6 +25,7 @@ import java.awt.*; public class Centerizer extends JPanel { public Centerizer(@NotNull JComponent comp) { + super(false); setOpaque(false); setBorder(null); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 0a19f1839d11..89aa02faf0be 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -20,7 +20,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.*; +import com.intellij.ui.ColorUtil; +import com.intellij.ui.Gray; +import com.intellij.ui.PanelWithAnchor; +import com.intellij.ui.SideBorder; import com.intellij.util.ArrayUtil; import com.intellij.util.PairFunction; import com.intellij.util.Processor; @@ -40,15 +43,12 @@ import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import javax.swing.plaf.ComboBoxUI; import javax.swing.plaf.ProgressBarUI; -import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicComboBoxUI; -import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.plaf.basic.ComboPopup; import javax.swing.text.DefaultEditorKit; import javax.swing.text.JTextComponent; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; -import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.*; import java.awt.font.FontRenderContext; @@ -1562,26 +1562,9 @@ public class UIUtil { return BORDER_COLOR; } - public static Color getTitledBorderLineColor() { - return BORDER_COLOR; - } - public static Font getTitledBorderFont() { - return getLabelFont(); - } - - public static Font getBorderFont(@NotNull FontSize size, boolean isBold) { - Font defFont = getTitledBorderFont(); - if (size == FontSize.SMALL) { - defFont = defFont.deriveFont(Math.max(defFont.getSize() - 2f, 11f)); - } - if (size == FontSize.MINI) { - defFont = defFont.deriveFont(Math.max(defFont.getSize() - 4f, 9f)); - } - //if (isBold) { - // defFont = defFont.deriveFont(Font.BOLD); - //} - return defFont; + Font defFont = getLabelFont(); + return defFont.deriveFont(Math.max(defFont.getSize() - 2f, 11f)); } public static Color getTitledBorderTitleColor() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java index ff9008bb46f5..801082dc1f82 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java @@ -34,15 +34,14 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsConfiguration; import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.RefreshablePanel; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileWrapper; import com.intellij.openapi.vfs.encoding.EncodingManager; -import com.intellij.ui.SplitterWithSecondHideable; +import com.intellij.ui.HideableTitledPanel; import com.intellij.util.Consumer; -import com.intellij.util.OnOffListener; +import com.intellij.util.ui.FormBuilder; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -58,7 +57,7 @@ public class CreatePatchConfigurationPanel { private static final String SYSTEM_DEFAULT = IdeBundle.message("encoding.name.system.default"); public static final String ALL = "(All)"; - private JPanel myPanel; + private JPanel myMainPanel; private TextFieldWithBrowseButton myFileNameField; private JCheckBox myReversePatchCheckbox; private JComboBox myEncoding; @@ -70,17 +69,18 @@ public class CreatePatchConfigurationPanel { private List myChanges; private Collection myIncludedChanges; private SelectFilesToAddTextsToPatchPanel mySelectFilesToAddTextsToPatchPanel; - private SplitterWithSecondHideable mySplitterWithSecondHideable; + private HideableTitledPanel myHideableTitledPanel; + private JPanel myPanelWithSelectedFiles; public CreatePatchConfigurationPanel(final Project project) { myProject = project; - initUi(); + initMainPanel(); myFileNameField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { final FileSaverDialog dialog = FileChooserFactory.getInstance().createSaveFileDialog( - new FileSaverDescriptor("Save patch to", ""), myPanel); + new FileSaverDescriptor("Save patch to", ""), myMainPanel); final String path = FileUtil.toSystemIndependentName(myFileNameField.getText().trim()); final int idx = path.lastIndexOf("/"); VirtualFile baseDir = idx == -1 ? project.getBaseDir() : @@ -121,27 +121,6 @@ public class CreatePatchConfigurationPanel { }); myErrorLabel.setForeground(Color.RED); checkName(); - /*new AdjustComponentWhenShown() { - @Override - protected boolean init() { - if (myPanel.isVisible()) { - IdeFocusManager.findInstanceByComponent(myPanel).requestFocus(myFileNameField.getTextField(), true); - if (myIncludeBaseRevisionTextCheckBox.isVisible()) { - // a hack =( - final JDialog dialog = getParentDialog(); - final Dimension dialogSize = dialog.getSize(); - dialog.setSize(dialogSize.width, dialogSize.height + 1); - if (dialogSize.width < 500) { - dialog.setSize(500, dialogSize.height - 1); - } else { - dialog.setSize(dialogSize.width, dialogSize.height - 1); - } - dialog.repaint(); - } - } - return false; - } - }.install(myPanel);*/ initEncodingCombo(); } @@ -165,110 +144,31 @@ public class CreatePatchConfigurationPanel { if (SYSTEM_DEFAULT.equals(selectedItem)) { return EncodingManager.getInstance().getDefaultCharset(); } - return (Charset) selectedItem; + return (Charset)selectedItem; } - private void initUi() { - myPanel = new JPanel(new GridBagLayout()); - myPanel.setMinimumSize(new Dimension(400, -1)); - final GridBagConstraints gb = new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(1, 1, 1, 1), 0, 0); - gb.anchor = GridBagConstraints.WEST; - final JLabel createPatchLabel = new JLabel(VcsBundle.message("create.patch.file.path")); - myPanel.add(createPatchLabel, gb); - gb.anchor = GridBagConstraints.NORTHWEST; + private void initMainPanel() { myFileNameField = new TextFieldWithBrowseButton(); - ++ gb.gridx; - gb.fill = GridBagConstraints.HORIZONTAL; - gb.weightx = 1; - myPanel.add(myFileNameField, gb); - - /*gb.fill = GridBagConstraints.NONE; - gb.weightx = 0;*/ - gb.gridx = 0; - ++ gb.gridy; - gb.gridwidth = 2; myReversePatchCheckbox = new JCheckBox(VcsBundle.message("create.patch.reverse.patch.checkbox")); - ++ gb.gridy; - myPanel.add(myReversePatchCheckbox, gb); - ++ gb.gridy; - gb.gridwidth = 2; - - gb.anchor = GridBagConstraints.WEST; - myPanel.add(new JLabel("Encoding:"), gb); - ++ gb.gridx; - gb.anchor = GridBagConstraints.NORTHWEST; myEncoding = new JComboBox(); - myPanel.add(myEncoding, gb); - ++ gb.gridy; - - gb.gridx = 0; myIncludeBaseRevisionTextCheckBox = new JCheckBox("Include base revision text(s) into patch file"); - myPanel.add(myIncludeBaseRevisionTextCheckBox, gb); - ++ gb.gridy; - myErrorLabel = new JLabel(); - myPanel.add(myErrorLabel, gb); + + myMainPanel = FormBuilder.createFormBuilder() + .addLabeledComponent(VcsBundle.message("create.patch.file.path"), myFileNameField) + .addComponent(myReversePatchCheckbox) + .addLabeledComponent("Encoding:", myEncoding) + .addComponent(myIncludeBaseRevisionTextCheckBox) + .addComponent(myErrorLabel) + .getPanel(); } - private void initSplitter(Runnable inclusionListener) { + private void initPanelWithSelectedFiles(Runnable inclusionListener) { mySelectFilesToAddTextsToPatchPanel = new SelectFilesToAddTextsToPatchPanel(myProject, myChanges, myIncludedChanges, inclusionListener); - final Dimension preferredSize = myPanel.getPreferredSize(); - final JPanel wrapper = new JPanel(new BorderLayout()) { - @Override - public Dimension getPreferredSize() { - return preferredSize; - } - - @Override - public Dimension getMaximumSize() { - return preferredSize; - } - - @Override - public Dimension getMinimumSize() { - return preferredSize; - } - }; - wrapper.add(myPanel, BorderLayout.NORTH); - mySplitterWithSecondHideable = new SplitterWithSecondHideable(true, ALL, wrapper, new OnOffListener() { - @Override - public void on(Integer integer) { - VcsConfiguration.getInstance(myProject).CREATE_PATCH_EXPAND_DETAILS_DEFAULT = true; - final JDialog dialog = getParentDialog(); - final Dimension dialogSize = dialog.getSize(); - int width = dialogSize.width < 550 ? 550 : dialogSize.width; - dialog.setSize(width, dialogSize.height + integer); - dialog.repaint(); - } - - @Override - public void off(Integer integer) { - VcsConfiguration.getInstance(myProject).CREATE_PATCH_EXPAND_DETAILS_DEFAULT = false; - final JDialog dialog = getParentDialog(); - final Dimension dialogSize = dialog.getSize(); - dialog.setSize(dialogSize.width, dialogSize.height - integer); - dialog.repaint(); - } - }, false) { - @Override - protected RefreshablePanel createDetails() { - return mySelectFilesToAddTextsToPatchPanel; - } - - @Override - protected float getSplitterInitialProportion() { - return 0.3f; - } - }; - } - - private JDialog getParentDialog() { - Container parent = myPanel.getParent(); - while (! (parent instanceof JDialog)) { - parent = parent.getParent(); - } - return (JDialog)parent; + myHideableTitledPanel = new HideableTitledPanel("", mySelectFilesToAddTextsToPatchPanel.getPanel(), false); + myPanelWithSelectedFiles = new JPanel(new BorderLayout()); + myPanelWithSelectedFiles.add(myMainPanel, BorderLayout.NORTH); + myPanelWithSelectedFiles.add(myHideableTitledPanel, BorderLayout.CENTER); } public void showTextStoreOption(final boolean dvcsIsUsed) { @@ -276,29 +176,29 @@ public class CreatePatchConfigurationPanel { if (myChanges.size() > 0) { myIncludeBaseRevisionTextCheckBox.setVisible(true); - final VcsConfiguration configuration = VcsConfiguration.getInstance(myProject); - - boolean turnOn = dvcsIsUsed || configuration.INCLUDE_TEXT_INTO_PATCH; - myIncludeBaseRevisionTextCheckBox.setSelected(turnOn); - myIncludeBaseRevisionTextCheckBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - mySelectFilesToAddTextsToPatchPanel.setEnabled(myIncludeBaseRevisionTextCheckBox.isSelected()); - mySplitterWithSecondHideable.setEnabledColor(myIncludeBaseRevisionTextCheckBox.isSelected()); - } - }); final Runnable inclusionListener = new Runnable() { @Override public void run() { if (mySelectFilesToAddTextsToPatchPanel != null) { myIncludedChanges = mySelectFilesToAddTextsToPatchPanel.getIncludedChanges(); - mySplitterWithSecondHideable.setText("Selected: " + (myIncludedChanges.size() == myChanges.size() ? - "All" : ("" + myIncludedChanges.size() + " of " + myChanges.size()))); + myHideableTitledPanel.setTitle("Selected: " + (myIncludedChanges.size() == myChanges.size() ? + "All" : (myIncludedChanges.size() + " of " + myChanges.size()))); } } }; - initSplitter(inclusionListener); + initPanelWithSelectedFiles(inclusionListener); inclusionListener.run(); + + final VcsConfiguration configuration = VcsConfiguration.getInstance(myProject); + boolean turnOn = dvcsIsUsed || configuration.INCLUDE_TEXT_INTO_PATCH; + myIncludeBaseRevisionTextCheckBox.setSelected(turnOn); + myIncludeBaseRevisionTextCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + myHideableTitledPanel.setEnabled(myIncludeBaseRevisionTextCheckBox.isSelected()); + } + }); + myHideableTitledPanel.setEnabled(myIncludeBaseRevisionTextCheckBox.isSelected()); } } @@ -306,7 +206,8 @@ public class CreatePatchConfigurationPanel { final PatchNameChecker patchNameChecker = new PatchNameChecker(myFileNameField.getText()); if (patchNameChecker.nameOk()) { myErrorLabel.setText(""); - } else { + } + else { myErrorLabel.setText(patchNameChecker.getError()); } if (myOkEnabledListener != null) { @@ -315,7 +216,7 @@ public class CreatePatchConfigurationPanel { } public void onOk() { - if (myIncludeBaseRevisionTextCheckBox.isVisible() && ! myDvcsIsUsed) { + if (myIncludeBaseRevisionTextCheckBox.isVisible() && !myDvcsIsUsed) { final VcsConfiguration vcsConfiguration = VcsConfiguration.getInstance(myProject); vcsConfiguration.INCLUDE_TEXT_INTO_PATCH = myIncludeBaseRevisionTextCheckBox.isSelected(); } @@ -330,7 +231,7 @@ public class CreatePatchConfigurationPanel { } public JComponent getPanel() { - return ! myIncludeBaseRevisionTextCheckBox.isVisible() || myChanges.isEmpty() ? myPanel : mySplitterWithSecondHideable.getComponent(); + return !myIncludeBaseRevisionTextCheckBox.isVisible() || myChanges.isEmpty() ? myMainPanel : myPanelWithSelectedFiles; } public void installOkEnabledListener(final Consumer runnable) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java index 70779b8b6882..900ed610ff03 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java @@ -994,7 +994,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj setSize(dialogSize.width, dialogSize.height - integer); repaint(); } - }, true) { + }) { @Override protected RefreshablePanel createDetails() { initDetails(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.form b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.form index 38e9bfe42b08..15724dc45ceb 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.form +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.form @@ -37,7 +37,7 @@ - + diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java index 52fd4fce9305..4959cf997cf3 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java @@ -151,11 +151,6 @@ public class MultipleFileMergeDialog extends DialogWrapper { acceptRevision(false); } }); - myMergeButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - showMergeDialog(); - } - }); myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(final ListSelectionEvent e) { updateButtonState(); @@ -327,6 +322,22 @@ public class MultipleFileMergeDialog extends DialogWrapper { MergeVersion.MergeDocumentVersion.reportProjectFileChangeIfNeeded(myProject, file); } + private void createUIComponents() { + Action mergeAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + showMergeDialog(); + } + }; + mergeAction.putValue(DEFAULT_ACTION, Boolean.TRUE); + myMergeButton = createJButtonForAction(mergeAction); + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myTable; + } + private static String decodeContent(final VirtualFile file, final byte[] content) { return StringUtil.convertLineSeparators(CharsetToolkit.bytesToString(content, file.getCharset())); } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java index 405fdbf069fc..0961c416e82d 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java @@ -188,6 +188,10 @@ public abstract class XBreakpointType, P extends XBreak return null; } + public String getShortText(B breakpoint) { + return getDisplayText(breakpoint); + } + public interface XBreakpointCreator

{ @NotNull XBreakpoint

createBreakpoint(@Nullable P properties); diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpoint.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpoint.java index 318360c98dfa..14d4b7aae28f 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpoint.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpoint.java @@ -35,4 +35,6 @@ public interface XLineBreakpoint

extends XBreak @NotNull XLineBreakpointType

getType(); + + String getShortFilePath(); } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java index 5ae43ab881c2..2a3582d49377 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java @@ -71,7 +71,11 @@ public abstract class XLineBreakpointType

exten public abstract P createBreakpointProperties(@NotNull VirtualFile file, int line); public String getDisplayText(final XLineBreakpoint

breakpoint) { - return XDebuggerBundle.message("xbreakpoint.default.display.text", breakpoint.getLine() + 1, breakpoint.getPresentableFilePath()); + return fileLineDisplayText(breakpoint.getPresentableFilePath(), breakpoint.getLine()); + } + + private String fileLineDisplayText(String path, int line) { + return XDebuggerBundle.message("xbreakpoint.default.display.text", line + 1, path); } @NotNull @@ -87,6 +91,11 @@ public abstract class XLineBreakpointType

exten return null; } + @Override + public String getShortText(XLineBreakpoint

breakpoint) { + return fileLineDisplayText(breakpoint.getShortFilePath(), breakpoint.getLine()); + } + /** * Default line breakpoints aren't supported */ diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java new file mode 100644 index 000000000000..d22376203b93 --- /dev/null +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java @@ -0,0 +1,33 @@ +/* + * 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.xdebugger.breakpoints.ui; + +import com.intellij.ui.popup.util.ItemWrapper; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 5/9/12 + * Time: 4:48 AM + * To change this template use File | Settings | File Templates. + */ +public interface BreakpointItem extends ItemWrapper { + Object getBreakpoint(); + + boolean isEnabled(); + + void setEnabled(boolean state); +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java index 691a8a9363fb..b8c45e8f0b6f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java @@ -22,8 +22,8 @@ import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.impl.actions.*; import com.intellij.xdebugger.impl.actions.handlers.*; +import com.intellij.xdebugger.impl.breakpoints.XBreakpointPanelProvider; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; -import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointPanelProvider; import com.intellij.xdebugger.impl.evaluate.quick.XQuickEvaluateHandler; import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler; import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsAction.java index a8d205efd602..14b21b5834ec 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsAction.java @@ -25,8 +25,10 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.registry.Registry; import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointsConfigurationDialogFactory; +import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointsMasterDetailPopupFactory; public class ViewBreakpointsAction extends AnAction implements AnAction.TransparentUpdate { private Object myInitialBreakpoint; @@ -52,8 +54,14 @@ public class ViewBreakpointsAction extends AnAction implements AnAction.Transpar } } - DialogWrapper dialog = BreakpointsConfigurationDialogFactory.getInstance(project).createDialog(myInitialBreakpoint); - dialog.show(); + if (Registry.is("debugger.breakpoint.use.breakpoints.popup")) { + BreakpointsMasterDetailPopupFactory. + getInstance(project).createPopup(myInitialBreakpoint).showCenteredInCurrentWindow(project); + } + else { + DialogWrapper dialog = BreakpointsConfigurationDialogFactory.getInstance(project).createDialog(myInitialBreakpoint); + dialog.show(); + } myInitialBreakpoint = null; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java index 4e3f17b778fc..ee402cd19137 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java @@ -400,8 +400,7 @@ public class XBreakpointBase, P extends XBreakpointP public boolean equals(Object obj) { return obj instanceof XLineBreakpointImpl.BreakpointGutterIconRenderer && getBreakpoint() == ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getBreakpoint() - && Comparing.equal(getIcon(), ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getIcon()) - ; + && Comparing.equal(getIcon(), ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getIcon()); } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java new file mode 100644 index 000000000000..16e180dc5e29 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java @@ -0,0 +1,131 @@ +/* + * 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.xdebugger.impl.breakpoints; + +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.xdebugger.XSourcePosition; +import com.intellij.xdebugger.breakpoints.XBreakpoint; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.xdebugger.impl.breakpoints.ui.XLightBreakpointPropertiesPanel; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: intendia +* Date: 10.05.12 +* Time: 1:14 +* To change this template use File | Settings | File Templates. +*/ +class XBreakpointItem implements BreakpointItem { + private final XBreakpoint myBreakpoint; + + public XBreakpointItem(XBreakpoint breakpoint) { + myBreakpoint = breakpoint; + } + + @Override + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + renderer.setIcon(getIcon()); + renderer.append(XBreakpointUtil.getShortText(myBreakpoint)); + } + + private Icon getIcon() { + return ((XBreakpointBase)myBreakpoint).getIcon(); + } + + @Override + public void updateMnemonicLabel(JLabel label) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void execute(Project project, JBPopup popup) { + final XSourcePosition position = myBreakpoint.getSourcePosition(); + if (position != null) { + position.createNavigatable(project).navigate(true); + popup.cancel(); + } + } + + @Override + public String speedSearchText() { + return ((XBreakpointBase)myBreakpoint).getType().getDisplayText(myBreakpoint); + } + + @Override + public String footerText() { + return ((XBreakpointBase)myBreakpoint).getType().getDisplayText(myBreakpoint); + } + + @Override + public void updateDetailView(DetailView panel) { + Project project = ((XBreakpointBase)myBreakpoint).getProject(); + + XLightBreakpointPropertiesPanel> propertiesPanel = + new XLightBreakpointPropertiesPanel>(project, getManager(), myBreakpoint, true); + propertiesPanel.loadProperties(); + panel.setDetailPanel(propertiesPanel.getMainPanel()); + + XSourcePosition sourcePosition = myBreakpoint.getSourcePosition(); + if (sourcePosition != null) { + panel.navigateInPreviewEditor(sourcePosition.getFile(), new LogicalPosition(sourcePosition.getLine(), sourcePosition.getOffset())); + } else { + panel.clearEditor(); + } + } + + private XBreakpointManagerImpl getManager() { + return ((XBreakpointBase)myBreakpoint).getBreakpointManager(); + } + + @Override + public boolean allowedToRemove() { + return !getManager().isDefaultBreakpoint(myBreakpoint); + } + + @Override + public void removed(Project project) { + final XBreakpointManagerImpl breakpointManager = getManager(); + new WriteAction() { + protected void run(final Result result) { + breakpointManager.removeBreakpoint(myBreakpoint); + } + }.execute(); + + } + + @Override + public Object getBreakpoint() { + return myBreakpoint; + } + + @Override + public boolean isEnabled() { + return myBreakpoint.isEnabled(); + } + + @Override + public void setEnabled(boolean state) { + myBreakpoint.setEnabled(state); + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java similarity index 50% rename from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java rename to platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java index 3d20b62da368..eaabb8bc8e7d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -13,8 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.xdebugger.impl.breakpoints.ui; +package com.intellij.xdebugger.impl.breakpoints; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.project.Project; @@ -22,22 +24,46 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.popup.util.ItemWrapper; +import com.intellij.ui.popup.util.SplitterItem; import com.intellij.xdebugger.breakpoints.*; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XDebuggerUtil; -import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; -import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl; +import com.intellij.xdebugger.impl.breakpoints.ui.AbstractBreakpointPanel; +import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; +import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointsPanel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * @author nik */ public class XBreakpointPanelProvider extends BreakpointPanelProvider { + private List myListeners = new CopyOnWriteArrayList(); + + @Override + public void addListener(BreakpointsListener listener, Project project) { + final MyXBreakpointListener listener1 = new MyXBreakpointListener(listener); + XDebuggerManager.getInstance(project).getBreakpointManager().addBreakpointListener(listener1); + myListeners.add(listener1); + } + + @Override + public void removeListener(BreakpointsListener listener) { + for (MyXBreakpointListener breakpointListener : myListeners) { + if (breakpointListener.myListener == listener) { + myListeners.remove(breakpointListener); + break; + } + } + } + public int getPriority() { return 0; } @@ -84,10 +110,73 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider result = new ArrayList(); + for (XBreakpointType type : XBreakpointUtil.getBreakpointTypes()) { + if (type.isAddBreakpointButtonVisible()) { + result.add(new AddXBreakpointAction(type)); + } + } + return result.toArray(new AnAction[result.size()]); + } + private static > XBreakpointsPanel createBreakpointsPanel(final Project project, DialogWrapper parentDialog, final XBreakpointType type) { return new XBreakpointsPanel(project, parentDialog, type); } public void onDialogClosed(final Project project) { } + + @Override + public void provideBreakpointItems(Project project, Collection items) { + final XBreakpointType[] types = XBreakpointUtil.getBreakpointTypes(); + final XBreakpointManager manager = XDebuggerManager.getInstance(project).getBreakpointManager(); + for (XBreakpointType type : types) { + final Collection> breakpoints = manager.getBreakpoints(type); + if (breakpoints.isEmpty()) continue; + items.add(new SplitterItem(type.getTitle())); + for (XBreakpoint breakpoint : breakpoints) { + items.add(new XBreakpointItem(breakpoint)); + } + } + } + + private static class MyXBreakpointListener implements XBreakpointListener> { + public BreakpointsListener myListener; + + public MyXBreakpointListener(BreakpointsListener listener) { + myListener = listener; + } + + @Override + public void breakpointAdded(@NotNull XBreakpoint breakpoint) { + myListener.breakpointsChanged(); + } + + @Override + public void breakpointRemoved(@NotNull XBreakpoint breakpoint) { + myListener.breakpointsChanged(); + } + + @Override + public void breakpointChanged(@NotNull XBreakpoint breakpoint) { + } + } + + private class AddXBreakpointAction extends AnAction { + + private XBreakpointType myType; + + public AddXBreakpointAction(XBreakpointType type) { + myType = type; + getTemplatePresentation().setIcon(type.getEnabledIcon()); + getTemplatePresentation().setText(type.getTitle()); + } + + @Override + public void actionPerformed(AnActionEvent e) { + myType.addBreakpoint(getEventProject(e), null); + } + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java index 262ed8a6d942..b685d3dca09a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java @@ -36,6 +36,10 @@ public class XBreakpointUtil { private XBreakpointUtil() { } + public static > String getShortText(B breakpoint) { + return getType(breakpoint).getShortText(breakpoint); + } + public static > String getDisplayText(@NotNull B breakpoint) { return getType(breakpoint).getDisplayText(breakpoint); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java index 4e4158543d49..dfe161a81663 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java @@ -46,6 +46,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.awt.dnd.DragSource; +import java.io.File; import java.util.List; /** @@ -123,6 +124,13 @@ public class XLineBreakpointImpl

extends XBreak return url != null ? url : ""; } + @Override + public String getShortFilePath() { + final String path = getPresentableFilePath(); + if (path.isEmpty()) return ""; + return new File(path).getName(); + } + @Nullable public RangeHighlighter getHighlighter() { return myHighlighter; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java index d9c48a7fd76d..b069579512b1 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java @@ -15,10 +15,12 @@ */ package com.intellij.xdebugger.impl.breakpoints.ui; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.ui.popup.util.ItemWrapper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,6 +30,15 @@ import java.util.Collection; * @author nik */ public abstract class BreakpointPanelProvider { + + public interface BreakpointsListener { + void breakpointsChanged(); + } + + public abstract void addListener(BreakpointsListener listener, Project project); + + public abstract void removeListener(BreakpointsListener listener); + public abstract int getPriority(); @Nullable @@ -39,6 +50,9 @@ public abstract class BreakpointPanelProvider { @NotNull public abstract Collection> getBreakpointPanels(@NotNull Project project, @NotNull DialogWrapper parentDialog); + public abstract AnAction[] getAddBreakpointActions(@NotNull Project project); + public abstract void onDialogClosed(final Project project); + public abstract void provideBreakpointItems(Project project, Collection items); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java new file mode 100644 index 000000000000..edc546a7446f --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -0,0 +1,287 @@ +/* + * 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.xdebugger.impl.breakpoints.ui; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.ex.CheckboxAction; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.JBPopupListener; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; +import com.intellij.ui.components.JBList; +import com.intellij.ui.popup.util.ItemWrapper; +import com.intellij.ui.popup.util.MasterDetailPopupBuilder; +import com.intellij.util.PlatformIcons; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.xdebugger.impl.DebuggerSupport; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 5/9/12 + * Time: 3:11 AM + * To change this template use File | Settings | File Templates. + */ +public class BreakpointsMasterDetailPopupFactory { + + private final List myBreakpointPanelProviders; + private Project myProject; + private BreakpointListModel myModel; + private MasterDetailPopupBuilder myPopupBuilder; + + public BreakpointsMasterDetailPopupFactory(Project project) { + myProject = project; + myBreakpointPanelProviders = new ArrayList(); + for (DebuggerSupport debuggerSupport : DebuggerSupport.getDebuggerSupports()) { + myBreakpointPanelProviders.add(debuggerSupport.getBreakpointPanelProvider()); + } + Collections.sort(myBreakpointPanelProviders, new Comparator() { + @Override + public int compare(BreakpointPanelProvider o1, BreakpointPanelProvider o2) { + return o2.getPriority() - o1.getPriority(); + } + }); + } + + public static BreakpointsMasterDetailPopupFactory getInstance(Project project) { + return ServiceManager.getService(project, BreakpointsMasterDetailPopupFactory.class); + } + + public JBPopup createPopup(@Nullable Object initialBreakpoint) { + final DefaultListSelectionModel selectionModel = new DefaultListSelectionModel(); + myModel = createBreakpointsItemsList(selectionModel); + final JBList list = new JBList(myModel); + list.setSelectionModel(selectionModel); + + selectInitial(initialBreakpoint, myModel, list); + + list.getEmptyText().setText("No Breakpoints"); + + DefaultActionGroup actions = getActions(list); + + myPopupBuilder = new MasterDetailPopupBuilder(myProject); + final JBPopup popup = myPopupBuilder. + setActionsGroup(actions). + setList(list). + setDelegate(new MasterDetailPopupBuilder.Delegate() { + @Override + public String getTitle() { + return "Breakpoints"; + } + + @Override + public void handleMnemonic(KeyEvent e, Project project, JBPopup popup) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean hasItemsWithMnemonic(Project project) { + return false; + } + }).setCloseOnEnter(false).createMasterDetailPopup(); + + popup.addListener(new JBPopupListener() { + @Override + public void beforeShown(LightweightWindowEvent event) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void onClosed(LightweightWindowEvent event) { + myModel.unsubscribe(); + } + }); + + return popup; + } + + private void selectInitial(Object initialBreakpoint, BreakpointListModel model, JBList list) { + for (int i = 0, l = model.size(); i < l; ++i) { + final ItemWrapper item = (ItemWrapper)model.get(i); + if (item instanceof BreakpointItem) { + if (((BreakpointItem)item).getBreakpoint() == initialBreakpoint) { + list.setSelectedIndex(i); + break; + } + } + } + } + + private DefaultActionGroup getActions(final JBList list) { + DefaultActionGroup actions = new DefaultActionGroup(); + final DefaultActionGroup breakpointTypes = new DefaultActionGroup(); + for (BreakpointPanelProvider provider : myBreakpointPanelProviders) { + breakpointTypes.addAll(provider.getAddBreakpointActions(myProject)); + } + actions.add(new AnAction("Add Breakpoint", null, PlatformIcons.ADD_ICON) { + @Override + public void actionPerformed(AnActionEvent e) { + + JBPopupFactory.getInstance() + .createActionGroupPopup(null, breakpointTypes, e.getDataContext(), JBPopupFactory.ActionSelectionAid.NUMBERING, false) + .showUnderneathOf(myPopupBuilder.getActionToolbar().getComponent()); + } + }); + actions.add(new AnAction("Remove Breakpoint", null, PlatformIcons.DELETE_ICON) { + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(MasterDetailPopupBuilder.allowedToRemoveSelectedItem(list, myProject)); + } + + @Override + public void actionPerformed(AnActionEvent e) { + MasterDetailPopupBuilder.removeSelectedItems(list, myProject); + } + }); + + actions.add(new CheckboxAction("Enabled"){ + { + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)), list); + } + @Override + public void update(AnActionEvent e) { + super.update(e); + e.getPresentation().setEnabled(list.getSelectedValue() instanceof BreakpointItem); + if (getCheckBox() != null) { + getCheckBox().setFocusable(false); + } + } + + @Override + public boolean isSelected(AnActionEvent e) { + return isSelectedBreakpointEnabled(list); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + setSelectedBreakpointEnabled(list, state); + } + }); + + return actions; + } + + private void setSelectedBreakpointEnabled(final JBList list, boolean state) { + final Object value = list.getSelectedValue(); + if (value instanceof BreakpointItem) { + ((BreakpointItem)value).setEnabled(state); + } + } + + private boolean isSelectedBreakpointEnabled(JBList list) { + final Object value = list.getSelectedValue(); + if (value instanceof BreakpointItem) { + return ((BreakpointItem)value).isEnabled(); + } + return false; + } + + private BreakpointListModel createBreakpointsItemsList(DefaultListSelectionModel selectionModel) { + final BreakpointListModel model = new BreakpointListModel(); + final ArrayList items = collectItems(); + for (ItemWrapper item : items) { + model.addElement(item); + } + model.subscribe(selectionModel); + return model; + } + + + private ArrayList collectItems() { + ArrayList items = new ArrayList(); + for (BreakpointPanelProvider panelProvider : myBreakpointPanelProviders) { + panelProvider.provideBreakpointItems(myProject, items); + } + return items; + } + + private class BreakpointListModel extends DefaultListModel { + List myListeners = new ArrayList(); + + private void subscribe(DefaultListSelectionModel selectionModel) { + for (BreakpointPanelProvider panelProvider : myBreakpointPanelProviders) { + final BreakpointPanelProvider.BreakpointsListener listener = new MyBreakpointsListener(this, selectionModel); + panelProvider.addListener(listener, myProject); + myListeners.add(listener); + } + } + + public void unsubscribe() { + for (int i = 0, size = myListeners.size(); i < size; i++) { + BreakpointPanelProvider.BreakpointsListener listener = myListeners.get(i); + myBreakpointPanelProviders.get(i).removeListener(listener); + } + } + + private class MyBreakpointsListener implements BreakpointPanelProvider.BreakpointsListener { + private final DefaultListModel myModel; + private DefaultListSelectionModel mySelectionModel; + + public MyBreakpointsListener(DefaultListModel model, DefaultListSelectionModel selectionModel) { + myModel = model; + mySelectionModel = selectionModel; + } + + @Override + public void breakpointsChanged() { + final ArrayList items = collectItems(); + if (!reallyChanged(items, myModel)) { + return; + } + rebuildModel(items, mySelectionModel, myModel); + } + + } + } + + private static void rebuildModel(ArrayList items, ListSelectionModel model, DefaultListModel model1) { + final int index = model.getLeadSelectionIndex(); + model1.removeAllElements(); + for (ItemWrapper item : items) { + model1.addElement(item); + } + model.setLeadSelectionIndex(index); + } + + private static boolean reallyChanged(List items, DefaultListModel model) { + if (items.size() != model.size()) return true; + for (int i = 0; i < model.size(); i++) { + final ItemWrapper item1 = items.get(i); + final ItemWrapper item2 = (ItemWrapper)model.get(i); + if (item1.getClass() != item2.getClass()) { + return true; + } + if (item1 instanceof BreakpointItem) { + if (((BreakpointItem)item1).getBreakpoint() != ((BreakpointItem)item2).getBreakpoint()) { + return true; + } + } + } + return false; + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/AddBreakpointAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XAddBreakpointAction.java similarity index 88% rename from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/AddBreakpointAction.java rename to platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XAddBreakpointAction.java index 6d6e2076c1a3..a0de8e158e2b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/AddBreakpointAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XAddBreakpointAction.java @@ -25,8 +25,8 @@ import java.util.Collection; /** * @author nik */ -public class AddBreakpointAction> extends XBreakpointPanelAction { - public AddBreakpointAction(final XBreakpointsPanel breakpointsPanel) { +public class XAddBreakpointAction> extends XBreakpointPanelAction { + public XAddBreakpointAction(final XBreakpointsPanel breakpointsPanel) { super(breakpointsPanel, XDebuggerBundle.message("xbreakpoints.dialog.button.add")); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java index ca55ec09655e..97273c7f7cdb 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java @@ -80,7 +80,7 @@ public class XBreakpointsPanel> extends AbstractBreakpo List> actions = new ArrayList>(); if (type.isAddBreakpointButtonVisible()) { - actions.add(new AddBreakpointAction(this)); + actions.add(new XAddBreakpointAction(this)); } actions.add(new GoToBreakpointAction(this, XDebuggerBundle.message("xbreakpoints.dialog.button.goto"), true)); actions.add(new GoToBreakpointAction(this, XDebuggerBundle.message("xbreakpoints.dialog.button.view.source"), false)); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form index 5946988f09c9..5169027b778f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form @@ -1,6 +1,6 @@

- + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java index 20c4cc5ff63d..27b426af12ee 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java @@ -55,6 +55,16 @@ public class XLightBreakpointPropertiesPanel> implement } } + private void createUIComponents() { + myMainPanel = new JPanel() { + @Override + public void removeNotify() { + super.removeNotify(); + saveProperties(); + } + }; + } + public interface Delegate { void showMoreOptions(); } @@ -158,7 +168,7 @@ public class XLightBreakpointPropertiesPanel> implement } } - public JComponent getMainPanel() { + public JPanel getMainPanel() { return myMainPanel; } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java index e2059dbddfd9..11b58784b313 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java @@ -268,7 +268,7 @@ public class DebuggerUIUtil { balloon.showInCenterOf(component); } else { - balloon.show(new RelativePoint(component, whereToShow), Balloon.Position.atRight); + balloon.show(new RelativePoint(component, whereToShow), Balloon.Position.below); } return balloon; diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/RelativeLayoutOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/RelativeLayoutOperation.java index 24e70befb986..4ec20a0066bf 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/RelativeLayoutOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/RelativeLayoutOperation.java @@ -134,42 +134,46 @@ public class RelativeLayoutOperation extends AbstractEditOperation { mySnapFeedback.repaint(); myBoundsFeedback.setLocation(myBounds.x, myBounds.y); - configureTextFeedback(); + configureTextFeedback(myHorizontalTextFeedback, myVerticalTextFeedback, myHorizontalPoint, myVerticalPoint, myContainerBounds); } - private void configureTextFeedback() { - myHorizontalTextFeedback.clear(); - myVerticalTextFeedback.clear(); + public static void configureTextFeedback(TextFeedback horizontalTextFeedback, + TextFeedback verticalTextFeedback, + SnapPoint horizontalPoint, + SnapPoint verticalPoint, + Rectangle containerBounds) { + horizontalTextFeedback.clear(); + verticalTextFeedback.clear(); - myHorizontalTextFeedback.setVisible(myHorizontalPoint != null); - if (myHorizontalPoint != null) { - myHorizontalPoint.addTextInfo(myHorizontalTextFeedback); + horizontalTextFeedback.setVisible(horizontalPoint != null); + if (horizontalPoint != null) { + horizontalPoint.addTextInfo(horizontalTextFeedback); - if (myVerticalPoint == null) { - myHorizontalTextFeedback.centerTop(myContainerBounds); + if (verticalPoint == null) { + horizontalTextFeedback.centerTop(containerBounds); } } - myVerticalTextFeedback.setVisible(myVerticalPoint != null); - if (myVerticalPoint != null) { - myVerticalPoint.addTextInfo(myVerticalTextFeedback); + verticalTextFeedback.setVisible(verticalPoint != null); + if (verticalPoint != null) { + verticalPoint.addTextInfo(verticalTextFeedback); - if (myHorizontalPoint == null) { - myVerticalTextFeedback.centerTop(myContainerBounds); + if (horizontalPoint == null) { + verticalTextFeedback.centerTop(containerBounds); } } - if (myHorizontalPoint != null && myVerticalPoint != null) { - Dimension size1 = myHorizontalTextFeedback.getPreferredSize(); - Dimension size2 = myVerticalTextFeedback.getPreferredSize(); + if (horizontalPoint != null && verticalPoint != null) { + Dimension size1 = horizontalTextFeedback.getPreferredSize(); + Dimension size2 = verticalTextFeedback.getPreferredSize(); int width = Math.max(size1.width, size2.width); int height = size1.height + size2.height; - int x = myContainerBounds.x + myContainerBounds.width / 2 - width / 2; - int y = myContainerBounds.y - height - 10; + int x = containerBounds.x + containerBounds.width / 2 - width / 2; + int y = containerBounds.y - height - 10; - myHorizontalTextFeedback.setBounds(x, y, width, size1.height); - myVerticalTextFeedback.setBounds(x, y + size1.height, width, size2.height); + horizontalTextFeedback.setBounds(x, y, width, size1.height); + verticalTextFeedback.setBounds(x, y + size1.height, width, size2.height); } } @@ -191,24 +195,10 @@ public class RelativeLayoutOperation extends AbstractEditOperation { } private void createPoints() { - List children = new ArrayList(myContainer.getChildren()); - children.removeAll(myComponents); - - Map relativeInfos = myContainer.getClientProperty(RelativeInfo.KEY); - for (RadComponent editComponent : myComponents) { - for (Iterator I = children.iterator(); I.hasNext(); ) { - RadComponent child = I.next(); - RelativeInfo info = relativeInfos.get(child); - if (info.contains(editComponent)) { - I.remove(); - } - } - } - myHorizontalPoints = new ArrayList(); myVerticalPoints = new ArrayList(); - for (RadComponent component : children) { + for (RadComponent component : getSnapComponents(myContainer, myComponents)) { myHorizontalPoints.add(new ComponentSnapPoint((RadViewComponent)component, true)); myVerticalPoints.add(new ComponentSnapPoint((RadViewComponent)component, false)); myVerticalPoints.add(new BaselineSnapPoint((RadViewComponent)component)); @@ -223,6 +213,24 @@ public class RelativeLayoutOperation extends AbstractEditOperation { myVerticalPoints.add(new AutoSnapPoint(container, false)); } + public static List getSnapComponents(RadComponent container, List components) { + List children = new ArrayList(container.getChildren()); + children.removeAll(components); + + Map relativeInfos = container.getClientProperty(RelativeInfo.KEY); + for (RadComponent editComponent : components) { + for (Iterator I = children.iterator(); I.hasNext(); ) { + RadComponent child = I.next(); + RelativeInfo info = relativeInfos.get(child); + if (info.contains(editComponent)) { + I.remove(); + } + } + } + + return children; + } + @Override public void execute() throws Exception { if (myContext.isCreate() || myContext.isPaste() || myContext.isAdd()) { diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/RelativeLayoutResizeOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/RelativeLayoutResizeOperation.java index 9f04adfd53c4..5df6f63217b3 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/RelativeLayoutResizeOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/RelativeLayoutResizeOperation.java @@ -15,10 +15,11 @@ */ package com.intellij.android.designer.designSurface.layout.actions; -import com.intellij.android.designer.designSurface.layout.relative.SnapPoint; -import com.intellij.android.designer.designSurface.layout.relative.SnapPointFeedbackHost; +import com.intellij.android.designer.designSurface.layout.RelativeLayoutOperation; +import com.intellij.android.designer.designSurface.layout.relative.*; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.designer.designSurface.EditOperation; +import com.intellij.designer.designSurface.FeedbackLayer; import com.intellij.designer.designSurface.OperationContext; import com.intellij.designer.designSurface.feedbacks.RectangleFeedback; import com.intellij.designer.designSurface.feedbacks.TextFeedback; @@ -26,8 +27,12 @@ import com.intellij.designer.designSurface.selection.DirectionResizePoint; import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator; import com.intellij.designer.model.RadComponent; import com.intellij.designer.utils.Position; +import com.intellij.openapi.util.Pair; +import com.intellij.ui.IdeBorderFactory; import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -37,15 +42,18 @@ public class RelativeLayoutResizeOperation implements EditOperation { public static final String TYPE = "relative_resize"; private final OperationContext myContext; + private List myComponents; private RadViewComponent myComponent; + private RadViewComponent myContainer; - private RectangleFeedback myFeedback; + private RectangleFeedback myBoundsFeedback; + private RectangleFeedback myWrapFeedback; private SnapPointFeedbackHost mySnapFeedback; private TextFeedback myHorizontalTextFeedback; private TextFeedback myVerticalTextFeedback; private Rectangle myContainerBounds; - private Rectangle myBounds; + private Dimension myWrapSize; private List myHorizontalPoints; private List myVerticalPoints; @@ -59,7 +67,9 @@ public class RelativeLayoutResizeOperation implements EditOperation { @Override public void setComponent(RadComponent component) { + myComponents = Arrays.asList(component); myComponent = (RadViewComponent)component; + myContainer = (RadViewComponent)myComponent.getParent(); } @Override @@ -67,17 +77,148 @@ public class RelativeLayoutResizeOperation implements EditOperation { } private void createFeedback() { + if (mySnapFeedback == null) { + myContainer.setClientProperty(SnapPointFeedbackHost.KEY, Boolean.TRUE); + + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + + myHorizontalTextFeedback = new TextFeedback(); + myHorizontalTextFeedback.setBorder(IdeBorderFactory.createEmptyBorder(0, 3, 2, 0)); + layer.add(myHorizontalTextFeedback); + + myVerticalTextFeedback = new TextFeedback(); + myVerticalTextFeedback.setBorder(IdeBorderFactory.createEmptyBorder(0, 3, 2, 0)); + layer.add(myVerticalTextFeedback); + + myBoundsFeedback = new RectangleFeedback(Color.blue, 2); + layer.add(myBoundsFeedback); + + int direction = myContext.getResizeDirection(); + if (direction == Position.EAST || direction == Position.SOUTH || direction == Position.SOUTH_EAST) { + Rectangle bounds = myComponent.getBounds(myContext.getArea().getFeedbackLayer()); + String width = myComponent.getTag().getAttributeValue("android:layout_width"); + String height = myComponent.getTag().getAttributeValue("android:layout_height"); + + Pair widthInfo = ResizeOperation.getDefaultSize(width, bounds.width); + Pair heightInfo = ResizeOperation.getDefaultSize(height, bounds.height); + + myWrapSize = new Dimension(widthInfo.first, heightInfo.first); + myComponent.calculateWrapSize(myWrapSize, bounds); + + Rectangle wrapBounds; + if (direction == Position.EAST) { + wrapBounds = new Rectangle(bounds.x, bounds.y, myWrapSize.width, bounds.height); + } + else if (direction == Position.SOUTH) { + wrapBounds = new Rectangle(bounds.x, bounds.y, bounds.width, myWrapSize.height); + } + else { + wrapBounds = new Rectangle(bounds.getLocation(), myWrapSize); + } + + myWrapFeedback = new RectangleFeedback(Color.green, 1); + myWrapFeedback.setBounds(wrapBounds); + layer.add(myWrapFeedback); + } + + myContainerBounds = myContainer.getBounds(layer); + + mySnapFeedback = new SnapPointFeedbackHost(); + mySnapFeedback.setBounds(myContainerBounds); + + createPoints(); + + layer.add(mySnapFeedback); + + layer.repaint(); + } } @Override public void showFeedback() { createFeedback(); - // TODO: Auto-generated method stub + + Rectangle bounds = myContext.getTransformedRectangle(myComponent.getBounds(myContext.getArea().getFeedbackLayer())); + bounds.width = Math.max(bounds.width, 0); + bounds.height = Math.max(bounds.height, 0); + + mySnapFeedback.clearAll(); + myHorizontalPoint = null; + myVerticalPoint = null; + + for (SnapPoint point : myHorizontalPoints) { + if (point.processBounds(myComponents, bounds, mySnapFeedback)) { + myHorizontalPoint = point; + break; + } + } + for (SnapPoint point : myVerticalPoints) { + if (point.processBounds(myComponents, bounds, mySnapFeedback)) { + myVerticalPoint = point; + break; + } + } + + mySnapFeedback.repaint(); + myBoundsFeedback.setBounds(bounds); + RelativeLayoutOperation.configureTextFeedback(myHorizontalTextFeedback, + myVerticalTextFeedback, + myHorizontalPoint, + myVerticalPoint, + myContainerBounds); } @Override public void eraseFeedback() { - // TODO: Auto-generated method stub + if (mySnapFeedback != null) { + myContainer.extractClientProperty(SnapPointFeedbackHost.KEY); + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + layer.remove(myHorizontalTextFeedback); + layer.remove(myVerticalTextFeedback); + layer.remove(myBoundsFeedback); + + if (myWrapFeedback != null) { + layer.remove(myWrapFeedback); + } + + layer.remove(mySnapFeedback); + layer.repaint(); + myHorizontalTextFeedback = null; + myVerticalTextFeedback = null; + myBoundsFeedback = null; + myWrapFeedback = null; + mySnapFeedback = null; + } + } + + private void createPoints() { + myHorizontalPoints = new ArrayList(); + myVerticalPoints = new ArrayList(); + + List snapComponents = RelativeLayoutOperation.getSnapComponents(myContainer, myComponents); + snapComponents.removeAll(myContext.getComponents()); + + int direction = myContext.getResizeDirection(); + if ((direction & Position.NORTH_SOUTH) != 0) { + createPoints(myVerticalPoints, snapComponents, false, direction); + } + if ((direction & Position.EAST_WEST) != 0) { + createPoints(myHorizontalPoints, snapComponents, true, direction); + } + } + + private void createPoints(List points, List snapComponents, boolean horizontal, int direction) { + for (RadComponent component : snapComponents) { + points.add(new ResizeComponentSnapPoint((RadViewComponent)component, horizontal)); + } + + points.add(new ResizeContainerSnapPoint(myContainer, horizontal)); + + if (direction == Position.EAST || direction == Position.SOUTH || direction == Position.SOUTH_EAST) { + points.add(new WrapSizeSnapPoint(myComponent, horizontal, myWrapSize)); + } + + points.add(new AutoResizeSnapPoint(myContainer, horizontal, direction)); } @Override @@ -87,7 +228,12 @@ public class RelativeLayoutResizeOperation implements EditOperation { @Override public void execute() throws Exception { - // TODO: Auto-generated method stub + if (myHorizontalPoint != null) { + myHorizontalPoint.execute(myComponents); + } + if (myVerticalPoint != null) { + myVerticalPoint.execute(myComponents); + } } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java index 34e2d1fa8125..c10c21fae8b6 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java @@ -43,7 +43,6 @@ public class ResizeOperation implements EditOperation { public final static Color blue = new Color(0, 50, 255); private static final int SNAP_DELTA = 4; - private static final int WRAP_CONTENT = 0 << 30; private final OperationContext myContext; private RadViewComponent myComponent; @@ -70,7 +69,6 @@ public class ResizeOperation implements EditOperation { myComponent = (RadViewComponent)component; Rectangle bounds = myComponent.getBounds(myContext.getArea().getFeedbackLayer()); - String width = myComponent.getTag().getAttributeValue("android:layout_width"); String height = myComponent.getTag().getAttributeValue("android:layout_height"); @@ -78,7 +76,7 @@ public class ResizeOperation implements EditOperation { Pair heightInfo = getDefaultSize(height, bounds.height); myWrapSize = new Dimension(widthInfo.first, heightInfo.first); - calculateWrapSize(bounds); + myComponent.calculateWrapSize(myWrapSize, bounds); myFillSize = new Dimension(widthInfo.second, heightInfo.second); calculateFillParentSize(bounds); @@ -86,33 +84,6 @@ public class ResizeOperation implements EditOperation { createStaticFeedback(bounds, width, height); } - private void calculateWrapSize(Rectangle bounds) { - if (myWrapSize.width == -1 || myWrapSize.height == -1) { - try { - Object viewObject = myComponent.getViewInfo().getViewObject(); - Class viewClass = viewObject.getClass(); - - viewClass.getMethod("forceLayout").invoke(viewObject); - viewClass.getMethod("measure", int.class, int.class).invoke(viewObject, WRAP_CONTENT, WRAP_CONTENT); - - if (myWrapSize.width == -1) { - myWrapSize.width = (Integer)viewClass.getMethod("getMeasuredWidth").invoke(viewObject); - } - if (myWrapSize.height == -1) { - myWrapSize.height = (Integer)viewClass.getMethod("getMeasuredHeight").invoke(viewObject); - } - } - catch (Throwable e) { - if (myWrapSize.width == -1) { - myWrapSize.width = bounds.width; - } - if (myWrapSize.height == -1) { - myWrapSize.height = bounds.height; - } - } - } - } - private void calculateFillParentSize(Rectangle bounds) { if (myFillSize.width == -1 || myFillSize.height == -1) { Rectangle parentBounds = myComponent.getParent().getBounds(myContext.getArea().getFeedbackLayer()); @@ -132,7 +103,7 @@ public class ResizeOperation implements EditOperation { } } - private static Pair getDefaultSize(String value, int size) { + public static Pair getDefaultSize(String value, int size) { int wrap = -1; int fill = -1; diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/AutoResizeSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/AutoResizeSnapPoint.java new file mode 100644 index 000000000000..2563f11eb425 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/AutoResizeSnapPoint.java @@ -0,0 +1,105 @@ +/* + * 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.android.designer.designSurface.layout.relative; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.designSurface.feedbacks.TextFeedback; +import com.intellij.designer.model.RadComponent; +import com.intellij.designer.utils.Position; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; + +import java.awt.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class AutoResizeSnapPoint extends SnapPoint { + private final int myDirection; + private int myMargin; + private int mySize; + + public AutoResizeSnapPoint(RadViewComponent container, boolean horizontal, int direction) { + super(container, horizontal); + myDirection = direction; + } + + @Override + public void addTextInfo(TextFeedback feedback) { + if (myMargin > 0) { + feedback.append("alignParent" + (myHorizontal ? "Left " : "Top "), SnapPointFeedbackHost.SNAP_ATTRIBUTES); + feedback.append(", margin" + (myHorizontal ? "Left " : "Top ") + Integer.toString(myMargin)); + feedback.dimension("dp"); + feedback.append(", "); + } + + if ((myDirection & Position.EAST_WEST) != 0) { + feedback.append("layout:width "); + } + else { + feedback.append("layout:height "); + } + + feedback.append(Integer.toString(mySize)); + feedback.dimension("dp"); + } + + @Override + public boolean processBounds(List components, Rectangle bounds, SnapPointFeedbackHost feedback) { + super.processBounds(components, bounds, feedback); + + if (myHorizontal) { + mySize = bounds.width; + + if ((myDirection & Position.WEST) != 0) { + myMargin = bounds.x - myBounds.x; + feedback.addVerticalLine(myBounds.x, myBounds.y, myBounds.height); + feedback.addHorizontalArrow(myBounds.x, bounds.y + bounds.height / 2, myMargin); + } + } + else { + mySize = bounds.height; + + if ((myDirection & Position.NORTH) != 0) { + myMargin = bounds.y - myBounds.y; + feedback.addHorizontalLine(myBounds.x, myBounds.y, myBounds.width); + feedback.addVerticalArrow(bounds.x + bounds.width / 2, myBounds.y, myMargin); + } + } + + return true; + } + + @Override + public void execute(final List components) throws Exception { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + XmlTag tag = ((RadViewComponent)components.get(0)).getTag(); + if (myMargin > 0) { + tag.setAttribute("android:layout_alignParent" + (myHorizontal ? "Left" : "Top"), "true"); + tag.setAttribute("android:layout_margin" + (myHorizontal ? "Left" : "Top"), Integer.toString(myMargin) + "dp"); + } + else { + ModelParser.deleteAttribute(tag, "android:layout_alignParent" + (myHorizontal ? "Right" : "Bottom")); + } + tag.setAttribute("android:layout_" + (myHorizontal ? "width" : "height"), Integer.toString(mySize) + "dp"); + } + }); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/BaselineSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/BaselineSnapPoint.java index e391ca5a84e7..a01db1391486 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/BaselineSnapPoint.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/BaselineSnapPoint.java @@ -32,7 +32,7 @@ public class BaselineSnapPoint extends SnapPoint { public BaselineSnapPoint(RadViewComponent component) { super(component, false); - myBaseline = ((RadViewComponent)component).getBaseline(); + myBaseline = component.getBaseline(); } @Override diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ComponentSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ComponentSnapPoint.java index 68c64c285354..438548f31839 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ComponentSnapPoint.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ComponentSnapPoint.java @@ -28,7 +28,7 @@ import java.util.List; * @author Alexander Lobas */ public class ComponentSnapPoint extends SnapPoint { - private Side myBeginSide; + protected Side myBeginSide; private Side myEndSide; public ComponentSnapPoint(RadViewComponent component, boolean horizontal) { diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ContainerSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ContainerSnapPoint.java index ca48d771434e..64075d082afc 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ContainerSnapPoint.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ContainerSnapPoint.java @@ -29,7 +29,7 @@ import java.util.List; * @author Alexander Lobas */ public class ContainerSnapPoint extends SnapPoint { - private Side mySide; + protected Side mySide; public ContainerSnapPoint(RadViewComponent container, boolean horizontal) { super(container, horizontal); @@ -139,7 +139,7 @@ public class ContainerSnapPoint extends SnapPoint { return false; } - private boolean processHorizontalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { + protected boolean processHorizontalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { int centerX = myBounds.x + myBounds.width / 2; int startX = centerX - SNAP_SIZE; @@ -156,7 +156,7 @@ public class ContainerSnapPoint extends SnapPoint { return false; } - private boolean processVerticalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { + protected boolean processVerticalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { int centerY = myBounds.y + myBounds.height / 2; int startY = centerY - SNAP_SIZE; diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeComponentSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeComponentSnapPoint.java new file mode 100644 index 000000000000..a8a239c52444 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeComponentSnapPoint.java @@ -0,0 +1,62 @@ +/* + * 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.android.designer.designSurface.layout.relative; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; + +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class ResizeComponentSnapPoint extends ComponentSnapPoint { + public ResizeComponentSnapPoint(RadViewComponent component, boolean horizontal) { + super(component, horizontal); + } + + @Override + public void execute(final List components) throws Exception { + super.execute(components); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + XmlTag tag = ((RadViewComponent)components.get(0)).getTag(); + + if (myBeginSide == Side.top) { + ModelParser.deleteAttribute(tag, "android:layout_alignParentTop"); + ModelParser.deleteAttribute(tag, "android:layout_marginTop"); + } + else if (myBeginSide == Side.bottom) { + ModelParser.deleteAttribute(tag, "android:layout_alignParentBottom"); + ModelParser.deleteAttribute(tag, "android:layout_marginBottom"); + } + else if (myBeginSide == Side.left) { + ModelParser.deleteAttribute(tag, "android:layout_alignParentLeft"); + ModelParser.deleteAttribute(tag, "android:layout_marginLeft"); + } + else if (myBeginSide == Side.right) { + ModelParser.deleteAttribute(tag, "android:layout_alignParentRight"); + ModelParser.deleteAttribute(tag, "android:layout_marginRight"); + } + } + }); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeContainerSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeContainerSnapPoint.java new file mode 100644 index 000000000000..5c6ea51cfb9e --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeContainerSnapPoint.java @@ -0,0 +1,73 @@ +/* + * 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.android.designer.designSurface.layout.relative; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; + +import java.awt.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class ResizeContainerSnapPoint extends ContainerSnapPoint { + public ResizeContainerSnapPoint(RadViewComponent container, boolean horizontal) { + super(container, horizontal); + } + + @Override + protected boolean processHorizontalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { + return false; + } + + @Override + protected boolean processVerticalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { + return false; + } + + @Override + public void execute(final List components) throws Exception { + super.execute(components); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + XmlTag tag = ((RadViewComponent)components.get(0)).getTag(); + + if (mySide == Side.top) { + ModelParser.deleteAttribute(tag, "android:layout_alignTop"); + ModelParser.deleteAttribute(tag, "android:layout_below"); + } + else if (mySide == Side.left) { + ModelParser.deleteAttribute(tag, "android:layout_alignBottom"); + ModelParser.deleteAttribute(tag, "android:layout_above"); + } + else if (mySide == Side.bottom) { + ModelParser.deleteAttribute(tag, "android:layout_alignLeft"); + ModelParser.deleteAttribute(tag, "android:layout_toRightOf"); + } + else if (mySide == Side.right) { + ModelParser.deleteAttribute(tag, "android:layout_alignRight"); + ModelParser.deleteAttribute(tag, "android:layout_toLeftOf"); + } + } + }); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/WrapSizeSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/WrapSizeSnapPoint.java new file mode 100644 index 000000000000..3a7891d30a43 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/WrapSizeSnapPoint.java @@ -0,0 +1,76 @@ +/* + * 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.android.designer.designSurface.layout.relative; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.designSurface.feedbacks.TextFeedback; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; + +import java.awt.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class WrapSizeSnapPoint extends SnapPoint { + private final Dimension myWrapSize; + + public WrapSizeSnapPoint(RadViewComponent component, boolean horizontal, Dimension wrapSize) { + super(component, horizontal); + myWrapSize = wrapSize; + } + + @Override + public void addTextInfo(TextFeedback feedback) { + feedback.append("layout:" + (myHorizontal ? "width " : "height ")); + feedback.snap("wrap_content"); + } + + @Override + public boolean processBounds(List components, Rectangle bounds, SnapPointFeedbackHost feedback) { + super.processBounds(components, bounds, feedback); + + if (myHorizontal) { + if (Math.abs(bounds.width - myWrapSize.width) < SNAP_SIZE) { + bounds.width = myWrapSize.width; + return true; + } + } + else { + if (Math.abs(bounds.height - myWrapSize.height) < SNAP_SIZE) { + bounds.height = myWrapSize.height; + return true; + } + } + + return false; + } + + @Override + public void execute(final List components) throws Exception { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + XmlTag tag = ((RadViewComponent)components.get(0)).getTag(); + ModelParser.deleteAttribute(tag, "android:layout_alignParent" + (myHorizontal ? "Right" : "Bottom")); + tag.setAttribute("android:layout_" + (myHorizontal ? "width" : "height"), "wrap_content"); + } + }); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java index 2fa5a8ea9f06..b7dbce9d9545 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java @@ -41,11 +41,6 @@ public class RadViewComponent extends RadVisualComponent { private XmlTag myTag; private List myProperties; - @Override - public List getChildren() { - return myChildren; - } - public XmlTag getTag() { return myTag; } @@ -75,6 +70,12 @@ public class RadViewComponent extends RadVisualComponent { myMargins = null; } + ////////////////////////////////////////////////////////////////////////////////////////// + // + // + // + ////////////////////////////////////////////////////////////////////////////////////////// + public String ensureId() { String id = getId(); if (id == null) { @@ -94,6 +95,12 @@ public class RadViewComponent extends RadVisualComponent { return "@id/" + idValue.substring(idValue.indexOf('/') + 1); } + ////////////////////////////////////////////////////////////////////////////////////////// + // + // + // + ////////////////////////////////////////////////////////////////////////////////////////// + public int getBaseline() { try { Object viewObject = myViewInfo.getViewObject(); @@ -128,6 +135,46 @@ public class RadViewComponent extends RadVisualComponent { return value == Integer.MIN_VALUE ? 0 : value; } + private static final int WRAP_CONTENT = 0 << 30; + + public void calculateWrapSize(Dimension wrapSize, Rectangle bounds) { + if (wrapSize.width == -1 || wrapSize.height == -1) { + try { + Object viewObject = myViewInfo.getViewObject(); + Class viewClass = viewObject.getClass(); + + viewClass.getMethod("forceLayout").invoke(viewObject); + viewClass.getMethod("measure", int.class, int.class).invoke(viewObject, WRAP_CONTENT, WRAP_CONTENT); + + if (wrapSize.width == -1) { + wrapSize.width = (Integer)viewClass.getMethod("getMeasuredWidth").invoke(viewObject); + } + if (wrapSize.height == -1) { + wrapSize.height = (Integer)viewClass.getMethod("getMeasuredHeight").invoke(viewObject); + } + } + catch (Throwable e) { + if (wrapSize.width == -1) { + wrapSize.width = bounds.width; + } + if (wrapSize.height == -1) { + wrapSize.height = bounds.height; + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // + // + ////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public List getChildren() { + return myChildren; + } + @Override public void delete() throws Exception { IdManager.get(this).removeComponent(this, true); diff --git a/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java b/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java index 4c72d48e355b..6771129b7fbb 100644 --- a/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java +++ b/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java @@ -47,14 +47,16 @@ public class GitQuickListContentProvider implements VcsQuickListContentProvider actions.add(new Separator(activeVcs.getDisplayName())); add("CheckinProject", manager, actions); + add("CheckinFiles", manager, actions); add("ChangesView.Rollback", manager, actions); + + addSeparator(actions); add("Vcs.ShowTabbedFileHistory", manager, actions); add("Annotate", manager, actions); add("Compare.SameVersion", manager, actions); addSeparator(actions); add("Git.Branches", manager, actions); - add("Git.Fetch", manager, actions); add("Git.Push", manager, actions); add("Git.Stash", manager, actions); add("Git.Unstash", manager, actions); diff --git a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java index 13491fd91270..52c77d4516cb 100644 --- a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java +++ b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java @@ -212,7 +212,7 @@ public class CherryPicker { public void run() { changeList.set(createChangeList(changes, commitMessage)); } - }, InvokeAfterUpdateMode.SYNCHRONOUS_NOT_CANCELLABLE, "", + }, InvokeAfterUpdateMode.SYNCHRONOUS_NOT_CANCELLABLE, "Cherry-pick", new Consumer() { public void consume(VcsDirtyScopeManager vcsDirtyScopeManager) { vcsDirtyScopeManager.filePathsDirty(paths, null); diff --git a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index d854a99bf2c6..1cb782365946 100644 --- a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -1,7 +1,6 @@ package org.jetbrains.jps.incremental.groovy; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; @@ -63,8 +62,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { Map class2Src = buildClassToSourceMap(chunk, context, toCompilePaths, moduleOutput); - String ideCharset = chunk.getProject().getProjectCharset(); - String encoding = !Comparing.equal(CharsetToolkit.getDefaultSystemCharset().name(), ideCharset) ? ideCharset : null; + final String encoding = context.getProjectDescriptor().getEncodingConfiguration().getPreferredModuleChunkEncoding(chunk); List patchers = Collections.emptyList(); //todo patchers final File tempFile = GroovycOSProcessHandler.fillFileWithGroovycParameters( compilerOutput, toCompilePaths, FileUtil.toSystemDependentName(moduleOutput), class2Src, encoding, patchers @@ -132,6 +130,11 @@ public class GroovyBuilder extends ModuleLevelBuilder { return moduleOutputPath.endsWith("/") ? moduleOutputPath : moduleOutputPath + "/"; } + @Override + public boolean shouldHonorFileEncodingForCompilation(File file) { + return isGroovyFile(file.getAbsolutePath()); + } + private String getCompilerOutput(String moduleOutputDir) throws IOException { return FileUtil.toCanonicalPath((myForStubs ? FileUtil.createTempDirectory("groovyStubs", null) : new File(moduleOutputDir)).getPath()); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index d0f4e3966024..1d0368b1bfff 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -1785,13 +1785,15 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { if (targetClass == null) return; addDynamicAnnotation(annotation, refExpr); - if (targetClass instanceof GrMemberOwner && targetClass.isWritable()) { + if (targetClass.isWritable()) { if (!(targetClass instanceof GroovyScriptClass)) { - annotation.registerFix(new CreateFieldFromUsageFix(refExpr, (GrMemberOwner)targetClass)); + if (targetClass instanceof GrMemberOwner) { + annotation.registerFix(new CreateFieldFromUsageFix(refExpr, (GrMemberOwner)targetClass)); + } } if (refExpr.getParent() instanceof GrCall && refExpr.getParent() instanceof GrExpression) { - annotation.registerFix(new CreateMethodFromUsageFix(refExpr, (GrMemberOwner)targetClass)); + annotation.registerFix(new CreateMethodFromUsageFix(refExpr, targetClass)); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java index 277c4cd30a1b..dcc285a8e05b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -23,6 +23,7 @@ import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -84,7 +85,8 @@ public abstract class CreateClassFix { GrMethod method = GroovyPsiElementFactory.getInstance(project).createConstructorFromText(name, paramTypes, paramNames, "{\n}"); method = targetClass.addMemberDeclaration(method, null); - IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true); + final PsiNameIdentifierOwner context = PsiTreeUtil.getParentOfType(myRefElement, PsiMethod.class, PsiClass.class); + IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true, context); } else { putCursor(project, targetClass.getContainingFile(), targetClass); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java index e051436b712f..8b02cc79bd6b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -18,9 +18,7 @@ package org.jetbrains.plugins.groovy.annotator.intentions; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -28,12 +26,8 @@ import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.intentions.base.IntentionUtils; import org.jetbrains.plugins.groovy.lang.editor.template.expressions.ChooseTypeExpression; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; @@ -45,10 +39,10 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; * @author ven */ public class CreateMethodFromUsageFix implements IntentionAction { - private final GrMemberOwner myTargetClass; + private final PsiClass myTargetClass; private final GrReferenceExpression myRefExpression; - public CreateMethodFromUsageFix(GrReferenceExpression refExpression, GrMemberOwner targetClass) { + public CreateMethodFromUsageFix(GrReferenceExpression refExpression, PsiClass targetClass) { myRefExpression = refExpression; myTargetClass = targetClass; } @@ -68,27 +62,21 @@ public class CreateMethodFromUsageFix implements IntentionAction { } public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - StringBuilder methodBuffer = new StringBuilder(); - if (PsiUtil.isInStaticContext(myRefExpression, myTargetClass)) methodBuffer.append("static "); - methodBuffer.append("Object ").append(myRefExpression.getReferenceName()).append(" ("); + final JVMElementFactory factory = JVMElementFactories.getFactory(myTargetClass.getLanguage(), project); + PsiMethod method = factory.createMethod(myRefExpression.getReferenceName(), PsiType.VOID); + if (PsiUtil.isInStaticContext(myRefExpression, myTargetClass)) { + method.getModifierList().setModifierProperty(PsiModifier.STATIC, true); + } + PsiType[] argTypes = PsiUtil.getArgumentTypes(myRefExpression, false); assert argTypes != null; - ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length]; - for (int i = 0; i < argTypes.length; i++) { - PsiType argType = argTypes[i]; - if (argType == null) argType = TypesUtil.getJavaLangObject(myRefExpression); - if (i > 0) methodBuffer.append(", "); - methodBuffer.append("Object o").append(i); - paramTypesExpressions[i] = - new ChooseTypeExpression(new TypeConstraint[]{SupertypeConstraint.create(argType)}, myRefExpression.getManager()); - } - methodBuffer.append(") {\n}"); - GrMethod method = GroovyPsiElementFactory.getInstance(project).createMethodFromText(methodBuffer.toString()); - GrMemberOwner owner = myTargetClass; + + ChooseTypeExpression[] paramTypesExpressions = setupParams(method, argTypes, factory); + TypeConstraint[] constraints = GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression)myRefExpression.getParent()); - PsiElement parent = myTargetClass instanceof GrTypeDefinition - ? ((GrTypeDefinition)myTargetClass).getBody() - : ((GroovyScriptClass)myTargetClass).getContainingFile(); + PsiElement parent = myTargetClass instanceof GroovyScriptClass + ? ((GroovyScriptClass)myTargetClass).getContainingFile() + : myTargetClass; if (PsiTreeUtil.isAncestor(parent, myRefExpression, false)) { PsiElement prevParent = PsiTreeUtil.findPrevParent(parent, myRefExpression); PsiElement sibling = PsiUtil.skipWhitespaces(prevParent.getNextSibling(), true); @@ -98,13 +86,28 @@ public class CreateMethodFromUsageFix implements IntentionAction { else { sibling = prevParent.getNextSibling(); } - method = owner.addMemberDeclaration(method, sibling); + method = (PsiMethod)myTargetClass.addAfter(method, sibling); } else { - method = owner.addMemberDeclaration(method, null); + method = (PsiMethod)myTargetClass.add(method); } - IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, owner, constraints, false); + final PsiElement context = PsiTreeUtil.getParentOfType(myRefExpression, PsiClass.class, PsiMethod.class); + IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, myTargetClass, constraints, false, context); + } + + private ChooseTypeExpression[] setupParams(PsiMethod method, PsiType[] argTypes, JVMElementFactory factory) { + final PsiParameterList parameterList = method.getParameterList(); + + ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length]; + for (int i = 0; i < argTypes.length; i++) { + PsiType argType = TypesUtil.unboxPrimitiveTypeWrapper(argTypes[i]); + if (argType == null) argType = TypesUtil.getJavaLangObject(myRefExpression); + final PsiParameter p = factory.createParameter("o", argType); + parameterList.add(p); + paramTypesExpressions[i] = new ChooseTypeExpression(new TypeConstraint[]{SupertypeConstraint.create(argType)}, myRefExpression.getManager()); + } + return paramTypesExpressions; } public boolean startInWriteAction() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java index d1df472da142..e484fcc94712 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java @@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElement; import com.intellij.util.containers.hash.HashSet; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.HashMap; @@ -36,8 +37,13 @@ class AlignmentProvider { private final Map> myTree = new HashMap>(); private final Map, Alignment> myAlignments = new HashMap, Alignment>(); private final Map, Boolean> myAllowBackwardShift = new HashMap, Boolean>(); + private final Map, Alignment.Anchor> myAnchor = new HashMap, Alignment.Anchor>(); public void addPair(PsiElement e1, PsiElement e2, Boolean allowBackwardShift) { + addPair(e1, e2, allowBackwardShift, null); + } + + public void addPair(PsiElement e1, PsiElement e2, @Nullable Boolean allowBackwardShift, @Nullable Alignment.Anchor anchor) { LOG.assertTrue(e1 != e2); final Set set1 = myTree.get(e1); @@ -46,9 +52,14 @@ class AlignmentProvider { if (set1 != null && set2 != null) { LOG.assertTrue(!myAlignments.containsKey(set1) || !myAlignments.containsKey(set2)); LOG.assertTrue(myAllowBackwardShift.get(set1).booleanValue() == myAllowBackwardShift.get(set2).booleanValue()); + LOG.assertTrue(myAnchor.get(set1) == myAnchor.get(set2)); if (allowBackwardShift != null) { LOG.assertTrue(myAllowBackwardShift.get(set1).booleanValue() == allowBackwardShift.booleanValue()); } + if (anchor != null) { + LOG.assertTrue(myAnchor.get(set1) == anchor); + } + if (myAlignments.containsKey(set2)) { for (Iterator iterator = set1.iterator(); iterator.hasNext(); ) { PsiElement element = iterator.next(); @@ -71,12 +82,18 @@ class AlignmentProvider { if (allowBackwardShift != null) { LOG.assertTrue(myAllowBackwardShift.get(set1).booleanValue() == allowBackwardShift.booleanValue()); } + if (anchor != null) { + LOG.assertTrue(myAnchor.get(set1) == anchor); + } addInternal(set1, e2); } else if (set2 != null) { if (allowBackwardShift != null) { LOG.assertTrue(myAllowBackwardShift.get(set2).booleanValue() == allowBackwardShift.booleanValue()); } + if (anchor != null) { + LOG.assertTrue(myAnchor.get(set2) == anchor); + } addInternal(set2, e1); } else { @@ -84,7 +101,7 @@ class AlignmentProvider { addInternal(set, e1); addInternal(set, e2); myAllowBackwardShift.put(set, allowBackwardShift); - + myAnchor.put(set, anchor); } } @@ -109,12 +126,17 @@ class AlignmentProvider { } private void add(PsiElement element, boolean allowBackwardShift) { + add(element, allowBackwardShift, Alignment.Anchor.LEFT); + } + + private void add(PsiElement element, boolean allowBackwardShift, @NotNull Alignment.Anchor anchor) { if (myTree.get(element) != null) return; final HashSet set = createHashSet(); set.add(element); myTree.put(element, set); myAllowBackwardShift.put(set, allowBackwardShift); + myAnchor.put(set, anchor); } @Nullable @@ -127,19 +149,24 @@ class AlignmentProvider { Alignment alignment = myAlignments.get(set); if (alignment != null) return alignment; - alignment = Alignment.createAlignment(myAllowBackwardShift.get(set)); + Alignment.Anchor anchor = myAnchor.get(set); + if (anchor == null) { + myAnchor.put(set, Alignment.Anchor.LEFT); + anchor = Alignment.Anchor.LEFT; + } + alignment = Alignment.createAlignment(myAllowBackwardShift.get(set), anchor); myAlignments.put(set, alignment); return alignment; } - public Aligner createAligner(PsiElement expression, boolean allowBackwardShift) { - Aligner aligner = new Aligner(allowBackwardShift); - aligner.append(expression); - return aligner; + public Aligner createAligner(boolean allowBackwardShift) { + return new Aligner(allowBackwardShift, Alignment.Anchor.LEFT); } - public Aligner createAligner(boolean allowBackwardShift) { - return new Aligner(allowBackwardShift); + public Aligner createAligner(PsiElement element, boolean allowBackwardShift, Alignment.Anchor anchor) { + final Aligner aligner = new Aligner(allowBackwardShift, anchor); + aligner.append(element); + return aligner; } /** @@ -151,9 +178,12 @@ class AlignmentProvider { class Aligner { private PsiElement myRef = null; private boolean allowBackwardShift = true; + @NotNull + private final Alignment.Anchor myAnchor; - Aligner(boolean allowBackwardShift) { + Aligner(boolean allowBackwardShift, @NotNull Alignment.Anchor anchor) { this.allowBackwardShift = allowBackwardShift; + myAnchor = anchor; } void append(@Nullable PsiElement element) { @@ -161,10 +191,10 @@ class AlignmentProvider { if (myRef == null) { myRef = element; - add(element, allowBackwardShift); + add(element, allowBackwardShift, myAnchor); } else { - addPair(myRef, element, allowBackwardShift); + addPair(myRef, element, allowBackwardShift, myAnchor); } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java index 80aabd5f05a9..1629934f5f81 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java @@ -228,7 +228,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes { else { currentGroup = new ArrayList(); for (LeafPsiElement expression : table) { - currentGroup.add(myAlignmentProvider.createAligner(expression, true)); + currentGroup.add(myAlignmentProvider.createAligner(expression, true, Alignment.Anchor.RIGHT)); } } } @@ -294,7 +294,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes { } private static boolean isTablePart(PsiElement psi) { - return psi instanceof GrBinaryExpression && mBOR == ((GrBinaryExpression)psi).getOperationTokenType(); + return psi instanceof GrBinaryExpression && (mBOR == ((GrBinaryExpression)psi).getOperationTokenType() || mLOR == ((GrBinaryExpression)psi).getOperationTokenType()); } private static List visibleChildren(ASTNode node) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties index 00d90c07f79d..f10fee212f67 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties @@ -1,9 +1,11 @@ +# suppress inspection "UnusedProperty" for whole file intention.category.groovy=Groovy intention.category.conversions=Expression conversions intention.category.closures=Closures intention.category.comments=Comments intention.category.groovy.style=Groovy-style intention.category.control.flow=Control Flow +intention.category.groovy.declaration=Declaration demorgans.law.intention.family.name=DeMorgan's Law demorgans.intention.name1=Replace ''\\&\\&'' with ''||'' demorgans.intention.name2=Replace ''||'' with ''\\&\\&'' @@ -84,8 +86,8 @@ convert.parameter.to.map.entry.intention.family.name=Convert method or closure p convert.parameter.to.map.entry.intention.name=Convert parameter to map entry find.method.ro.closure.usages.0=Searching for usages of enclosing {0} in project files conversion.not.allowed.in.non.groovy.files=Refactoring is not allowed for {0}s which have occurrences in non-Groovy files: \n -wrong.first.parameter.type={0} ''{1}'' is used with named arguments, but its first parameter ''{2}'' does not conform to Map type. -create.first.new=&Create new parameter for named arguments +wrong.first.parameter.type={0} ''{1}'' is used with named arguments, but its first parameter ''{2}'' does not conform to Map type. +create.first.new=&Create new parameter for named arguments do.not.create.first.new=Use &existing first parameter as map for named arguments convert.cannot.itself=Refactoring is not available for map parameter itself perform.refactoring=Performing refactoring diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java index eefcae38a423..5b25841fc6dd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -16,15 +16,16 @@ package org.jetbrains.plugins.groovy.intentions.base; import com.intellij.codeInsight.CodeInsightUtilBase; -import com.intellij.codeInsight.template.Template; -import com.intellij.codeInsight.template.TemplateBuilderImpl; -import com.intellij.codeInsight.template.TemplateManager; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateMethodFromUsageFix; +import com.intellij.codeInsight.template.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -33,12 +34,7 @@ import org.jetbrains.plugins.groovy.lang.editor.template.expressions.ChooseTypeE import org.jetbrains.plugins.groovy.lang.editor.template.expressions.ParameterNameExpression; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; /** @@ -47,6 +43,8 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; */ public class IntentionUtils { + private static final Logger LOG = Logger.getInstance(IntentionUtils.class); + public static void replaceExpression(@NotNull String newExpression, @NotNull GrExpression expression) throws IncorrectOperationException { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(expression.getProject()); final GrExpression newCall = factory.createExpressionFromText(newExpression); @@ -62,27 +60,29 @@ public class IntentionUtils { public static void createTemplateForMethod(PsiType[] argTypes, ChooseTypeExpression[] paramTypesExpressions, - GrMethod method, - GrMemberOwner owner, - TypeConstraint[] constraints, boolean isConstructor) { + PsiMethod method, + PsiClass owner, + TypeConstraint[] constraints, + boolean isConstructor, + final PsiElement context) { - Project project = owner.getProject(); - GrTypeElement typeElement = method.getReturnTypeElementGroovy(); + final Project project = owner.getProject(); + PsiTypeElement typeElement = method.getReturnTypeElement(); ChooseTypeExpression expr = new ChooseTypeExpression(constraints, PsiManager.getInstance(project)); TemplateBuilderImpl builder = new TemplateBuilderImpl(method); if (!isConstructor) { assert typeElement != null; builder.replaceElement(typeElement, expr); } - GrParameter[] parameters = method.getParameterList().getParameters(); + PsiParameter[] parameters = method.getParameterList().getParameters(); assert parameters.length == argTypes.length; for (int i = 0; i < parameters.length; i++) { - GrParameter parameter = parameters[i]; - GrTypeElement parameterTypeElement = parameter.getTypeElementGroovy(); + PsiParameter parameter = parameters[i]; + PsiTypeElement parameterTypeElement = parameter.getTypeElement(); builder.replaceElement(parameterTypeElement, paramTypesExpressions[i]); - builder.replaceElement(parameter.getNameIdentifierGroovy(), new ParameterNameExpression()); + builder.replaceElement(parameter.getNameIdentifier(), new ParameterNameExpression()); } - GrOpenBlock body = method.getBlock(); + PsiCodeBlock body = method.getBody(); assert body != null; PsiElement lbrace = body.getLBrace(); assert lbrace != null; @@ -91,11 +91,53 @@ public class IntentionUtils { method = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(method); Template template = builder.buildTemplate(); - Editor newEditor = QuickfixUtil.positionCursor(project, owner.getContainingFile(), method); + final PsiFile targetFile = owner.getContainingFile(); + final Editor newEditor = QuickfixUtil.positionCursor(project, targetFile, method); TextRange range = method.getTextRange(); newEditor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset()); TemplateManager manager = TemplateManager.getInstance(project); - manager.startTemplate(newEditor, template); + + + TemplateEditingListener templateListener = new TemplateEditingAdapter() { + @Override + public void templateFinished(Template template, boolean brokenOff) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument()); + final int offset = newEditor.getCaretModel().getOffset(); + PsiMethod method = PsiTreeUtil.findElementOfClassAtOffset(targetFile, offset - 1, PsiMethod.class, false); + if (context instanceof PsiMethod) { + final PsiTypeParameter[] typeParameters = ((PsiMethod)context).getTypeParameters(); + if (typeParameters.length > 0) { + for (PsiTypeParameter typeParameter : typeParameters) { + if (CreateMethodFromUsageFix.checkTypeParam(method, typeParameter)) { + final JVMElementFactory factory = JVMElementFactories.getFactory(method.getLanguage(), method.getProject()); + PsiTypeParameterList list = method.getTypeParameterList(); + if (list == null) { + PsiTypeParameterList newList = factory.createTypeParameterList(); + list = (PsiTypeParameterList)method.addAfter(newList, method.getModifierList()); + } + list.add(factory.createTypeParameter(typeParameter.getName(), typeParameter.getExtendsList().getReferencedTypes())); + } + } + } + } + if (method != null) { + try { + CreateFromUsageUtils.setupMethodBody(method); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + + CreateFromUsageUtils.setupEditor(method, newEditor); + } + } + }); + } + }; + manager.startTemplate(newEditor, template, templateListener); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java index 711886e11677..b2cb97656628 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -114,9 +114,10 @@ public class JavaStylePropertiesInvocationIntention extends Intention { else { method = call.resolveMethod(); if (!isSimplePropertySetter(method)) return false; + LOG.assertTrue(method != null); } - if (!GroovyNamesUtil.isValidReference(getPropertyNameByGetterName(method.getName(), true), + if (!GroovyNamesUtil.isValidReference(getPropertyNameBySetterName(method.getName()), ((GrReferenceExpression)expr).getQualifier() != null, call.getProject())) { return false; @@ -143,7 +144,7 @@ public class JavaStylePropertiesInvocationIntention extends Intention { PsiMethod method = call.resolveMethod(); if (!isSimplePropertyGetter(method)) return false; - + LOG.assertTrue(method != null); if (!GroovyNamesUtil.isValidReference(getPropertyNameByGetterName(method.getName(), true), ((GrReferenceExpression)expr).getQualifier() != null, call.getProject())) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/template/expressions/ChooseTypeExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/template/expressions/ChooseTypeExpression.java index b2cc84051433..d5e4a2dd2cbc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/template/expressions/ChooseTypeExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/template/expressions/ChooseTypeExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -22,6 +22,7 @@ import com.intellij.codeInsight.template.Expression; import com.intellij.codeInsight.template.ExpressionContext; import com.intellij.codeInsight.template.PsiTypeResult; import com.intellij.codeInsight.template.Result; +import com.intellij.openapi.editor.Document; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTypesUtil; @@ -86,7 +87,12 @@ public class ChooseTypeExpression extends Expression { PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); PsiType type = myTypePointer.getType(); if (type != null) { - return new PsiTypeResult(type, context.getProject()); + return new PsiTypeResult(type, context.getProject()) { + @Override + public void handleRecalc(PsiFile psiFile, Document document, int segmentStart, int segmentEnd) { + if (myItems.length <= 1) super.handleRecalc(psiFile, document, segmentStart, segmentEnd); + } + }; } return null; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java index 17c6dea2ca3b..379274b22dcc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -85,12 +85,17 @@ public class ParameterDeclaration implements GroovyElementTypes { PsiBuilder.Marker rb = builder.mark(); - TypeSpec.parseStrict(builder); + final ReferenceElement.ReferenceElementResult result = TypeSpec.parseStrict(builder); if (mIDENT.equals(builder.getTokenType()) || (mTRIPLE_DOT.equals(builder.getTokenType()))) { rb.drop(); } - else { + else if (result == ReferenceElement.ReferenceElementResult.mustBeType) { + rb.drop(); + pdMarker.error(GroovyBundle.message("identifier.expected")); + return true; + } + else { rb.rollbackTo(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index dabda0feaf5e..eb22d3caf49b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -158,6 +158,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return (GrExpression) topStatements[0]; } + @NotNull @Override public GrCodeReferenceElement createReferenceElementByType(PsiClassType type) { if (type instanceof GrClassReferenceType) { @@ -173,6 +174,34 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return createCodeReferenceElementFromText(type.getPresentableText()); } + @NotNull + @Override + public PsiTypeParameterList createTypeParameterList() { + return createMethodFromText("def <> void foo(){}").getTypeParameterList(); + } + + @NotNull + @Override + public PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes) { + StringBuilder builder = new StringBuilder(); + builder.append("def <").append(name); + if (superTypes.length > 0) { + builder.append(" extends "); + for (PsiClassType type : superTypes) { + builder.append(type.getCanonicalText()).append(','); + } + + builder.delete(builder.length() - 1, builder.length()); + } + builder.append("> void foo(){}"); + try { + return createMethodFromText(builder.toString()).getTypeParameters()[0]; + } + catch (RuntimeException e) { + throw new IncorrectOperationException("type parameter text: " + builder.toString()); + } + } + public GrVariableDeclaration createVariableDeclaration(@Nullable String[] modifiers, @Nullable GrExpression initializer, @Nullable PsiType type, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java index 6b81544df17a..2a9739930282 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -73,6 +73,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithme import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrMultiplicativeExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrRangeExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrSyntheticCodeBlock; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrSyntheticTypeElement; import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; @@ -90,6 +91,7 @@ public class PsiImplUtil { private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil"); private static final String MAIN_METHOD = "main"; public static final Key> PSI_CODE_BLOCK = Key.create("Psi_code_block"); + public static final Key> PSI_TYPE_ELEMENT = Key.create("psi.type.element"); private PsiImplUtil() { } @@ -535,6 +537,17 @@ public class PsiImplUtil { return newBody; } + public static PsiTypeElement getOrCreateTypeElement(@Nullable GrTypeElement typeElement) { + if (typeElement==null) return null; + + final SoftReference ref = typeElement.getUserData(PSI_TYPE_ELEMENT); + final PsiTypeElement element = ref == null ? null : ref.get(); + if (element != null) return element; + final GrSyntheticTypeElement newTypeElement = new GrSyntheticTypeElement(typeElement); + typeElement.putUserData(PSI_TYPE_ELEMENT, new SoftReference(newTypeElement)); + return newTypeElement; + } + public static T replaceBody(T newBody, GrStatement body, ASTNode node, Project project) { if (body == null || newBody == null) { throw new IncorrectOperationException(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java index 334b19bceb9d..6f8e7c9c1397 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -77,7 +77,7 @@ public abstract class GrVariableBaseImpl extends GrStubEl @Nullable public PsiTypeElement getTypeElement() { - return null; + return PsiImplUtil.getOrCreateTypeElement(getTypeElementGroovy()); } @Nullable diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java index d4f7b4cf2567..b62f4ef64866 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java index 1d8b1d0ec8af..9a02f6bc73fd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -292,7 +292,7 @@ public abstract class GrMethodBaseImpl extends GrStubElementBase i @Nullable public PsiTypeElement getReturnTypeElement() { - return null; + return PsiImplUtil.getOrCreateTypeElement(getReturnTypeElementGroovy()); } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodImpl.java index 6bc7c5348f43..ffc55d2e3a73 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -19,7 +19,9 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList; import org.jetbrains.plugins.groovy.lang.psi.stubs.GrMethodStub; /** @@ -36,6 +38,16 @@ public class GrMethodImpl extends GrMethodBaseImpl implements GrMethod { super(stub, GroovyElementTypes.METHOD_DEFINITION); } + @Override + public ASTNode addInternal(ASTNode first, ASTNode last, ASTNode anchor, Boolean before) { + if (first == last && first.getPsi() instanceof GrTypeParameterList) { + if (!getModifierList().hasExplicitVisibilityModifiers()) { + getModifierList().setModifierProperty(GrModifier.DEF, true); + } + } + return super.addInternal(first, last, anchor, before); + } + public String toString() { return "Method"; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticTypeElement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticTypeElement.java new file mode 100644 index 000000000000..f144f4a06026 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticTypeElement.java @@ -0,0 +1,123 @@ +/* + * 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 org.jetbrains.plugins.groovy.lang.psi.impl.synthetic; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.impl.light.LightElement; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; + +/** + * @author Max Medvedev + */ +public class GrSyntheticTypeElement extends LightElement implements PsiTypeElement { + @NotNull private final GrTypeElement myElement; + + public GrSyntheticTypeElement(@NotNull GrTypeElement element) { + super(element.getManager(), element.getLanguage()); + + myElement = element; + } + + @NotNull + @Override + public PsiType getType() { + return myElement.getType(); + } + + @Override + public PsiJavaCodeReferenceElement getInnermostComponentReferenceElement() { + return null; + } + + @Override + public PsiAnnotationOwner getOwner(PsiAnnotation annotation) { + return null; + } + + @Override + public PsiType getTypeNoResolve(@NotNull PsiElement context) { + return myElement.getType(); + } + + @NotNull + @Override + public PsiAnnotation[] getAnnotations() { + return PsiAnnotation.EMPTY_ARRAY; + } + + @NotNull + @Override + public PsiAnnotation[] getApplicableAnnotations() { + return PsiAnnotation.EMPTY_ARRAY; + } + + @Override + public PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) { + return null; + } + + @NotNull + @Override + public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + return "Synthetic PsiTypeElement"; + } + + @Override + public TextRange getTextRange() { + return myElement.getTextRange(); + } + + @Override + public int getTextOffset() { + return myElement.getTextOffset(); + } + + @Override + public String getText() { + return myElement.getText(); + } + + @Override + public boolean isValid() { + return myElement.isValid(); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor)visitor).visitTypeElement(this); + } + } + + @Override + public void acceptChildren(@NotNull PsiElementVisitor visitor) { + final PsiElement[] children = myElement.getChildren(); + for (PsiElement child : children) { + if (child instanceof GrTypeElement) { + PsiImplUtil.getOrCreateTypeElement((GrTypeElement)child).accept(visitor); + } + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeParameterListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeParameterListImpl.java index 197534082d94..f089d1a9f252 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeParameterListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeParameterListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -23,6 +23,7 @@ import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.stubs.EmptyStub; import com.intellij.util.ArrayFactory; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter; @@ -74,4 +75,35 @@ public class GrTypeParameterListImpl extends GrStubElementBase implem public void accept(GroovyElementVisitor visitor) { visitor.visitTypeParameterList(this); } + + @Override + public ASTNode addInternal(ASTNode first, ASTNode last, ASTNode anchor, Boolean before) { + if (first == last && first.getPsi() instanceof GrTypeParameter) { + boolean hasParams = getTypeParameters().length > 0; + + final ASTNode _anchor; + + if (anchor == null) { + if (before.booleanValue()) { + _anchor = getLastChild().getNode(); + } + else { + _anchor = getFirstChild().getNode(); + } + } + else { + _anchor = anchor; + } + + + final ASTNode node = super.addInternal(first, last, _anchor, before); + if (hasParams) { + getNode().addLeaf(GroovyTokenTypes.mCOMMA, ",", anchor != null ? anchor : node); + } + return node; + } + else { + return super.addInternal(first, last, anchor, before); + } + } } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava.groovy b/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava.groovy index 7ae2a99dca0b..1ec30ed5cc8e 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava.groovy @@ -1,3 +1,18 @@ +/* + * 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. + */ class GClass { public void test() {} } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava_after.groovy index a96448e49cf8..1af7c4e5372c 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava_after.groovy @@ -1,3 +1,18 @@ +/* + * 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. + */ class GClass { - public test(def p = 1) {} + public void test(def p = 1) {} } \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java index 61d03c11270e..235e1d1f2f33 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java @@ -201,39 +201,44 @@ public class MavenFoldersImporter { } } - private void configGeneratedSourceFolder(@NotNull File dir, boolean isTestSources) { + private void configGeneratedSourceFolder(@NotNull File targetDir, boolean isTestSources) { switch (myImportingSettings.getGeneratedSourcesFolder()) { case GENERATED_SOURCE_FOLDER: - if (!myModel.hasRegisteredSourceSubfolder(dir)) { - myModel.addSourceFolder(dir.getPath(), isTestSources); - } + addAsSourceFolder(targetDir, isTestSources); break; case SUBFOLDER: - addAllSubDirsAsSources(dir, isTestSources); + addAllSubDirsAsSources(targetDir, isTestSources); break; case AUTODETECT: - Collection sourceRoots = JavaSourceRootDetectionUtil.suggestRoots(dir); - if (sourceRoots.size() == 1) { - JavaModuleSourceRoot root = sourceRoots.iterator().next(); - if (dir.equals(root.getDirectory())) { - if (!myModel.hasRegisteredSourceSubfolder(dir)) { - myModel.addSourceFolder(dir.getPath(), isTestSources); - } - break; + Collection sourceRoots = JavaSourceRootDetectionUtil.suggestRoots(targetDir); + + for (JavaModuleSourceRoot root : sourceRoots) { + if (targetDir.equals(root.getDirectory())) { + addAsSourceFolder(targetDir, isTestSources); + return; } + + addAsSourceFolder(root.getDirectory(), isTestSources); } - addAllSubDirsAsSources(dir, isTestSources); + + addAllSubDirsAsSources(targetDir, isTestSources); break; } } + private void addAsSourceFolder(@NotNull File dir, boolean isTestSources) { + if (!myModel.hasRegisteredSourceSubfolder(dir)) { + myModel.addSourceFolder(dir.getPath(), isTestSources); + } + } + private void addAllSubDirsAsSources(@NotNull File dir, boolean isTestSources) { for (File f : getChildren(dir)) { - if (!f.isDirectory()) continue; - if (myModel.hasRegisteredSourceSubfolder(f)) continue; - myModel.addSourceFolder(f.getPath(), isTestSources); + if (f.isDirectory()) { + addAsSourceFolder(f, isTestSources); + } } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java index 0604282bafdb..dab37f367960 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java @@ -52,7 +52,7 @@ public class MavenImportingSettings implements Cloneable { private List myListeners = ContainerUtil.createEmptyCOWList(); public enum GeneratedSourcesFolder { - AUTODETECT("Auto detect"), + AUTODETECT("Detect automatically"), GENERATED_SOURCE_FOLDER("target/generated-sources"), SUBFOLDER("subdirectories of \"target/generated-sources\""); @@ -187,16 +187,29 @@ public class MavenImportingSettings implements Cloneable { @Override public int hashCode() { - int result = dedicatedModuleDir.hashCode(); - result = 31 * result + (lookForNested ? 1 : 0); - result = 31 * result + (importAutomatically ? 1 : 0); - result = 31 * result + (createModulesForAggregators ? 1 : 0); - result = 31 * result + (createModuleGroups ? 1 : 0); - result = 31 * result + (keepSourceFolders ? 1 : 0); - result = 31 * result + (useMavenOutput ? 1 : 0); + int result = 0; + + if (lookForNested) result++; + result <<= 1; + if (importAutomatically) result++; + result <<= 1; + if (createModulesForAggregators) result++; + result <<= 1; + if (createModuleGroups) result++; + result <<= 1; + if (keepSourceFolders) result++; + result <<= 1; + if (useMavenOutput) result++; + result <<= 1; + if (downloadSourcesAutomatically) result++; + result <<= 1; + if (downloadDocsAutomatically) result++; + result <<= 1; + result = 31 * result + (updateFoldersOnImportPhase != null ? updateFoldersOnImportPhase.hashCode() : 0); - result = 31 * result + (downloadSourcesAutomatically ? 1 : 0); - result = 31 * result + (downloadDocsAutomatically ? 1 : 0); + result = 31 * result + dedicatedModuleDir.hashCode(); + result = 31 * result + generatedSourcesFolder.hashCode(); + return result; } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java index 4e343e5f6011..80dde852438b 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java @@ -589,6 +589,42 @@ public class FoldersImportingTest extends MavenImportingTestCase { "target/generated-sources/com"); } + public void testAddingExistingGeneratedSources4() throws Exception { + createStdProjectFolders(); + + createProjectSubFile("target/generated-sources/A1/B1/com/A1.java", "package com; class A1 {}"); + createProjectSubFile("target/generated-sources/A1/B2/com/A2.java", "package com; class A2 {}"); + createProjectSubFile("target/generated-sources/A2/com/A3.java", "package com; class A3 {}"); + + importProject("test" + + "project" + + "1"); + + assertSources("project", + "src/main/java", + "src/main/resources", + "target/generated-sources/A1/B1", + "target/generated-sources/A1/B2", + "target/generated-sources/A2"); + } + + public void testAddingExistingGeneratedSources5() throws Exception { + createStdProjectFolders(); + + createProjectSubFile("target/generated-sources/A1/B1/com/A1.java", "package com; class A1 {}"); + createProjectSubFile("target/generated-sources/A2.java", "class A2 {}"); + + importProject("test" + + "project" + + "1"); + + assertSources("project", + "src/main/java", + "src/main/resources", + "target/generated-sources"); + } + + public void testAddingExistingGeneratedSourcesWithCustomTargetDir() throws Exception { createStdProjectFolders(); createProjectSubDirs("targetCustom/generated-sources/src", diff --git a/plugins/rearranger/rearranger.iml b/plugins/rearranger/rearranger.iml index 7adfe3aca0d2..cb24fd03e1f1 100644 --- a/plugins/rearranger/rearranger.iml +++ b/plugins/rearranger/rearranger.iml @@ -17,6 +17,7 @@ + diff --git a/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java b/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java index 10bd83c6ce03..64a58b1ca43d 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java +++ b/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java @@ -152,7 +152,7 @@ public final class RearrangerActionHandler extends EditorActionHandler { wb.whenTrue(); } catch (InterruptedException e) { - e.printStackTrace(); //To change body of catch statement use Options | File Templates. + e.printStackTrace(); } LOG.debug("end execute"); } @@ -186,7 +186,7 @@ public final class RearrangerActionHandler extends EditorActionHandler { } LOG.debug("respacing document"); PsiDocumentManager.getInstance(project).commitDocument(document); - Spacer spacer = new Spacer(project, psiFile, document, settings); + Spacer spacer = new Spacer(psiFile, document, settings); if (spacer.respace()) { PsiDocumentManager.getInstance(project).commitDocument(document); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java index 743e31a51e15..cbde789e0a10 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java @@ -26,6 +26,7 @@ import com.intellij.psi.PsiField; import com.wrq.rearranger.popup.FilePopupEntry; import com.wrq.rearranger.popup.RearrangerTreeNode; import com.wrq.rearranger.settings.RearrangerSettings; +import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; @@ -33,22 +34,19 @@ 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 FilePopupEntry -{ - public ClassContentsEntry(final PsiElement start, - final PsiElement end, +public abstract class ClassContentsEntry extends RangeEntry implements FilePopupEntry { + public ClassContentsEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final int modifiers, final String modifierString, - final String name, + final @Nullable String name, final String type) { super(start, end, modifiers, modifierString, name, type); } - public ClassContentsEntry(final PsiElement start, - final PsiElement end, + public ClassContentsEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final boolean fixedHeader, final boolean fixedTrailer) { @@ -57,10 +55,10 @@ public abstract class ClassContentsEntry public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { DefaultMutableTreeNode node = null; - if ((end instanceof PsiField && settings.isShowFields()) || + if ((myEnd instanceof PsiField && settings.isShowFields()) || (this instanceof ClassEntry)) { - node = new RearrangerTreeNode(this, name); + node = new RearrangerTreeNode(this, myName); parent.add(node); } return node; diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java index f73d7c96543b..1afbc42ddb12 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java @@ -35,6 +35,8 @@ import com.wrq.rearranger.rearrangement.GenericRearranger; import com.wrq.rearranger.ruleinstance.RuleInstance; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.util.ModifierUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; @@ -48,36 +50,33 @@ 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 FilePopupEntry -{ +public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { + private static final Logger LOG = Logger.getInstance("#" + ClassEntry.class.getName()); - protected final List contents; - private List myResultRuleInstances; - private final RearrangerSettings settings; - private final int nestingLevel; + protected final List myContents; + private List myResultRuleInstances; + private final RearrangerSettings mySettings; + private final int myNestingLevel; - public ClassEntry(PsiElement start, - PsiElement end, + public ClassEntry(@Nullable PsiElement start, + @Nullable PsiElement end, int modifiers, String modifierString, - String name, + @Nullable String name, int nestingLevel, - RearrangerSettings settings) - { + RearrangerSettings settings) { super(start, end, modifiers, modifierString, name, ""); - contents = new ArrayList(); + myContents = new ArrayList(); myResultRuleInstances = null; - this.settings = settings; - this.nestingLevel = nestingLevel; + mySettings = settings; + myNestingLevel = nestingLevel; } public String getTypeIconName() { String result = "nodes/class"; - if (end.getParent() instanceof PsiClass) { - PsiClass psiClass = (PsiClass)end.getParent(); + if (myEnd.getParent() instanceof PsiClass) { + PsiClass psiClass = (PsiClass)myEnd.getParent(); if (psiClass.isEnum()) { result = "nodes/enum"; } @@ -89,15 +88,20 @@ public class ClassEntry } public String[] getAdditionalIconNames() { - if (end instanceof PsiJavaToken && end.getText().equals("{")) { - PsiClass psiClass = (PsiClass)end.getParent(); - if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) { + if (myEnd instanceof PsiJavaToken && myEnd.getText().equals("{")) { + PsiClass psiClass = (PsiClass)myEnd.getParent(); + final PsiModifierList modifierList = psiClass.getModifierList(); + if (modifierList == null) { + return null; + } + + if (modifierList.hasModifierProperty(PsiModifier.PUBLIC)) { return new String[]{"nodes/c_public"}; } - if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PROTECTED)) { + if (modifierList.hasModifierProperty(PsiModifier.PROTECTED)) { return new String[]{"nodes/c_protected"}; } - if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) { + if (modifierList.hasModifierProperty(PsiModifier.PRIVATE)) { return new String[]{"nodes/c_private"}; } return new String[]{"nodes/c_plocal"}; @@ -106,20 +110,19 @@ public class ClassEntry } public JLabel getPopupEntryText(RearrangerSettings settings) { - return new JLabel(name); + return new JLabel(myName); } 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) { + if (mySettings.isRearrangeInnerClasses() || myNestingLevel <= 1) { for (int i = startingIndex; i < psiClass.getChildren().length; i++) { PsiElement child = psiClass.getChildren()[i]; if (child instanceof PsiJavaToken && child.getText().equals("{")) { @@ -163,7 +166,7 @@ public class ClassEntry ); } if (child instanceof PsiClass) { - parseClassAttributes(child, attributes); + parseClassAttributes((PsiClass)child, attributes); // // if child is an enum, set the last entry past the LBrace to the final enumeration or the // semicolon thereafter, if any. @@ -189,8 +192,8 @@ public class ClassEntry attributes.modifiers, attributes.modifierString, attributes.name, - nestingLevel + 1, - settings + myNestingLevel + 1, + mySettings ); classContentsEntry = entry; entry.parseRemainingClassContents( @@ -206,7 +209,7 @@ public class ClassEntry attributes.modifierString, attributes.name); } - contents.add(classContentsEntry); + myContents.add(classContentsEntry); classContentsEntry.checkForComment(); lastIndex = i + 1; // next class includes everything since the end of the prior class. } @@ -222,7 +225,7 @@ public class ClassEntry psiClass.getChildren()[psiClass.getChildren().length - 1], false, true ); - contents.add(miscellaneousTextEntry); + myContents.add(miscellaneousTextEntry); miscellaneousTextEntry.checkForComment(); } } @@ -234,7 +237,7 @@ public class ClassEntry * @param clazz * @return starting element index for the portion of the enumeration class following its enum declarations. */ - private int findLastEnumTerminator(PsiClass clazz) { + private static int findLastEnumTerminator(PsiClass clazz) { int startElementIndex = 0; // go until we hit RBrace (non-inclusive), or semicolon (inclusive) boolean foundLBrace = false; @@ -260,25 +263,31 @@ public class ClassEntry return startElementIndex; } - private int parseField(PsiElement child, MemberAttributes attributes, int i, final PsiClass psiClass) { + private static 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 + final PsiClass containingClass = attributes.field.getContainingClass(); + final PsiTypeElement typeElement = attributes.field.getTypeElement(); + if (typeElement == null && containingClass != null) { + attributes.type = containingClass.getName(); // if enum, use class as type } - else { - attributes.type = attributes.field.getTypeElement().getText(); + else if (typeElement != null) { + attributes.type = typeElement.getText(); + } + final PsiModifierList modifierList = attributes.field.getModifierList(); + if (modifierList != null) { + attributes.modifierString = modifierList.getText(); } - attributes.modifierString = attributes.field.getModifierList().getText(); attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString); - if (attributes.field.getContainingClass().isInterface()) { + if (containingClass != null && containingClass.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(); + final PsiExpression initializer = attributes.field.getInitializer(); + if (initializer instanceof PsiNewExpression) { + final PsiElement lc = initializer.getLastChild(); if (lc instanceof PsiAnonymousClass) { attributes.modifiers |= ModifierConstants.INIT_TO_ANON_CLASS; } @@ -332,19 +341,21 @@ public class ClassEntry return i; } - private void parseMethod(PsiElement child, MemberAttributes attributes, final PsiSearchHelper psh) { + private static void parseMethod(PsiElement child, MemberAttributes attributes, final PsiSearchHelper psh) { attributes.method = (PsiMethod)child; attributes.name = attributes.method.getName(); - if (attributes.method.getReturnTypeElement() == null) { + final PsiTypeElement returnTypeElement = attributes.method.getReturnTypeElement(); + if (returnTypeElement == null) { attributes.type = "null"; } else { - attributes.type = attributes.method.getReturnTypeElement().getText(); + attributes.type = returnTypeElement.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()) { + final PsiClass containingClass = attributes.method.getContainingClass(); + if (containingClass != null && containingClass.isInterface()) { // methods in an interface are always considered public attributes.modifiers |= Modifier.PUBLIC; } @@ -376,12 +387,12 @@ public class ClassEntry attributes.modifiers |= ModifierConstants.OVERRIDDEN; } } - // determine if this method overrides another. + // 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. + // 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(); @@ -397,9 +408,8 @@ public class ClassEntry 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. - */ + // 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; } @@ -411,7 +421,7 @@ public class ClassEntry ); } - private int isCanonicalOrInterface(PsiMethod method, MemberAttributes attributes) { + private static 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(); @@ -455,7 +465,7 @@ public class ClassEntry return 0; } - private void dumpMethodNames(PsiMethod[] methods) { + private static void dumpMethodNames(PsiMethod[] methods) { for (int j = 0; j < methods.length; j++) { LOG.debug( j + @@ -467,13 +477,16 @@ public class ClassEntry } } - private void parseClassAttributes(PsiElement child, MemberAttributes attributes) { - attributes.childClass = (PsiClass)child; + private static void parseClassAttributes(@NotNull PsiClass child, @NotNull MemberAttributes attributes) { + attributes.childClass = child; attributes.name = attributes.childClass.getName(); if (attributes.name == null) { attributes.name = ""; } - attributes.modifierString = attributes.childClass.getModifierList().getText(); + final PsiModifierList modifierList = child.getModifierList(); + if (modifierList != null) { + attributes.modifierString = modifierList.getText(); + } attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString); attributes.type = attributes.childClass.isEnum() ? "enum" : "class"; if (attributes.childClass.isEnum()) { @@ -481,17 +494,19 @@ public class ClassEntry } } - private void parseClassInitializer(PsiElement child, MemberAttributes attributes) { + private static void parseClassInitializer(PsiElement child, MemberAttributes attributes) { attributes.classInitializer = (PsiClassInitializer)child; - attributes.classInitializer.getModifierList(); attributes.name = ""; - attributes.modifierString = attributes.classInitializer.getModifierList().getText(); + final PsiModifierList modifierList = attributes.classInitializer.getModifierList(); + if (modifierList != null) { + attributes.modifierString = modifierList.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. + // First emit the text up to and including the left brace. super.emit(emitter); // now emit all children. emitter.emitRuleInstances(getResultRuleInstances()); @@ -508,42 +523,38 @@ public class ClassEntry return result; } - /** rearranges the contents of this PsiClass according to supplied rules. */ + /** 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()); + if (contentsEntry instanceof RelatableEntry) { + ((RelatableEntry)contentsEntry).determineSettersAndMethodCalls(mySettings, getContents()); } } LOG.debug("relating extracted methods"); for (ClassContentsEntry contentsEntry : getContents()) { - if (contentsEntry instanceof IRelatableEntry) { - ((IRelatableEntry)contentsEntry).determineExtractedMethod(settings.getExtractedMethodsSettings()); + if (contentsEntry instanceof RelatableEntry) { + ((RelatableEntry)contentsEntry).determineExtractedMethod(mySettings.getExtractedMethodsSettings()); } } - /** - * remove any cycles in the related method graph. - */ + // 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); + // 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(), mySettings); final GenericRearranger classContentsRearranger = - new GenericRearranger(settings.getItemOrderAttributeList(), - contents, - nestingLevel, - settings) + new GenericRearranger(mySettings.getItemOrderAttributeList(), + myContents, + myNestingLevel, + mySettings) { public void rearrangeRelatedItems(List entries, List ruleInstanceList) { for (RuleInstance ruleInstance : ruleInstanceList) { - ruleInstance.rearrangeRuleItems(entries, settings); + ruleInstance.rearrangeRuleItems(entries, mySettings); } } }; @@ -551,13 +562,13 @@ public class ClassEntry } private void buildMethodCallGraph() { - if (settings.getExtractedMethodsSettings().isMoveExtractedMethods() || - settings.isKeepGettersSettersTogether()) + if (mySettings.getExtractedMethodsSettings().isMoveExtractedMethods() || + mySettings.isKeepGettersSettersTogether()) { LOG.debug("building method call & getter-setter graph"); for (ClassContentsEntry contentsEntry : getContents()) { - if (contentsEntry instanceof IRelatableEntry) { - ((IRelatableEntry)contentsEntry).determineGetterSetterAndExtractedMethodStatus(settings); + if (contentsEntry instanceof RelatableEntry) { + ((RelatableEntry)contentsEntry).determineGetterSetterAndExtractedMethodStatus(mySettings); } } } @@ -566,7 +577,7 @@ public class ClassEntry // End Methods of Interface IFilePopupEntry public final List getContents() { - return contents; + return myContents; } public List getResultRuleInstances() { diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java index f15a3b75c5e4..33d71745ba6a 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java @@ -61,7 +61,7 @@ public class ClassInitializerEntry public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { LOG.debug("add class initializer to popup tree"); - DefaultMutableTreeNode node = new RearrangerTreeNode(this, name); + DefaultMutableTreeNode node = new RearrangerTreeNode(this, myName); parent.add(node); return node; } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java index 92b96ab24473..cf764203ccd5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java @@ -54,16 +54,16 @@ public class FieldEntry } public String getTypeIconName() { - if (end instanceof PsiField) { - PsiField f = (PsiField)end; + if (myEnd instanceof PsiField) { + PsiField f = (PsiField)myEnd; 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 (myEnd instanceof PsiField) { + PsiField f = (PsiField)myEnd; 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"}; @@ -74,7 +74,7 @@ public class FieldEntry public JLabel getPopupEntryText(RearrangerSettings settings) { StringBuffer name = new StringBuffer(80); - PsiField f = (PsiField)end; + PsiField f = (PsiField)myEnd; name.append(f.getName()); name.append(": "); name.append(f.getTypeElement().getText()); @@ -89,7 +89,7 @@ public class FieldEntry DefaultMutableTreeNode node = super.addToPopupTree(parent, settings); if (node != null && getterMethod != null) { getterMethod.addToPopupTree(node, settings); - for (MethodEntry me : getterMethod.correspondingGetterSetters) { + for (MethodEntry me : getterMethod.myCorrespondingGetterSetters) { me.addToPopupTree(node, settings); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java index 450d3e7ddb97..209c0e894f4c 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java @@ -47,7 +47,7 @@ import java.util.*; */ public class MethodEntry extends ClassContentsEntry - implements IRelatableEntry + implements RelatableEntry { // ------------------------------ FIELDS ------------------------------ @@ -58,22 +58,23 @@ public class MethodEntry * the corresponding setter will be placed in calledMethods. This allows the same code to rearrange both * types of related methods. */ - List calledMethods = new ArrayList(); - List calledByMethods = new ArrayList(); - List overloadedMethods = new ArrayList(); + private final List myCalledMethods = new ArrayList(); + private final List myCalledByMethods = new ArrayList(); + private final List myOverloadedMethods = new ArrayList(); // MethodEntry correspondingSetter = null; // TODO - avoid wrong level for setters - List correspondingGetterSetters = new ArrayList(); - private boolean keptWithProperty; - private boolean relatedMethod; + final List myCorrespondingGetterSetters = new ArrayList(); + + private boolean myKeptWithProperty; + private boolean myRelatedMethod; /** @return true if the method is related to another. In this case, the method is exempt from rule matching. */ public boolean isRelatedMethod() { - return relatedMethod; + return myRelatedMethod; } /** @return true if the method is a setter and will be emitted below a corresponding getter. */ public boolean isEmittableSetter() { - return setter && correspondingGetterSetters.size() > 0; + return setter && myCorrespondingGetterSetters.size() > 0; } private boolean isOverloadedMethod; @@ -151,16 +152,16 @@ public class MethodEntry { List parentEntries = new ArrayList(ruleInstance.getMatches()); for (RangeEntry o : parentEntries) { - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; if (me.isGetter()) { - if (me.keptWithProperty) { + if (me.myKeptWithProperty) { if (me.getMatchedRule() != null && me.getMatchedRule().getMatches() != null) { // prevent the getter from appearing under a rule it matches; it will be placed under the property me.getMatchedRule().getMatches().remove(me); } } - for (MethodEntry theSetter : me.correspondingGetterSetters) { + for (MethodEntry theSetter : me.myCorrespondingGetterSetters) { final RuleInstance theRule = theSetter.getMatchedRule(); LOG.debug( "rearrangeRelatedItems: for getter method " + @@ -173,7 +174,7 @@ public class MethodEntry { LOG.debug( "remove entry " + - theSetter.end + + theSetter.myEnd + " from matched rule" + theRule + "; matches = " + @@ -183,15 +184,15 @@ public class MethodEntry } } } - if (me.calledMethods.size() > 0) { + if (me.myCalledMethods.size() > 0) { List parents = new LinkedList(); parents.add(me); moveRelatedItems( entries, parents, rms, - ((PsiMethod)me.end).getName(), - ((PsiMethod)me.end).getName() + "()", + ((PsiMethod)me.myEnd).getName(), + ((PsiMethod)me.myEnd).getName() + "()", 1 ); if (LOG.isDebugEnabled()) { @@ -234,10 +235,10 @@ public class MethodEntry ListIterator li = entries.listIterator(); while (li.hasNext()) { Object o = li.next(); - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; for (MethodEntry entry : parents) { - if (me.calledByMethods.contains(entry)) { + if (me.myCalledByMethods.contains(entry)) { children.add(me); li.remove(); break; @@ -255,10 +256,10 @@ public class MethodEntry ListIterator li = entries.listIterator(); while (li.hasNext()) { Object o = li.next(); - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; for (MethodEntry entry : parents) { - if (me.calledByMethods.contains(entry)) { + if (me.myCalledByMethods.contains(entry)) { me.insertAlphabetically(children); li.remove(); break; @@ -274,7 +275,7 @@ public class MethodEntry * Add these to the list of children in order of invocation. */ for (MethodEntry me : parents) { - for (MethodEntry child : me.calledMethods) { + for (MethodEntry child : me.myCalledMethods) { if (entries.contains(child)) { children.add(child); entries.remove(child); @@ -292,7 +293,7 @@ public class MethodEntry if (children.size() > 0) { if (rms.isDepthFirstOrdering()) { for (MethodEntry entry : children) { - if (entry.calledMethods.size() == 0) { + if (entry.myCalledMethods.size() == 0) { continue; } List parent = new LinkedList(); @@ -302,7 +303,7 @@ public class MethodEntry parent, rms, topLevelMethodName, - allMethodNames + "." + ((PsiMethod)entry.end).getName() + "()", + allMethodNames + "." + ((PsiMethod)entry.myEnd).getName() + "()", level + 1 ); } @@ -336,7 +337,7 @@ public class MethodEntry allMN.append(","); } first = false; - allMN.append(((PsiMethod)entry.end).getName()); + allMN.append(((PsiMethod)entry.myEnd).getName()); } } if (parents.size() > 1) { @@ -348,11 +349,11 @@ public class MethodEntry public void insertAlphabetically(final List list) { Comparator comparator = new Comparator() { public int compare(MethodEntry me, MethodEntry me2) { - String s = ((PsiMethod)me.end).getName(); + String s = ((PsiMethod)me.myEnd).getName(); if (me.isGetter()) { - s = MethodUtil.getPropertyName((PsiMethod)me.end); + s = MethodUtil.getPropertyName((PsiMethod)me.myEnd); } - return s.compareTo(((PsiMethod)me2.end).getName()); + return s.compareTo(((PsiMethod)me2.myEnd).getName()); } }; insertInList(list, comparator); @@ -365,7 +366,7 @@ public class MethodEntry MethodEntry entry = ((MethodEntry)li.next()); if (comparator.compare(this, entry) < 0) { LOG.debug( - "insertInList dependent method: add " + end.toString() + " at index " + (li.nextIndex() - 1) + "insertInList dependent method: add " + myEnd.toString() + " at index " + (li.nextIndex() - 1) ); list.add(li.nextIndex() - 1, this); inserted = true; @@ -377,7 +378,7 @@ public class MethodEntry } void dumpChild(int level) { - LOG.debug(level + ": " + ((PsiMethod)end).getName()); + LOG.debug(level + ": " + ((PsiMethod)myEnd).getName()); for (MethodEntry methodEntry : sortedMethods) { methodEntry.dumpChild(level + 1); } @@ -397,7 +398,7 @@ public class MethodEntry */ public static void eliminateCycles(List contents) { for (ClassContentsEntry entry : contents) { - if (entry instanceof IRelatableEntry) { + if (entry instanceof RelatableEntry) { MethodEntry current = (MethodEntry)entry; List set = new LinkedList(); set.add(current); @@ -407,13 +408,13 @@ public class MethodEntry } private static void test(MethodEntry current, List set) { - Iterator it = current.calledMethods.iterator(); + Iterator it = current.myCalledMethods.iterator(); while (it.hasNext()) { MethodEntry callee = it.next(); if (set.contains(callee)) { - callee.calledByMethods.remove(current); - if (callee.calledByMethods.size() == 0) { - callee.relatedMethod = false; + callee.myCalledByMethods.remove(current); + if (callee.myCalledByMethods.size() == 0) { + callee.myRelatedMethod = false; } it.remove(); } @@ -443,10 +444,10 @@ public class MethodEntry cullOverloadedMethods(contents, false); List copy = new ArrayList(contents); for (ClassContentsEntry rangeEntry : copy) { - if (rangeEntry instanceof IRelatableEntry) { + if (rangeEntry instanceof RelatableEntry) { MethodEntry current = (MethodEntry)rangeEntry; - if (current.overloadedMethods.size() > 0) { - List newList = new ArrayList(current.overloadedMethods.size() + 1); + if (current.myOverloadedMethods.size() > 0) { + List newList = new ArrayList(current.myOverloadedMethods.size() + 1); newList.add(current); /** * we are looking at the head of a list of overloaded methods. We need to sort the list @@ -456,11 +457,11 @@ public class MethodEntry case RearrangerSettings.OVERLOADED_ORDER_RETAIN_ORIGINAL: // list is already in original order, except perhaps that the top-most extracted method // comes first (if there is one). - newList.addAll(current.overloadedMethods); + newList.addAll(current.myOverloadedMethods); break; case RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS: case RearrangerSettings.OVERLOADED_ORDER_DESCENDING_PARAMETERS: - for (MethodEntry entry : current.overloadedMethods) { + for (MethodEntry entry : current.myOverloadedMethods) { boolean inserted = false; for (int index = 0; index < newList.size(); index++) { MethodEntry me = newList.get(index); @@ -479,7 +480,7 @@ public class MethodEntry } break; } - current.overloadedMethods.clear(); + current.myOverloadedMethods.clear(); /** * if the head of the arraylist is not the same as "current", then the sort operation moved * another method to the head of the list. Replace that in the contents array. Then assign @@ -513,23 +514,23 @@ public class MethodEntry { List copy = new ArrayList(contents); for (ClassContentsEntry o : copy) { - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; if ((me.isRelatedMethod() == doExtractedMethods) && !me.isOverloadedMethod) { - String meName = me.end.toString(); + String meName = me.myEnd.toString(); // search contents list for methods with identical name, and attach them as overloaded methods. ListIterator contentIterator = contents.listIterator(); while (contentIterator.hasNext()) { Object o1 = contentIterator.next(); - if (o1 instanceof IRelatableEntry) { + if (o1 instanceof RelatableEntry) { MethodEntry me2 = (MethodEntry)o1; if (me2 == me) { continue; } - String me2Name = me2.end.toString(); + String me2Name = me2.myEnd.toString(); if (meName.equals(me2Name)) { contentIterator.remove(); - me.overloadedMethods.add(me2); + me.myOverloadedMethods.add(me2); me2.isOverloadedMethod = true; // set flag so array copy will skip this entry. } } @@ -564,8 +565,8 @@ public class MethodEntry public String[] getAdditionalIconNames() { ArrayList result = new ArrayList(); String[] sa = new String[0]; - if (end instanceof PsiMethod) { - PsiMethod m = (PsiMethod)end; + if (myEnd instanceof PsiMethod) { + PsiMethod m = (PsiMethod)myEnd; if (m.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) { result.add("nodes/c_public"); } @@ -595,8 +596,8 @@ public class MethodEntry } public String getTypeIconName() { - if (end instanceof PsiMethod) { - PsiMethod m = (PsiMethod)end; + if (myEnd instanceof PsiMethod) { + PsiMethod m = (PsiMethod)myEnd; return (((PsiModifierList)m.getModifierList()).hasModifierProperty(PsiModifier.STATIC)) ? "nodes/staticMethod" : "nodes/method"; } return null; @@ -610,7 +611,7 @@ public class MethodEntry public JLabel getPopupEntryText(RearrangerSettings settings) { StringBuffer name = new StringBuffer(80); - PsiMethod m = (PsiMethod)end; + PsiMethod m = (PsiMethod)myEnd; if (m.getReturnTypeElement() != null && !settings.isShowTypeAfterMethod()) { name.append(m.getReturnTypeElement().getText()); name.append(' '); @@ -670,13 +671,13 @@ public class MethodEntry */ setGetter( MethodUtil.isGetter( - (PsiMethod)end, + (PsiMethod)myEnd, settings.getDefaultGSDefinition() ) ); setSetter( MethodUtil.isSetter( - (PsiMethod)end, + (PsiMethod)myEnd, settings.getDefaultGSDefinition() ) ); @@ -686,7 +687,7 @@ public class MethodEntry if (((IRestrictMethodExtraction)rule).isNoExtractedMethods()) { LOG.debug( "excluding " + - end.toString() + + myEnd.toString() + " from extracted method consideration" ); setNoExtractedMethods(true); @@ -739,47 +740,47 @@ public class MethodEntry * option to keep getters and setters together is set. This is a special case.) */ public void determineExtractedMethod(RelatedMethodsSettings settings) { - relatedMethod = false; + myRelatedMethod = false; if (!isGetter() && !isSetter()) { - if (calledByMethods.size() > 0) { - PsiMethod m = (PsiMethod)end; + if (myCalledByMethods.size() > 0) { + PsiMethod m = (PsiMethod)myEnd; if (!m.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) { switch (settings.getNonPrivateTreatment()) { case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_NEVER: break; case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ONE_CALLER: - if (calledByMethods.size() == 1) { - relatedMethod = true; + if (myCalledByMethods.size() == 1) { + myRelatedMethod = true; } break; case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ANY_CALLERS: - relatedMethod = true; + myRelatedMethod = true; break; } } else { - relatedMethod = true; + myRelatedMethod = true; } } } else { - if (isSetter() && calledByMethods.size() > 0 && correspondingGetterSetters.size() == 0) { - relatedMethod = true; - LOG.debug(end.toString() + " is setter but has no getter, treated as extracted method"); + if (isSetter() && myCalledByMethods.size() > 0 && myCorrespondingGetterSetters.size() == 0) { + myRelatedMethod = true; + LOG.debug(myEnd.toString() + " is setter but has no getter, treated as extracted method"); } else { - LOG.debug(end.toString() + " is getter/setter, not treated as extracted method"); + LOG.debug(myEnd.toString() + " is getter/setter, not treated as extracted method"); } } - LOG.debug("determined " + end.toString() + " is extracted method? " + relatedMethod); + LOG.debug("determined " + myEnd.toString() + " is extracted method? " + myRelatedMethod); /** * If this is not an extracted method, remove it from any callers so that it won't be moved. */ - if (!relatedMethod) { - ListIterator li = calledByMethods.listIterator(); + if (!myRelatedMethod) { + ListIterator li = myCalledByMethods.listIterator(); while (li.hasNext()) { MethodEntry entry = (li.next()); - entry.calledMethods.remove(this); + entry.myCalledMethods.remove(this); li.remove(); } } @@ -787,31 +788,31 @@ public class MethodEntry * Remaining entries are only extracted methods at this point. Using first/last rule, keep only the call by * the calling method that this child method will be grouped with, and discard the rest. */ - if (calledByMethods.size() > 1) { + if (myCalledByMethods.size() > 1) { ListIterator li; if (settings.isBelowFirstCaller()) { - li = calledByMethods.listIterator(1); + li = myCalledByMethods.listIterator(1); while (li.hasNext()) { MethodEntry entry = (li.next()); - entry.calledMethods.remove(this); + entry.myCalledMethods.remove(this); li.remove(); } } else { - li = calledByMethods.listIterator(calledByMethods.size() - 1); + li = myCalledByMethods.listIterator(myCalledByMethods.size() - 1); while (li.hasPrevious()) { MethodEntry entry = (li.previous()); - entry.calledMethods.remove(this); + entry.myCalledMethods.remove(this); li.remove(); } } } - if (relatedMethod) { + if (myRelatedMethod) { LOG.debug( "extracted method " + toString() + " will be arranged under " + - calledByMethods.get(0).toString() + myCalledByMethods.get(0).toString() ); } } @@ -819,11 +820,11 @@ public class MethodEntry // -------------------------- OTHER METHODS -------------------------- public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { - DefaultMutableTreeNode node = new RearrangerTreeNode(this, name); + DefaultMutableTreeNode node = new RearrangerTreeNode(this, myName); parent.add(node); ListIterator li; for (MethodEntry methodEntry : sortedMethods) { - if (methodEntry.isSetter() && methodEntry.calledByMethods.size() > 0) { + if (methodEntry.isSetter() && methodEntry.myCalledByMethods.size() > 0) { // setters are arranged with getters when "keep getters/setters together" option is checked. // but setters are not really called by getters. So attach them to the upper level. methodEntry.addToPopupTree(parent, settings); @@ -832,7 +833,7 @@ public class MethodEntry methodEntry.addToPopupTree(node, settings); } } - for (MethodEntry methodEntry : overloadedMethods) { + for (MethodEntry methodEntry : myOverloadedMethods) { methodEntry.addToPopupTree(node, settings); } return node; @@ -850,15 +851,15 @@ public class MethodEntry String allMethodNames, int level) { - final String currentMethodName = ((PsiMethod)end).getName(); + final String currentMethodName = ((PsiMethod)myEnd).getName(); String[] callingNames = new String[allCallingMethods.size()]; for (int i = 0; i < allCallingMethods.size(); i++) { MethodEntry me = allCallingMethods.get(i); - callingNames[i] = ((PsiMethod)me.end).getName(); + callingNames[i] = ((PsiMethod)me.myEnd).getName(); } MethodEntry topLevel = this; - while (topLevel.calledByMethods.size() > 0) { - topLevel = (topLevel.calledByMethods.get(0)); + while (topLevel.myCalledByMethods.size() > 0) { + topLevel = (topLevel.myCalledByMethods.get(0)); } switch (rms.getCommentType()) { case RelatedMethodsSettings.COMMENT_TYPE_TOP_LEVEL: @@ -886,14 +887,14 @@ public class MethodEntry rms.getPrecedingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); customizedTrailingComment = expandComment( rms.getTrailingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); // recursively assign comments. @@ -929,7 +930,7 @@ public class MethodEntry rms.getPrecedingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); } @@ -954,7 +955,7 @@ public class MethodEntry rms.getPrecedingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); // recursively assign comments for each level. @@ -980,7 +981,7 @@ public class MethodEntry rms.getTrailingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); } @@ -1059,15 +1060,15 @@ public class MethodEntry * to only that text up to and including the open brace. Temporarily remove the rest of the text; append * it again after checking for comments. */ - int brace = alternateValue.indexOf('{'); + int brace = myAlternateValue.indexOf('{'); String temp = ""; if (brace >= 0) { // every method should have an open brace -- unless it is abstract. - temp = alternateValue.substring(brace + 1, alternateValue.length()); - alternateValue = alternateValue.substring(0, brace + 1); + temp = myAlternateValue.substring(brace + 1, myAlternateValue.length()); + myAlternateValue = myAlternateValue.substring(0, brace + 1); } super.checkForComment(); - alternateValue += temp; + myAlternateValue += temp; } /** @@ -1085,7 +1086,7 @@ public class MethodEntry /** * recursively walk the method's code block looking for method calls. */ - final PsiMethod thisMethod = (PsiMethod)end; + final PsiMethod thisMethod = (PsiMethod)myEnd; final MethodEntry thisMethodEntry = this; JavaRecursiveElementVisitor rev = new JavaRecursiveElementVisitor() { @@ -1095,11 +1096,11 @@ public class MethodEntry /** * if the called method is already in our list, don't add it again. */ - if (c != null && !calledMethods.contains(c)) { + if (c != null && !myCalledMethods.contains(c)) { for (ClassContentsEntry o : possibleMethods) { - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; - PsiMethod m = (PsiMethod)me.end; + PsiMethod m = (PsiMethod)me.myEnd; if (c == m) { if (settings.isKeepOverloadedMethodsTogether() && m.getName().equals(thisMethod.getName())) @@ -1108,8 +1109,8 @@ public class MethodEntry } else { LOG.debug("method " + thisMethod.toString() + " calls " + m.toString()); - calledMethods.add(me); - me.calledByMethods.add(thisMethodEntry); + myCalledMethods.add(me); + me.myCalledByMethods.add(thisMethodEntry); } break; } @@ -1138,40 +1139,40 @@ public class MethodEntry { return; } - final PsiMethod thisMethod = (PsiMethod)end; + final PsiMethod thisMethod = (PsiMethod)myEnd; String thisProperty = MethodUtil.getPropertyName(thisMethod); - if (isGetter() && !keptWithProperty) { + if (isGetter() && !myKeptWithProperty) { if (settings.isKeepGettersSettersWithProperty()) { hookGetterToProperty(possibleMethods); } } for (ClassContentsEntry o : possibleMethods) { - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; // don't use a setter twice (could be two methods which both look like getters; assign the setter // to only one of them.) Also, associate all getter/setter methods for the same property with the // first one encountered. if ((me.isSetter() || me.isGetter()) && - me.correspondingGetterSetters.size() == 0 && + me.myCorrespondingGetterSetters.size() == 0 && me != this) { - PsiMethod m = (PsiMethod)me.end; + PsiMethod m = (PsiMethod)me.myEnd; String otherProperty = MethodUtil.getPropertyName(m); if (thisProperty.equals(otherProperty)) { LOG.debug("method " + thisMethod.toString() + " is getter; its setter is " + m.toString()); // place getters ahead of setters if (me.isGetter()) { - correspondingGetterSetters.add(0, me); + myCorrespondingGetterSetters.add(0, me); // clear the getter flag and set the setter flag; this causes the method to be emitted // under the first getter encountered. me.setGetter(false); me.setSetter(true); } else { - correspondingGetterSetters.add(me); + myCorrespondingGetterSetters.add(me); } - me.correspondingGetterSetters.add(this); + me.myCorrespondingGetterSetters.add(this); } } } @@ -1186,7 +1187,7 @@ public class MethodEntry */ private void hookGetterToProperty(List entries) { ListIterator li = entries.listIterator(); - String property = MethodUtil.getPropertyName((PsiMethod)end); + String property = MethodUtil.getPropertyName((PsiMethod)myEnd); while (li.hasNext()) { Object o = li.next(); if (o instanceof FieldEntry) { @@ -1195,7 +1196,7 @@ public class MethodEntry sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); if (fe.getGetterMethod() == null && property.equals(sb.toString())) { fe.setGetterMethod(this); - keptWithProperty = true; + myKeptWithProperty = true; break; } } @@ -1203,7 +1204,7 @@ public class MethodEntry } public void emit(Emitter emitter) { - StringBuffer sb = emitter.getStringBuffer(); + StringBuilder sb = emitter.getTextBuffer(); if (getCustomizedPrecedingComment().length() > 0) { sb.append("\n"); sb.append(getCustomizedPrecedingComment()); @@ -1218,11 +1219,11 @@ public class MethodEntry */ ListIterator li; if (isGetter()) { - for (MethodEntry entry : correspondingGetterSetters) { + for (MethodEntry entry : myCorrespondingGetterSetters) { entry.emit(emitter); } } - for (MethodEntry me : overloadedMethods) { + for (MethodEntry me : myOverloadedMethods) { me.emit(emitter); } for (MethodEntry me : sortedMethods) { @@ -1230,17 +1231,17 @@ public class MethodEntry } } - protected void emitAllElements(StringBuffer sb, Document document) { - if (alternateValue != null) { + protected void emitAllElements(StringBuilder sb, Document document) { + if (myAlternateValue != null) { /** * protect body of method from removing newlines. */ - int brace = alternateValue.indexOf('{'); + int brace = myAlternateValue.indexOf('{'); String temp = ""; if (brace >= 0) { // every method should have an open brace -- unless it is abstract. - temp = alternateValue.substring(brace + 1, alternateValue.length()); - alternateValue = alternateValue.substring(0, brace + 1); + temp = myAlternateValue.substring(brace + 1, myAlternateValue.length()); + myAlternateValue = myAlternateValue.substring(0, brace + 1); } super.emitAllElements(sb, document); sb.append(temp); @@ -1253,8 +1254,8 @@ public class MethodEntry public void insertInterfaceOrder(List list) { Comparator comparator = new Comparator() { public int compare(MethodEntry o1, MethodEntry o2) { - final int offset1 = getMethodOffsetInInterface((PsiMethod)o1.end); - final int offset2 = getMethodOffsetInInterface((PsiMethod)o2.end); + final int offset1 = getMethodOffsetInInterface((PsiMethod)o1.myEnd); + final int offset2 = getMethodOffsetInInterface((PsiMethod)o2.myEnd); if (offset1 < offset2) return -1; if (offset1 == offset2) return 0; return 1; @@ -1263,7 +1264,7 @@ public class MethodEntry insertInList(list, comparator); } - private int getMethodOffsetInInterface(PsiMethod method) { + private static int getMethodOffsetInInterface(PsiMethod method) { final PsiMethod[] superMethods = method.findSuperMethods(); // final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method); // todo - for IDEA 5.0 if (superMethods.length == 0) return 0; @@ -1277,11 +1278,11 @@ public class MethodEntry public String toString() { return "MethodEntry " + - end.toString() + + myEnd.toString() + "; calls " + - calledMethods.size() + + myCalledMethods.size() + ", called by " + - calledByMethods.size() + + myCalledByMethods.size() + ", nParameters=" + nParameters; } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java index 4d3da310a052..be17b09ebe30 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java @@ -23,13 +23,13 @@ package com.wrq.rearranger.entry; import com.intellij.psi.PsiElement; import com.wrq.rearranger.settings.RearrangerSettings; +import org.jetbrains.annotations.Nullable; import javax.swing.*; /** Corresponds to comments and whitespace that surround Java syntactic items like classes and methods. */ -public class MiscellaneousTextEntry - extends ClassContentsEntry -{ +public class MiscellaneousTextEntry extends ClassContentsEntry { + public MiscellaneousTextEntry(final PsiElement start, final PsiElement end, final boolean fixedHeader, @@ -38,6 +38,7 @@ public class MiscellaneousTextEntry super(start, end, fixedHeader, fixedTrailer); } + @Nullable public String getTypeIconName() { // do not show headers and trailers in the file structure popup. return null; @@ -47,6 +48,7 @@ public class MiscellaneousTextEntry return null; } + @Nullable public JLabel getPopupEntryText(RearrangerSettings settings) { return null; } @@ -59,7 +61,7 @@ public class MiscellaneousTextEntry else { result = "Trailer"; } - if (alternateValue != null) { + if (myAlternateValue != null) { result += "; comments removed"; } return result; diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/PopupTreeRangeEntry.java similarity index 93% rename from plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java rename to plugins/rearranger/src/com/wrq/rearranger/entry/PopupTreeRangeEntry.java index eb4e7636443f..ac6af64d28c3 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/PopupTreeRangeEntry.java @@ -26,13 +26,11 @@ 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 { +public interface PopupTreeRangeEntry { /** * Gives individual entries control over their appearance, depending on settings. diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java index 11ac5ba48afe..b6264f1cf68e 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java @@ -27,6 +27,7 @@ import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; import com.wrq.rearranger.settings.RearrangerSettings; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,27 +37,24 @@ import java.util.List; * 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) { +public class PsiFileEntry extends ClassEntry { + + public PsiFileEntry(@NotNull 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 + * Strips 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 parseFile(Project project, - PsiElement psiFile, - List commentList) - { + public List parseFile(Project project, PsiElement psiFile) { int startingIndex = 0; + // TODO den re-write to the 'firstChild & nextSibling' for (int i = 0; i < psiFile.getChildren().length; i++) { PsiElement child = psiFile.getChildren()[i]; if (child instanceof PsiClass) { @@ -86,8 +84,8 @@ public class PsiFileEntry } parseRemainingClassContents(project, startingIndex, psiFile); if (miscellaneousTextEntry != null) { - contents.add(0, miscellaneousTextEntry); + myContents.add(0, miscellaneousTextEntry); } - return contents; + return myContents; } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java index 96fd5a97102c..18b525ad3ded 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java @@ -23,12 +23,15 @@ package com.wrq.rearranger.entry; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.wrq.rearranger.popup.RearrangerTreeNode; import com.wrq.rearranger.rearrangement.Emitter; import com.wrq.rearranger.ruleinstance.RuleInstance; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.util.CommentUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; import java.util.regex.Matcher; @@ -38,66 +41,68 @@ import java.util.regex.Matcher; * 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 { +abstract public class RangeEntry implements PopupTreeRangeEntry { + // ------------------------------ 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 RuleInstance myMatchedRule; - private boolean separatorCommentPrecedes; + + String myAlternateValue; + final String myName; + protected final PsiElement myStart; + protected final PsiElement myEnd; + private final int myModifiers; + private final String myModifierString; + private final boolean myFixedHeader; + private final boolean myFixedTrailer; + private final String myType; + private RuleInstance myMatchedRule; + private boolean mySeparatorCommentPrecedes; // --------------------------- CONSTRUCTORS --------------------------- - public RangeEntry(final PsiElement start, - final PsiElement end, + public RangeEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final boolean fixedHeader, final boolean fixedTrailer) { this(start, end, 0, "", "", "", fixedHeader, fixedTrailer); } - RangeEntry(final PsiElement start, - final PsiElement end, + RangeEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final int modifiers, final String modifierString, - final String name, + @Nullable final String name, final String type) { this(start, end, modifiers, modifierString, name, type, false, false); } - private RangeEntry(final PsiElement start, - final PsiElement end, + private RangeEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final int modifiers, final String modifierString, - final String name, + @Nullable 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; + myStart = start; + myEnd = end; + myModifiers = modifiers; + myModifierString = modifierString; + myFixedHeader = fixedHeader; + myFixedTrailer = fixedTrailer; + myName = name; + myType = type; + myAlternateValue = null; } // --------------------- GETTER / SETTER METHODS --------------------- public PsiElement getEnd() { - return end; + return myEnd; } public RuleInstance getMatchedRule() { @@ -109,59 +114,59 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { } public int getModifiers() { - return modifiers; + return myModifiers; } public String getModifierString() { - return modifierString; + return myModifierString; } public String getName() { - return name; + return myName; } public String getType() { - return type; + return myType; } public PsiElement getStart() { - return start; + return myStart; } public boolean isFixedHeader() { - return fixedHeader; + return myFixedHeader; } public boolean isFixedTrailer() { - return fixedTrailer; + return myFixedTrailer; } // ------------------------ CANONICAL METHODS ------------------------ public String toString() { - String result = (name == null ? "" : name); - if (start != null && end != null) { + String result = (myName == null ? "" : myName); + if (myStart != null && myEnd != null) { result += "; range from " + - start.toString() + + myStart.toString() + " [" + - start.getTextRange().getStartOffset() + + myStart.getTextRange().getStartOffset() + "] to " + - end.toString() + + myEnd.toString() + " [" + - end.getTextRange().getEndOffset() + + myEnd.getTextRange().getEndOffset() + "]; modifiers=0x" + - Integer.toHexString(modifiers); + Integer.toHexString(myModifiers); } else { result += "; no start/end specified"; } - if (fixedHeader) { + if (myFixedHeader) { result = "Header: " + result; } - if (fixedTrailer) { + if (myFixedTrailer) { result = "Trailer: " + result; } - if (alternateValue != null) { + if (myAlternateValue != null) { result += "; comments removed"; } return result; @@ -173,7 +178,7 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { // --------------------- Interface IPopupTreeRangeEntry --------------------- public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { - DefaultMutableTreeNode myNode = new RearrangerTreeNode(this, name); + DefaultMutableTreeNode myNode = new RearrangerTreeNode(this, myName); parent.add(myNode); return myNode; } @@ -189,40 +194,37 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { * for each separator comment specified by the user, check to see if this comment matches. */ for (Matcher matcher : CommentUtil.getCommentMatchers()) { - matcher.reset(alternateValue); + matcher.reset(myAlternateValue); boolean foundMatch = matcher.find(); if (foundMatch) { LOG.debug("found comment pattern '" + matcher.pattern().pattern().replaceAll("\n", "#") + "' in '" + - alternateValue.replaceAll("\n", "#") + + myAlternateValue.replaceAll("\n", "#") + "'"); - StringBuffer sb = new StringBuffer(alternateValue.length()); + StringBuffer sb = new StringBuffer(myAlternateValue.length()); do { - boolean leadingNewlines = start.getTextRange().getStartOffset() > 0; + boolean leadingNewlines = myStart.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", "#")); + myAlternateValue = sb.toString(); + LOG.debug("RangeEntry alternateValue=" + myAlternateValue.replaceAll("\n", "#")); } } } protected void createAlternateValueString() { - if (alternateValue != null) { + if (myAlternateValue != 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()) { + final StringBuilder sb = new StringBuilder(myEnd.getTextRange().getEndOffset() - myStart.getTextRange().getStartOffset()); + PsiElement e = myStart; + while (e != null && e != myEnd) { + if (e == myEnd.getParent()) { e = e.getFirstChild(); } else { @@ -230,58 +232,52 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { e = e.getNextSibling(); } } - if (e == end) { - sb.append(end.getText()); + if (e == myEnd) { + sb.append(myEnd.getText()); } - alternateValue = sb.toString(); + myAlternateValue = sb.toString(); } public void emit(Emitter emitter) { - emitAllElements(emitter.getStringBuffer(), emitter.getDocument()); + emitAllElements(emitter.getTextBuffer(), emitter.getDocument()); } - protected void emitAllElements(StringBuffer sb, Document document) { - if (alternateValue != null) { - String result = alternateValue; - if (separatorCommentPrecedes) { + protected void emitAllElements(StringBuilder buffer, Document document) { + if (myAlternateValue != null) { + String result = myAlternateValue; + if (mySeparatorCommentPrecedes) { // 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"); + myName + "; original value=" + + myAlternateValue.replaceAll("\n", "#")); + result = myAlternateValue.replaceFirst("\n[ \t\n]*\n", "\n"); LOG.debug("emitAllElements: resulting value=" + - alternateValue.replaceAll("\n", "#")); + myAlternateValue.replaceAll("\n", "#")); } - sb.append(result); + buffer.append(result); } else { - PsiElement curr = start; - while (curr != null && curr != end) { - if (curr == end.getParent()) { + PsiElement curr = myStart; + while (curr != null && curr != myEnd) { + if (curr == myEnd.getParent()) { curr = curr.getFirstChild(); } else { - emitElement(curr, sb, document); + emitElement(curr, buffer, document); curr = curr.getNextSibling(); } } - if (curr == end) { - emitElement(end, sb, document); + if (curr == myEnd && myEnd != null) { + emitElement(myEnd, buffer, document); } } } - private void emitElement(final PsiElement curr, - final StringBuffer sb, - final Document document) - { + private static void emitElement(@NotNull final PsiElement curr, @NotNull final StringBuilder sb, @NotNull final Document document) { + final TextRange range = curr.getTextRange(); try { - sb.append( - document.getCharsSequence().toString().toCharArray(), // for Irida (builds 3185 etc). - curr.getTextRange().getStartOffset(), - curr.getTextRange().getEndOffset() - curr.getTextRange().getStartOffset() - ); + sb.append(document.getCharsSequence(), range.getStartOffset(), range.getEndOffset()); } catch (ArrayIndexOutOfBoundsException oob) { LOG.error("internal error attempting to append text to document"); @@ -290,17 +286,17 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { 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("current PSI element text range, start offset=" + range.getStartOffset()); + LOG.error("current PSI element text range, end offset=" + range.getEndOffset()); + LOG.error("current PSI element text range, length=" + range.getLength()); LOG.error(oob); throw oob; } } public void setSeparatorCommentPrecedes(boolean precedes) { - this.separatorCommentPrecedes = precedes; - LOG.debug("emitAllElements: set separator comment precedes " + name); + this.mySeparatorCommentPrecedes = precedes; + LOG.debug("emitAllElements: set separator comment precedes " + myName); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/RelatableEntry.java similarity index 98% rename from plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java rename to plugins/rearranger/src/com/wrq/rearranger/entry/RelatableEntry.java index 317360a1a093..1b893f6197d4 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/RelatableEntry.java @@ -30,7 +30,7 @@ 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 { +public interface RelatableEntry { /** * Determine if the entry is a getter/setter or is excluded from extracted method consideration by an * overriding rule. diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/FilePopupEntry.java b/plugins/rearranger/src/com/wrq/rearranger/popup/FilePopupEntry.java index b1fbb6dd6229..4df540539a80 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/popup/FilePopupEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/FilePopupEntry.java @@ -29,6 +29,7 @@ import javax.swing.*; /** Interface implemented by objects which can appear as entries in the file structure popup. */ public interface FilePopupEntry { /** @return the name of the icon representing the popup entry's type of Java object (method, class, etc.) */ + @Nullable String getTypeIconName(); /** @@ -39,5 +40,6 @@ public interface FilePopupEntry { String[] getAdditionalIconNames(); /** @return a JLabel containing the text of the popup tree entry. */ + @Nullable JLabel getPopupEntryText(RearrangerSettings settings); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java index 6e6b7ddba87c..77287d0d9a13 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java @@ -24,41 +24,48 @@ package com.wrq.rearranger.rearrangement; import com.intellij.openapi.editor.Document; import com.intellij.psi.PsiFile; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; /** Emits a new document from the rearranged entries. */ public final class Emitter { - private final PsiFile psiFile; - private final List myResultRuleInstances; - private final Document document; - private StringBuffer stringBuffer; - public Emitter(final PsiFile psiFile, final List resultRuleInstances, final Document document) { - this.psiFile = psiFile; - this.myResultRuleInstances = resultRuleInstances; - this.document = document; - stringBuffer = new StringBuffer(psiFile.getText().length() + 100); // room for inserted blank lines + @NotNull private final StringBuilder myStringBuffer = new StringBuilder(); + @NotNull private final List myResultRuleInstances = new ArrayList(); + + @NotNull private final PsiFile myFile; + @NotNull private final Document myDocument; + + public Emitter(@NotNull final PsiFile file, @NotNull final List resultRuleInstances, @NotNull final Document document) { + myFile = file; + myResultRuleInstances.addAll(resultRuleInstances); + myDocument = document; + myStringBuffer.ensureCapacity(myFile.getText().length() + 100 /* room for inserted blank lines */); } + @NotNull public Document getDocument() { - return document; + return myDocument; } - public StringBuffer getStringBuffer() { - return stringBuffer; + @NotNull + public StringBuilder getTextBuffer() { + return myStringBuffer; } public void emitRearrangedDocument() { emitRuleInstances(myResultRuleInstances); - document.replaceString( - psiFile.getTextRange().getStartOffset(), - psiFile.getTextRange().getEndOffset(), - stringBuffer.toString() + myDocument.replaceString( + myFile.getTextRange().getStartOffset(), + myFile.getTextRange().getEndOffset(), + myStringBuffer.toString() ); } - public void emitRuleInstances(List resultRuleInstances) { + public void emitRuleInstances(@Nullable List resultRuleInstances) { if (resultRuleInstances == null) { return; } diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java index fb1232ee1650..0fe9f582a692 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java @@ -24,12 +24,13 @@ 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.entry.RelatableEntry; import com.wrq.rearranger.ruleinstance.CommentRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.attributeGroups.*; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -37,23 +38,24 @@ 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 rules; - private final List entries; - private final List myResultRuleInstances; - private final int nestingLevel; - private final RearrangerSettings settings; + + private final List myRules; + private final List myEntries; + private final List myResultRuleInstances; + private final int myNestingLevel; + private final RearrangerSettings mySettings; @SuppressWarnings({"AssignmentToCollectionOrArrayFieldFromParameter"}) protected GenericRearranger(final List rules, final List outerClasses, final int nestingLevel, - final RearrangerSettings settings) - { - this.rules = rules; - entries = outerClasses; - this.nestingLevel = nestingLevel; - this.settings = settings; + final RearrangerSettings settings) { + myRules = rules; + myEntries = outerClasses; + this.myNestingLevel = nestingLevel; + this.mySettings = settings; myResultRuleInstances = new ArrayList(rules.size() + 4); } @@ -66,27 +68,23 @@ public abstract class GenericRearranger { public final List rearrangeEntries() { final List prioritizedRuleInstances = new ArrayList(); buildRuleInstanceLists(prioritizedRuleInstances); - /** - * recursively reorder contents of every nested ClassEntry. - */ - for (ClassContentsEntry entry : entries) { + + // Recursively reorder contents of every nested ClassEntry + for (ClassContentsEntry entry : myEntries) { 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, myResultRuleInstances); - /** - * 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()) { + // Move related methods together. Extracted methods and setters (emitted with getters) + // were not moved by the rearrangement code ("MatchPrioritizedRules()") just above. + rearrangeRelatedItems(myEntries, myResultRuleInstances); + + // 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 (myNestingLevel <= 1 || mySettings.isRearrangeInnerClasses()) { determineEmittedComments(); } return myResultRuleInstances; @@ -103,7 +101,9 @@ public abstract class GenericRearranger { for (int j = i + 1; j < myResultRuleInstances.size(); j++) { RuleInstance instance = myResultRuleInstances.get(j); if (instance.hasMatches()) { - RangeEntry entry = (instance.getMatches().get(0)); + final List matches = instance.getMatches(); + assert matches != null; + RangeEntry entry = (matches.get(0)); entry.setSeparatorCommentPrecedes(true); break; } @@ -122,17 +122,17 @@ public abstract class GenericRearranger { * @param prioritizedRules prioritized list of rules */ @SuppressWarnings({"StringContatenationInLoop"}) - private void matchPrioritizedRules(List prioritizedRules) { + private void matchPrioritizedRules(@NotNull List prioritizedRules) { for (RuleInstance ruleInstance : prioritizedRules) { final Rule rule = ruleInstance.getRule(); - final ListIterator entryIterator = entries.listIterator(); + final ListIterator entryIterator = myEntries.listIterator(); while (entryIterator.hasNext()) { final RangeEntry entry = (RangeEntry)entryIterator.next(); - if (entry instanceof IRelatableEntry) { + if (entry instanceof RelatableEntry) { // 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); + final RelatableEntry relatableEntry = ((RelatableEntry)entry); if (relatableEntry.isRelatedMethod() || relatableEntry.isEmittableSetter()) { continue; } @@ -154,18 +154,14 @@ public abstract class GenericRearranger { * @param prioritizedRuleInstances */ private void buildRuleInstanceLists(final List prioritizedRuleInstances) { - /** - * add a HeaderTrailerRuleInstance to pick up any headers that might exist. - */ + // Add a HeaderTrailerRuleInstance to pick up any headers that might exist. RuleInstance hri = new HeaderRule().createRuleInstance(); myResultRuleInstances.add(hri); prioritizedRuleInstances.add(hri); - for (Rule rule : rules) { + for (Rule rule : myRules) { RuleInstance instance = rule.createRuleInstance(); myResultRuleInstances.add(instance); - /** - * now insert the rule instance into the prioritized list; highest priority first; stable insertion. - */ + // 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--) { RuleInstance entry = (prioritizedRuleInstances.get(i)); @@ -179,11 +175,11 @@ public abstract class GenericRearranger { prioritizedRuleInstances.add(0, instance); } } - // now add a default rule to pick up all unmatched items. + // Now add a default rule to pick up all unmatched items. RuleInstance defaultRuleInstance = new DefaultRule().createRuleInstance(); myResultRuleInstances.add(defaultRuleInstance); prioritizedRuleInstances.add(defaultRuleInstance); - // finally, add a TrailerRuleInstance to pick up any leftover text. + // Finally, add a TrailerRuleInstance to pick up any leftover text. RuleInstance tri = new TrailerRule().createRuleInstance(); myResultRuleInstances.add(tri); prioritizedRuleInstances.add(tri); @@ -196,7 +192,6 @@ public abstract class GenericRearranger { * @param entries * @param rearrangedEntries */ - public abstract void rearrangeRelatedItems(List entries, - List rearrangedEntries); + public abstract void rearrangeRelatedItems(List entries, List rearrangedEntries); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java index 97c77425d617..89b4b6f1e1c4 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java @@ -30,22 +30,21 @@ import java.util.List; /** Moves (rearranges) classes and class members according to rules specified by the user. */ public final class Mover { - private final List outerClasses; - private final RearrangerSettings settings; - public Mover(final List outerClasses, - final RearrangerSettings settings) - { - this.outerClasses = new ArrayList(outerClasses); - this.settings = settings; + private final List myOuterClasses = new ArrayList(); + private final RearrangerSettings mySettings; + + public Mover(final List outerClasses, final RearrangerSettings settings) { + myOuterClasses.addAll(outerClasses); + mySettings = settings; } public List rearrangeOuterClasses() { final GenericRearranger outerClassRearranger = new GenericRearranger( - settings.getClassOrderAttributeList(), - outerClasses, + mySettings.getClassOrderAttributeList(), + myOuterClasses, 0, - settings) + mySettings) { /** * There are no items related to outer classes -- outer classes are completely disjoint @@ -55,9 +54,7 @@ public final class Mover { @param rearrangedEntries */ - public void rearrangeRelatedItems(List entries, - List rearrangedEntries) - { + public void rearrangeRelatedItems(List entries, List rearrangedEntries) { } }; diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java index 53033b2d264f..6f4f5badea06 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java @@ -29,34 +29,36 @@ 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 org.jetbrains.annotations.NotNull; 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; + private static final Logger LOG = Logger.getInstance("#" + Parser.class.getName()); + + private final Project myProject; + private final RearrangerSettings mySettings; + private final PsiFile myPsiFile; + + public Parser(final @NotNull Project project, final @NotNull RearrangerSettings settings, final @NotNull PsiFile psiFile) { + myProject = project; + mySettings = settings; + myPsiFile = psiFile; } + @NotNull public List parseOuterLevel() { /** * Parse the top level contents of the PsiFile here. */ - PsiFileEntry fileEntry = new PsiFileEntry(settings); - return fileEntry.parseFile(project, psiFile, settings.getClassOrderAttributeList()); + PsiFileEntry fileEntry = new PsiFileEntry(mySettings); + return fileEntry.parseFile(myProject, myPsiFile); } - private void dumpOuterClasses(final List outerClasses) { + @SuppressWarnings("UnusedDeclaration") + private static void dumpOuterClasses(final List outerClasses) { LOG.debug("Outer class entries:"); for (ClassEntry classEntry : outerClasses) { LOG.debug(classEntry.toString()); diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java index 0158aff9e423..acbb698009a0 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java @@ -23,7 +23,6 @@ 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; @@ -34,24 +33,22 @@ 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 final PsiFile myFile; + private final Document myDocument; + private final RearrangerSettings mySettings; + private final char[] myNewlineChars; + private boolean myChangesMade; + private StringBuilder myBuffer; private Map virtualElements = new HashMap(); - 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(); + public Spacer(PsiFile psiFile, Document document, RearrangerSettings settings) { + myFile = psiFile; + myDocument = document; + mySettings = settings; + myChangesMade = false; int size = 0; size += settings.getAfterClassLBrace().getnBlankLines() + 1; size += settings.getBeforeMethodLBrace().getnBlankLines() + 1; @@ -61,9 +58,9 @@ public class Spacer { size += settings.getBeforeClassRBrace().getnBlankLines() + 1; size += settings.getAfterClassRBrace().getnBlankLines() + 1; LOG.debug("constructor allocating " + size + " newline chars for max insertion"); - newlineChars = new char[size]; + myNewlineChars = new char[size]; while (size > 0) { - newlineChars[--size] = '\n'; + myNewlineChars[--size] = '\n'; } LOG.debug(settings.getAfterClassLBrace().toString()); LOG.debug(settings.getBeforeMethodLBrace().toString()); @@ -74,29 +71,29 @@ public class Spacer { LOG.debug(settings.getAfterClassRBrace().toString()); final int ROOM_FOR_EXPANSION = 100; int maxSize = document.getTextLength() + ROOM_FOR_EXPANSION; - sb = new StringBuffer(maxSize); + myBuffer = new StringBuilder(maxSize); } - private class AbortRespacing extends RuntimeException { + private static class AbortRespacingException extends RuntimeException { } - private class BadPsiElement extends Exception { - BadPsiElement(String string) { + private static class BadPsiElementException extends Exception { + BadPsiElementException(String string) { super(string); } } - private void handleBadPsiElementException(BadPsiElement bpe, String desc, PsiElement element) - throws AbortRespacing + private static void handleBadPsiElementException(String desc, PsiElement element) + throws AbortRespacingException { 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(); + throw new AbortRespacingException(); } public boolean respace() { - sb.append(document.getText()); + myBuffer.append(myDocument.getText()); JavaElementVisitor visitor = new JavaRecursiveElementVisitor() { private int bias = 0; @@ -106,13 +103,13 @@ public class Spacer { public void visitFile(PsiFile psiFile) { super.visitFile(psiFile); - if (settings.getNewLinesAtEOF().isForce()) { + if (mySettings.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); + while (myBuffer.length() > 0 && myBuffer.charAt(myBuffer.length() - 1) == '\n') { + myBuffer.setLength(myBuffer.length() - 1); } - for (int count = 0; count < settings.getNewLinesAtEOF().getnBlankLines(); count++) { - sb.append('\n'); + for (int count = 0; count < mySettings.getNewLinesAtEOF().getnBlankLines(); count++) { + myBuffer.append('\n'); } } } @@ -131,32 +128,28 @@ public class Spacer { bias += adjustSpacing( psiClass.getLBrace(), psiClass.getRBrace(), - settings.getAfterClassLBrace(), + mySettings.getAfterClassLBrace(), bias ); } - catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "class " + psiClass.getName() + " missing left brace. Body follows:", - psiClass); + catch (BadPsiElementException badPsiElement) { + handleBadPsiElementException("class " + psiClass.getName() + " missing left brace. Body follows:", psiClass); } - log(settings.getAfterClassLBrace(), psiClass.getName(), oldbias, bias); + log(mySettings.getAfterClassLBrace(), psiClass.getName(), oldbias, bias); super.visitClass(psiClass); oldbias = bias; try { bias += adjustSpacing( psiClass.getRBrace(), psiClass.getLBrace(), - settings.getBeforeClassRBrace(), + mySettings.getBeforeClassRBrace(), bias ); } - catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "class " + psiClass.getName() + " missing right brace. Body follows:", - psiClass); + catch (BadPsiElementException badPsiElement) { + handleBadPsiElementException("class " + psiClass.getName() + " missing right brace. Body follows:", psiClass); } - log(settings.getBeforeClassRBrace(), psiClass.getName(), oldbias, bias); + log(mySettings.getBeforeClassRBrace(), psiClass.getName(), oldbias, bias); if (anonymous) { return; @@ -176,16 +169,14 @@ public class Spacer { bias += adjustSpacing( psiClass.getRBrace(), psiClass.getLBrace(), - settings.getAfterClassRBrace(), + mySettings.getAfterClassRBrace(), bias ); } - catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "class " + psiClass.getName() + " missing left brace. Body follows:", - psiClass); + catch (BadPsiElementException badPsiElement) { + handleBadPsiElementException("class " + psiClass.getName() + " missing left brace. Body follows:", psiClass); } - log(settings.getAfterClassRBrace(), psiClass.getName(), oldbias, bias); + log(mySettings.getAfterClassRBrace(), psiClass.getName(), oldbias, bias); } else { LOG.debug( @@ -230,38 +221,34 @@ public class Spacer { bias += adjustSpacing( psiMethod.getBody().getLBrace(), psiMethod.getBody().getRBrace(), - settings.getBeforeMethodLBrace(), + mySettings.getBeforeMethodLBrace(), bias ); bias += adjustSpacing( psiMethod.getBody().getLBrace(), psiMethod.getBody().getRBrace(), - settings.getAfterMethodLBrace(), + mySettings.getAfterMethodLBrace(), bias ); } - catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "body of method " + psiMethod.getName() + " missing left brace. Body follows:", - psiMethod); + catch (BadPsiElementException badPsiElement) { + handleBadPsiElementException("body of method " + psiMethod.getName() + " missing left brace. Body follows:", psiMethod); } - log(settings.getAfterMethodLBrace(), psiMethod.getName(), oldbias, bias); + log(mySettings.getAfterMethodLBrace(), psiMethod.getName(), oldbias, bias); super.visitMethod(psiMethod); oldbias = bias; try { bias += adjustSpacing( psiMethod.getBody().getRBrace(), psiMethod.getBody().getLBrace(), - settings.getBeforeMethodRBrace(), + mySettings.getBeforeMethodRBrace(), bias ); } - catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "body of method " + psiMethod.getName() + " missing right brace. Body follows:", - psiMethod); + catch (BadPsiElementException badPsiElement) { + handleBadPsiElementException("body of method " + psiMethod.getName() + " missing right brace. Body follows:", psiMethod); } - log(settings.getBeforeMethodRBrace(), psiMethod.getName(), oldbias, bias); + log(mySettings.getBeforeMethodRBrace(), psiMethod.getName(), oldbias, bias); } else { LOG.debug("method " + psiMethod.getName() + " is empty, no internal spacing changes"); @@ -285,16 +272,14 @@ public class Spacer { bias += adjustSpacing( psiMethod.getBody().getRBrace(), psiMethod.getBody().getLBrace(), - settings.getAfterMethodRBrace(), + mySettings.getAfterMethodRBrace(), bias ); } - catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "body of method " + psiMethod.getName() + " missing right brace. Body follows:", - psiMethod); + catch (BadPsiElementException badPsiElement) { + handleBadPsiElementException("body of method " + psiMethod.getName() + " missing right brace. Body follows:", psiMethod); } - log(settings.getAfterMethodRBrace(), psiMethod.getName(), oldbias, bias); + log(mySettings.getAfterMethodRBrace(), psiMethod.getName(), oldbias, bias); } else { LOG.debug( @@ -308,51 +293,49 @@ public class Spacer { public void visitCodeBlock(PsiCodeBlock psiCodeBlock) { int oldbias; if (!(psiCodeBlock.getParent() instanceof PsiMethod) && - settings.isRemoveBlanksInsideCodeBlocks()) + mySettings.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); + catch (BadPsiElementException badPsiElement) { + handleBadPsiElementException("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()) + mySettings.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); + catch (BadPsiElementException badPsiElement) { + handleBadPsiElementException("code block missing right brace. Content follows:\n", psiCodeBlock); } log("code block right brace", oldbias, bias); } } }; try { - psiFile.accept(visitor); + myFile.accept(visitor); } - catch (AbortRespacing ar) { + catch (AbortRespacingException ar) { return false; } - if (changesMade) { + if (myChangesMade) { LOG.debug( "changes made to document; old length=" + - document.getTextLength() + ", new=" + sb.length() + myDocument.getTextLength() + ", new=" + myBuffer.length() ); - LOG.debug("old document is:\n" + document.getText()); - LOG.debug("new document is:\n" + sb.toString()); - document.replaceString(0, document.getTextLength(), sb.toString()); + LOG.debug("old document is:\n" + myDocument.getText()); + LOG.debug("new document is:\n" + myBuffer.toString()); + myDocument.replaceString(0, myDocument.getTextLength(), myBuffer.toString()); } - return changesMade; + return myChangesMade; } /** @@ -365,7 +348,7 @@ public class Spacer { * @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) { + private static boolean isLastMeaningfulElement(PsiElement owner, PsiElement psiElement) { boolean lastMethod; // class is immediate parent PsiElement[] elements = owner.getChildren(); @@ -389,7 +372,7 @@ public class Spacer { return lastMethod; } - private void log(ForceBlankLineSetting fbls, String name, int oldbias, int bias) { + private static void log(ForceBlankLineSetting fbls, String name, int oldbias, int bias) { if (oldbias != bias) { LOG.debug( fbls.getObjectName() + @@ -403,7 +386,7 @@ public class Spacer { } } - private void log(String name, int oldbias, int bias) { + private static void log(String name, int oldbias, int bias) { if (oldbias != bias) { LOG.debug( name + @@ -414,7 +397,7 @@ public class Spacer { } private int adjustSpacing(PsiElement brace, PsiElement matchingBrace, ForceBlankLineSetting fbls, int bias) - throws BadPsiElement + throws BadPsiElementException { if (fbls.isForce()) { return adjustSpacing(brace, matchingBrace, fbls.isBefore(), fbls.getnBlankLines(), bias); @@ -463,11 +446,11 @@ public class Spacer { * @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 + throws BadPsiElementException { int result = 0; if (brace == null) { - throw new BadPsiElement( + throw new BadPsiElementException( "adjustSpacing: illegal syntax (mismatched braces); PsiElement for brace is null" ); } @@ -478,17 +461,17 @@ public class Spacer { int direction = before ? -1 : +1; int count = 0; { - char braceChar = sb.charAt(offset); + char braceChar = myBuffer.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(); + if (R > myBuffer.length()) { + R = myBuffer.length(); } - String context = sb.toString().substring(L, R); + String context = myBuffer.toString().substring(L, R); throw new RuntimeException( "adjustSpacing: char at offset " + offset + @@ -512,9 +495,7 @@ public class Spacer { return result; } } - while (whiteSpace != null && - (!(whiteSpace instanceof PsiWhiteSpace) || - whiteSpace.getText().indexOf('\n') < 0)); + while (whiteSpace != null && (!(whiteSpace instanceof PsiWhiteSpace) || whiteSpace.getText().indexOf('\n') < 0)); VirtualElement virtualWhiteSpace = null; if (whiteSpace != null) { @@ -539,7 +520,7 @@ public class Spacer { /** * first count the number of existing blank lines. */ - if (offset + direction >= sb.length()) { + if (offset + direction >= myBuffer.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; @@ -607,31 +588,31 @@ public class Spacer { endIndex += offset + 1; } else { - offset = endIndex = sb.length(); + offset = endIndex = myBuffer.length(); } try { - changesMade = true; + myChangesMade = true; LOG.debug( "sb.replace(" + offset + "," + endIndex + ") with " + desiredNewlineChars + " newline characters" ); - sb.replace(offset, endIndex, new String(newlineChars, 0, desiredNewlineChars)); + myBuffer.replace(offset, endIndex, new String(myNewlineChars, 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)); + vsb.replace(offset, endIndex, new String(myNewlineChars, 0, desiredNewlineChars)); virtualWhiteSpace.setTextValue(vsb.toString()); } } catch (StringIndexOutOfBoundsException si) { throw new RuntimeException( "sb.length()=" + - sb.length() + + myBuffer.length() + ", offset=" + offset + ", before=" + @@ -640,7 +621,7 @@ public class Spacer { count + ", desiredNewlineChars=" + desiredNewlineChars + - ", charAt offset=" + (offset < sb.length() ? "" + sb.charAt(offset) : "OOB"), si + ", charAt offset=" + (offset < myBuffer.length() ? "" + myBuffer.charAt(offset) : "OOB"), si ); } return result; diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java index a8493481dd7c..71ec06a4812e 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java @@ -33,32 +33,30 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import java.awt.*; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** Used to store a generated comment, and to determine if it should be emitted. */ -public abstract class CommentRuleInstance - implements RuleInstance, - FilePopupEntry -{ - protected final CommentRule commentRule; - protected boolean emit; +public abstract class CommentRuleInstance implements RuleInstance, FilePopupEntry { + + protected final CommentRule myCommentRule; + protected boolean myEmit; public CommentRuleInstance(final CommentRule commentRule) { - this.commentRule = commentRule; - emit = false; + this.myCommentRule = commentRule; + myEmit = false; } public boolean isEmit() { - return emit; + return myEmit; } public void setEmit(final boolean emit) { - this.emit = emit; + this.myEmit = emit; } public Rule getRule() { - return commentRule; + return myCommentRule; } /** Determine if this comment, in this instance, should be emitted. */ @@ -69,15 +67,15 @@ public abstract class CommentRuleInstance } public void emit(Emitter emitter) { - StringBuffer sb = emitter.getStringBuffer(); - if (emit) { + StringBuilder sb = emitter.getTextBuffer(); + if (myEmit) { // 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()); + sb.append(myCommentRule.getExpandedCommentText()); } else { - sb.append(commentRule.getExpandedCommentText()); + sb.append(myCommentRule.getExpandedCommentText()); sb.append('\n'); } } @@ -91,12 +89,10 @@ public abstract class CommentRuleInstance } public List getMatches() { - return new ArrayList(); + return Collections.emptyList(); } - public void rearrangeRuleItems(List entries, - RearrangerSettings settings) - { + public void rearrangeRuleItems(List entries, RearrangerSettings settings) { } public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) { @@ -117,7 +113,7 @@ public abstract class CommentRuleInstance * append the comment if generated and if showComments is set. */ if (isEmit()) { - commentRule.addToPopupTree(top, settings); + myCommentRule.addToPopupTree(top, settings); } } @@ -131,14 +127,14 @@ public abstract class CommentRuleInstance } public JLabel getPopupEntryText(RearrangerSettings settings) { - JLabel label = new JLabel(commentRule.toString()); + JLabel label = new JLabel(myCommentRule.toString()); Font font = label.getFont().deriveFont(Font.ITALIC); label.setFont(font); return label; } public String toString() { - return "instance of:" + commentRule.toString(); + return "instance of:" + myCommentRule.toString(); } /** diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java index 502418ae4a7f..810315c9e902 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java @@ -23,7 +23,7 @@ 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.PopupTreeRangeEntry; import com.wrq.rearranger.entry.MethodEntry; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.popup.FilePopupEntry; @@ -65,7 +65,7 @@ public abstract class CommonRuleInstance */ public void addEntry(RangeEntry entry) { if (myRule instanceof CommonAttributes) { - SortOptions sortOptions = ((CommonAttributes)myRule).getSortAttr(); + SortOptions sortOptions = ((CommonAttributes)myRule).getSortOptions(); insertionSort(entry, sortOptions); } else { @@ -135,7 +135,7 @@ public abstract class CommonRuleInstance /** * append each of the matches to the top level. */ - for (IPopupTreeRangeEntry entry : getMatches()) { + for (PopupTreeRangeEntry entry : getMatches()) { entry.addToPopupTree(top, settings); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java index 677740beea2b..cc8aa53d3655 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java @@ -26,19 +26,20 @@ import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.rearrangement.Emitter; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.attributeGroups.Rule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; import java.util.ArrayList; import java.util.List; /** Instance to pick up header text. */ -public class HeaderTrailerRuleInstance - implements RuleInstance -{ - private final Rule myRule; - private RangeEntry myEntry; +public class HeaderTrailerRuleInstance implements RuleInstance { - public HeaderTrailerRuleInstance(Rule rule) { + @NotNull private final Rule myRule; + @Nullable private RangeEntry myEntry; + + public HeaderTrailerRuleInstance(@NotNull Rule rule) { myRule = rule; } @@ -55,12 +56,13 @@ public class HeaderTrailerRuleInstance return list; } + @NotNull public Rule getRule() { return myRule; } - public void addEntry(RangeEntry entry) { - this.myEntry = entry; // a header only has one entry + public void addEntry(@Nullable RangeEntry entry) { + myEntry = entry; // a header only has one entry } public void emit(Emitter emitter) { diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java index a5c7b79cb9b9..1b289a200102 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java @@ -118,20 +118,21 @@ public class InterfaceInstance } } + @SuppressWarnings("MismatchedQueryAndUpdateOfStringBuilder") void emit(Emitter emitter) { - StringBuffer sb = emitter.getStringBuffer(); + StringBuilder buffer = emitter.getTextBuffer(); String commentString = expandComment(rule.getPrecedingComment()); if (commentString.length() > 0) { - sb.append("\n"); - sb.append(commentString); + buffer.append("\n"); + buffer.append(commentString); } for (MethodEntry rangeEntry : methods) { rangeEntry.emit(emitter); } commentString = expandComment(rule.getTrailingComment()); if (commentString.length() > 0) { - sb.append("\n"); - sb.append(commentString); + buffer.append("\n"); + buffer.append(commentString); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java index 5dea4fbd84d6..bd1854a7ffa3 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java @@ -38,10 +38,10 @@ public class PrecedingCommentRuleInstance public void determineEmit(List resultRuleInstances, int startIndex) { if (match( resultRuleInstances, - commentRule.getnPrecedingRulesToMatch(), + myCommentRule.getnPrecedingRulesToMatch(), -1, startIndex, - commentRule.isAllPrecedingRules())) + myCommentRule.isAllPrecedingRules())) { setEmit(true); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/RuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/RuleInstance.java index ab2e5772431d..48c4b5a9f9e5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/RuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/RuleInstance.java @@ -32,10 +32,11 @@ 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 + * One {@link 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 RuleInstance { + /** @return true if one or more items matched the rule in this instance. */ boolean hasMatches(); diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java index 267706698450..bc1b41265865 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java @@ -38,10 +38,10 @@ public class SubsequentCommentRuleInstance public void determineEmit(List resultRuleInstances, int startIndex) { if (match( resultRuleInstances, - commentRule.getnSubsequentRulesToMatch(), + myCommentRule.getnSubsequentRulesToMatch(), +1, startIndex, - commentRule.isAllSubsequentRules() + myCommentRule.isAllSubsequentRules() )) { setEmit(true); diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java index 33e90ff12e0a..a41874b6cdb5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java @@ -38,17 +38,17 @@ public class SurroundingCommentRuleInstance public void determineEmit(List resultRuleInstances, int startIndex) { if (match( resultRuleInstances, - commentRule.getnPrecedingRulesToMatch(), + myCommentRule.getnPrecedingRulesToMatch(), -1, startIndex, - commentRule.isAllPrecedingRules() + myCommentRule.isAllPrecedingRules() ) && match( resultRuleInstances, - commentRule.getnSubsequentRulesToMatch(), + myCommentRule.getnSubsequentRulesToMatch(), +1, startIndex, - commentRule.isAllSubsequentRules() + myCommentRule.isAllSubsequentRules() )) { setEmit(true); diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java index 4e8710cb489e..c9dcc3f3467c 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java @@ -21,7 +21,7 @@ */ package com.wrq.rearranger.settings; -import com.wrq.rearranger.entry.IPopupTreeRangeEntry; +import com.wrq.rearranger.entry.PopupTreeRangeEntry; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.popup.FilePopupEntry; import com.wrq.rearranger.popup.RearrangerTreeNode; @@ -32,6 +32,7 @@ import com.wrq.rearranger.settings.attributeGroups.RegexUtil; import com.wrq.rearranger.util.Constraints; import org.jdom.Attribute; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -50,7 +51,7 @@ import java.util.List; /** Handles insertion of comment separators between sections of the rearranged file. */ public final class CommentRule implements AttributeGroup, - IPopupTreeRangeEntry, + PopupTreeRangeEntry, FilePopupEntry { // ------------------------------------------------------- FIELDS ------------------------------------------------------ @@ -417,6 +418,7 @@ public final class CommentRule // ---------------------------------------------- Interface AttributeGroup --------------------------------------------- + @NotNull public final /*CommentRule*/AttributeGroup deepCopy() { final CommentRule comment = new CommentRule(); comment.commentText = commentText; @@ -429,7 +431,7 @@ public final class CommentRule return comment; } - public final void writeExternal(final Element parent) { + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("Comment"); me.setText(escape(commentText)); me.setAttribute("condition", "" + emitCondition); @@ -464,11 +466,12 @@ public final class CommentRule // -------------------------------------------------- Interface IRule -------------------------------------------------- + @NotNull public RuleInstance createRuleInstance() { return CommentRuleInstanceFactory.buildCommentRuleInstance(this); } - public boolean isMatch(RangeEntry rangeEntry) { + public boolean isMatch(@NotNull RangeEntry rangeEntry) { return false; // comment rules match no entries -- they're just placeholders to generate comments. } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java index f3180b76f6a9..28c033e05725 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java @@ -31,9 +31,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** Base class for all boolean attributes. */ -abstract public class AndNotAttribute - extends AtomicAttribute -{ +abstract public class AndNotAttribute extends AtomicAttribute { // ------------------------------ FIELDS ------------------------------ boolean value; diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java index e3cbef25990b..a13ada7458ea 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java @@ -24,9 +24,7 @@ package com.wrq.rearranger.settings.atomicAttributes; import com.wrq.rearranger.ModifierConstants; import org.jdom.Element; -public final class InitToAnonClassAttribute - extends AndNotAttribute -{ +public final class InitToAnonClassAttribute extends AndNotAttribute { // -------------------------- STATIC METHODS -------------------------- diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java index 3b39e9c046c8..a9b278f586e9 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java @@ -22,15 +22,15 @@ package com.wrq.rearranger.settings.attributeGroups; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; /** Methods implemented by rule objects, which are saved in configuration. */ -public interface AttributeGroup - extends Rule -{ +public interface AttributeGroup extends Rule { // -------------------------- OTHER METHODS -------------------------- - public AttributeGroup deepCopy(); + @NotNull + AttributeGroup deepCopy(); - public void writeExternal(final Element parent); + void writeExternal(final @NotNull Element parent); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java index 0af457a9d854..41559ecda682 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java @@ -29,6 +29,8 @@ import com.wrq.rearranger.settings.atomicAttributes.AbstractAttribute; import com.wrq.rearranger.settings.atomicAttributes.EnumAttribute; import com.wrq.rearranger.util.Constraints; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; @@ -47,6 +49,7 @@ public final class ClassAttributes // -------------------------- STATIC METHODS -------------------------- + @Nullable public static AttributeGroup readExternal(final Element element) { if (element.getName().equals("Class")) { final ClassAttributes result = new ClassAttributes(); @@ -82,11 +85,11 @@ public final class ClassAttributes // ------------------------ CANONICAL METHODS ------------------------ public final String toString() { - final StringBuffer sb = new StringBuffer(70); + final StringBuilder sb = new StringBuilder(70); sb.append(abAttr.getDescriptiveString()); - sb.append(plAttr.getProtectionLevelString()); - sb.append(stAttr.getDescriptiveString()); - sb.append(fAttr.getDescriptiveString()); + sb.append(getProtectionLevelAttributes().getProtectionLevelString()); + sb.append(getStaticAttribute().getDescriptiveString()); + sb.append(getFinalAttribute().getDescriptiveString()); sb.append(enumAttr.getDescriptiveString()); if (sb.length() == 0) { sb.append("all classes"); @@ -94,11 +97,11 @@ public final class ClassAttributes else { sb.append("classes"); } - if (nameAttr.isMatch()) { + if (getNameAttribute().isMatch()) { sb.append(' '); - sb.append(nameAttr.getDescriptiveString()); + sb.append(getNameAttribute().getDescriptiveString()); } - sb.append(sortAttr.getDescriptiveString()); + sb.append(getSortOptions().getDescriptiveString()); return sb.toString(); } @@ -107,6 +110,7 @@ public final class ClassAttributes // --------------------- Interface AttributeGroup --------------------- + @NotNull public final /*ClassAttributes*/AttributeGroup deepCopy() { final ClassAttributes result = new ClassAttributes(); deepCopyCommonItems(result); @@ -115,7 +119,8 @@ public final class ClassAttributes return result; } - public final void writeExternal(final Element parent) { + @SuppressWarnings("unchecked") + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("Class"); writeExternalCommonAttributes(me); abAttr.appendAttributes(me); @@ -146,27 +151,27 @@ public final class ClassAttributes constraints.weightx = 1.0d; constraints.weighty = 0.0d; constraints.insets = new Insets(0, 0, 10, 0); - caPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + caPanel.add(getProtectionLevelAttributes().getProtectionLevelPanel(), constraints); constraints.gridy = 4; constraints.gridheight = 1; - caPanel.add(getStAttr().getAndNotPanel(), constraints); + caPanel.add(getStaticAttribute().getAndNotPanel(), constraints); constraints.gridy++; caPanel.add(getAbAttr().getAndNotPanel(), constraints); constraints.gridy++; - caPanel.add(getfAttr().getAndNotPanel(), constraints); + caPanel.add(getFinalAttribute().getAndNotPanel(), constraints); constraints.gridy++; caPanel.add(getEnumAttr().getAndNotPanel(), constraints); constraints.gridy++; - caPanel.add(getNameAttr().getStringPanel(), constraints); + caPanel.add(getNameAttribute().getStringPanel(), constraints); constraints.gridy++; constraints.gridheight = GridBagConstraints.REMAINDER; constraints.weighty = 1.0d; constraints.insets = new Insets(0, 0, 0, 0); - caPanel.add(sortAttr.getSortOptionsPanel(), constraints); + caPanel.add(getSortOptions().getSortOptionsPanel(), constraints); return caPanel; } - public final boolean isMatch(RangeEntry entry) + public final boolean isMatch(@NotNull RangeEntry entry) // final int modifiers, final String name, final String returnType) { return entry.getEnd().getParent() instanceof PsiClass && diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java index 341378944a7b..ad8c6c1a64e6 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java @@ -27,6 +27,7 @@ import com.wrq.rearranger.ruleinstance.RuleInstance; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.atomicAttributes.*; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -36,64 +37,67 @@ import java.util.List; * protected, package), final modifier, and static modifier. Ability to match the name to a regular * expression is also supported. */ -public abstract class CommonAttributes - implements AttributeGroup, PrioritizedRule -{ +public abstract class CommonAttributes implements AttributeGroup, PrioritizedRule { + // ------------------------------ FIELDS ------------------------------ - ProtectionLevelAttributes plAttr; - FinalAttribute fAttr; - StaticAttribute stAttr; - NameAttribute nameAttr; - SortOptions sortAttr; - int priority; // 1 = low priority, > 1 is higher priority + private ProtectionLevelAttributes myProtectionLevelAttributes; + private FinalAttribute myFinalAttribute; + private StaticAttribute myStaticAttribute; + private NameAttribute myNameAttribute; + private SortOptions mySortOptions; + private int myPriority; // 1 = low priority, > 1 is higher priority // -------------------------- STATIC METHODS -------------------------- static void readExternal(final CommonAttributes result, final Element item) { - result.plAttr = ProtectionLevelAttributes.readExternal(item); - result.stAttr = StaticAttribute.readExternal(item); - result.fAttr = FinalAttribute.readExternal(item); - result.nameAttr = NameAttribute.readExternal(item); - result.sortAttr = SortOptions.readExternal(item); - result.priority = RearrangerSettings.getIntAttribute(item, "priority", 1); + result.myProtectionLevelAttributes = ProtectionLevelAttributes.readExternal(item); + result.myStaticAttribute = StaticAttribute.readExternal(item); + result.myFinalAttribute = FinalAttribute.readExternal(item); + result.myNameAttribute = NameAttribute.readExternal(item); + result.mySortOptions = SortOptions.readExternal(item); + result.myPriority = RearrangerSettings.getIntAttribute(item, "priority", 1); } // --------------------------- CONSTRUCTORS --------------------------- public CommonAttributes() { - plAttr = new ProtectionLevelAttributes(); - fAttr = new FinalAttribute(); - stAttr = new StaticAttribute(); - nameAttr = new NameAttribute(); - sortAttr = new SortOptions(); - priority = 1; + myProtectionLevelAttributes = new ProtectionLevelAttributes(); + myFinalAttribute = new FinalAttribute(); + myStaticAttribute = new StaticAttribute(); + myNameAttribute = new NameAttribute(); + mySortOptions = new SortOptions(); + myPriority = 1; } // --------------------- GETTER / SETTER METHODS --------------------- - public final NameAttribute getNameAttr() { - return nameAttr; + @NotNull + public final NameAttribute getNameAttribute() { + return myNameAttribute; } - final public ProtectionLevelAttributes getPlAttr() { - return plAttr; + @NotNull + final public ProtectionLevelAttributes getProtectionLevelAttributes() { + return myProtectionLevelAttributes; } public int getPriority() { - return priority; + return myPriority; } public void setPriority(int priority) { - this.priority = priority; + this.myPriority = priority; } - final public StaticAttribute getStAttr() { - return stAttr; + @NotNull + final public StaticAttribute getStaticAttribute() { + return myStaticAttribute; } - public SortOptions getSortAttr() { - return sortAttr; + @NotNull + public SortOptions getSortOptions() { + return mySortOptions; } // ------------------------ CANONICAL METHODS ------------------------ @@ -103,12 +107,12 @@ public abstract class CommonAttributes return false; } final CommonAttributes ca = (CommonAttributes)obj; - return plAttr.equals(ca.plAttr) && - stAttr.equals(ca.stAttr) && - fAttr.equals(ca.fAttr) && - nameAttr.equals(ca.nameAttr) && - sortAttr.equals(ca.sortAttr) && - priority == ca.priority; + return myProtectionLevelAttributes.equals(ca.myProtectionLevelAttributes) && + myStaticAttribute.equals(ca.myStaticAttribute) && + myFinalAttribute.equals(ca.myFinalAttribute) && + myNameAttribute.equals(ca.myNameAttribute) && + mySortOptions.equals(ca.mySortOptions) && + myPriority == ca.myPriority; } // ------------------------ INTERFACE METHODS ------------------------ @@ -116,16 +120,14 @@ public abstract class CommonAttributes // --------------------- Interface IRule --------------------- + @NotNull public RuleInstance createRuleInstance() { return new DefaultRuleInstance(this); } - public boolean isMatch(RangeEntry rangeEntry) { - final boolean result = plAttr.isMatch(rangeEntry.getModifiers()) && - stAttr.isMatch(rangeEntry.getModifiers()) && - fAttr.isMatch(rangeEntry.getModifiers()) && - nameAttr.isMatch(rangeEntry.getName()); - return result; + public boolean isMatch(@NotNull RangeEntry rangeEntry) { + return myProtectionLevelAttributes.isMatch(rangeEntry.getModifiers()) && myStaticAttribute.isMatch(rangeEntry.getModifiers()) + && myFinalAttribute.isMatch(rangeEntry.getModifiers()) && myNameAttribute.isMatch(rangeEntry.getName()); } /** @@ -147,38 +149,31 @@ public abstract class CommonAttributes return 0; } - /** - * Calculates a list of regular expression patterns, one for each comment that the rule might create, which will - * match any comment that the rule might generate. These can be combined to form a global comment pattern which - * will match all possible generated comments from all rules. These patterns will be appended to the supplied - * list. - */ public void addCommentPatternsToList(List list) { - return; } // -------------------------- OTHER METHODS -------------------------- final void deepCopyCommonItems(final CommonAttributes result) { - result.plAttr = (ProtectionLevelAttributes)plAttr.deepCopy(); - result.fAttr = (FinalAttribute)fAttr.deepCopy(); - result.stAttr = (StaticAttribute)stAttr.deepCopy(); - result.nameAttr = (NameAttribute)nameAttr.deepCopy(); - result.sortAttr = (SortOptions)sortAttr.deepCopy(); - result.priority = priority; + result.myProtectionLevelAttributes = (ProtectionLevelAttributes)myProtectionLevelAttributes.deepCopy(); + result.myFinalAttribute = (FinalAttribute)myFinalAttribute.deepCopy(); + result.myStaticAttribute = (StaticAttribute)myStaticAttribute.deepCopy(); + result.myNameAttribute = (NameAttribute)myNameAttribute.deepCopy(); + result.mySortOptions = (SortOptions)mySortOptions.deepCopy(); + result.myPriority = myPriority; } - final public FinalAttribute getfAttr() { - return fAttr; + final public FinalAttribute getFinalAttribute() { + return myFinalAttribute; } final void writeExternalCommonAttributes(final Element child) { - plAttr.appendAttributes(child); - stAttr.appendAttributes(child); - fAttr.appendAttributes(child); - nameAttr.appendAttributes(child); - sortAttr.appendAttributes(child); - child.setAttribute("priority", "" + priority); + myProtectionLevelAttributes.appendAttributes(child); + myStaticAttribute.appendAttributes(child); + myFinalAttribute.appendAttributes(child); + myNameAttribute.appendAttributes(child); + mySortOptions.appendAttributes(child); + child.setAttribute("priority", String.valueOf(myPriority)); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java index 5310def3f88e..c35cc64163a5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java @@ -24,6 +24,7 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.DefaultRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -35,6 +36,7 @@ import java.util.List; public class DefaultRule implements Rule { + @NotNull public RuleInstance createRuleInstance() { return new DefaultRuleInstance(this); } @@ -47,7 +49,7 @@ public class DefaultRule // does nothing } - public boolean isMatch(RangeEntry entry) { + public boolean isMatch(@NotNull RangeEntry entry) { return !(entry.isFixedHeader() || entry.isFixedTrailer()); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java index 6706b7fae11e..c85fd2cc842a 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java @@ -29,15 +29,14 @@ import com.wrq.rearranger.settings.atomicAttributes.TypeAttribute; import com.wrq.rearranger.settings.atomicAttributes.VolatileAttribute; import com.wrq.rearranger.util.Constraints; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; import java.awt.*; /** Routines to handle field attributes not covered by CommonAttributes. */ -public final class FieldAttributes - extends ItemAttributes -{ +public final class FieldAttributes extends ItemAttributes { // ------------------------------ FIELDS ------------------------------ @@ -88,10 +87,10 @@ public final class FieldAttributes // ------------------------ CANONICAL METHODS ------------------------ public final String toString() { - final StringBuffer sb = new StringBuffer(70); - sb.append(plAttr.getProtectionLevelString()); - sb.append(stAttr.getDescriptiveString()); - sb.append(fAttr.getDescriptiveString()); + final StringBuilder sb = new StringBuilder(70); + sb.append(getProtectionLevelAttributes().getProtectionLevelString()); + sb.append(getStaticAttribute().getDescriptiveString()); + sb.append(getFinalAttribute().getDescriptiveString()); sb.append(transientAttr.getDescriptiveString()); sb.append(volatileAttr.getDescriptiveString()); @@ -109,21 +108,21 @@ public final class FieldAttributes sb.append(" which are not initialized to an anonymous class"); } } - if (nameAttr.isMatch()) { + if (getNameAttribute().isMatch()) { if (initToAnonClassAttr.isValue()) { sb.append(" and"); } sb.append(' '); - sb.append(nameAttr.getDescriptiveString()); + sb.append(getNameAttribute().getDescriptiveString()); } if (typeAttr.isMatch()) { - if (nameAttr.isMatch() || initToAnonClassAttr.isValue()) { + if (getNameAttribute().isMatch() || initToAnonClassAttr.isValue()) { sb.append(" and"); } sb.append(' '); sb.append(typeAttr.getDescriptiveString()); } - sb.append(sortAttr.getDescriptiveString()); + sb.append(getSortOptions().getDescriptiveString()); return sb.toString(); } @@ -132,6 +131,7 @@ public final class FieldAttributes // --------------------- Interface AttributeGroup --------------------- + @NotNull public final /*FieldAttributes*/AttributeGroup deepCopy() { final FieldAttributes result = new FieldAttributes(); deepCopyCommonItems(result); @@ -142,7 +142,8 @@ public final class FieldAttributes return result; } - public final void writeExternal(final Element parent) { + @SuppressWarnings("unchecked") + public final void writeExternal(@NotNull final Element parent) { final Element child = new Element("Field"); writeExternalCommonAttributes(child); initToAnonClassAttr.appendAttributes(child); @@ -173,16 +174,16 @@ public final class FieldAttributes constraints.gridwidth = 1; constraints.gridheight = 4; constraints.weightx = 1.0d; - plPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + plPanel.add(getProtectionLevelAttributes().getProtectionLevelPanel(), constraints); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.gridy = 0; constraints.gridx = 1; constraints.gridheight = 1; constraints.weighty = 0; - plPanel.add(getStAttr().getAndNotPanel(), constraints); + plPanel.add(getStaticAttribute().getAndNotPanel(), constraints); constraints.gridy++; - plPanel.add(getfAttr().getAndNotPanel(), constraints); + plPanel.add(getFinalAttribute().getAndNotPanel(), constraints); constraints.gridy++; plPanel.add(getTransientAttr().getAndNotPanel(), constraints); constraints.gridy++; @@ -192,18 +193,18 @@ public final class FieldAttributes constraints.gridy++; plPanel.add(getInitToAnonClassAttr().getAndNotPanel(), constraints); constraints.gridy++; - plPanel.add(getNameAttr().getStringPanel(), constraints); + plPanel.add(getNameAttribute().getStringPanel(), constraints); constraints.gridy++; plPanel.add(getTypeAttr().getStringPanel(), constraints); constraints.gridy++; constraints.gridheight = GridBagConstraints.REMAINDER; constraints.weighty = 1.0d; constraints.insets = new Insets(0, 0, 0, 0); - plPanel.add(sortAttr.getSortOptionsPanel(), constraints); + plPanel.add(getSortOptions().getSortOptionsPanel(), constraints); return plPanel; } - public boolean isMatch(RangeEntry rangeEntry) { + public boolean isMatch(@NotNull RangeEntry rangeEntry) { return rangeEntry.getEnd() instanceof PsiField && initToAnonClassAttr.isMatch(rangeEntry.getModifiers()) && transientAttr.isMatch(rangeEntry.getModifiers()) && diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java index fe32d118e50f..932046294061 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java @@ -24,14 +24,16 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.HeaderTrailerRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; /** A rule to match header text (text which does not constitute a matchable item such as a field or method.) */ -public class HeaderRule - implements Rule -{ +public class HeaderRule implements Rule { + + @NotNull public RuleInstance createRuleInstance() { return new HeaderTrailerRuleInstance(this); } @@ -45,15 +47,15 @@ public class HeaderRule // does nothing } - public boolean isMatch(RangeEntry rangeEntry) { + public boolean isMatch(@NotNull RangeEntry rangeEntry) { return rangeEntry.isFixedHeader(); } - public boolean commentsMatchGlobalPattern(String pattern) { + public boolean commentsMatchGlobalPattern(@Nullable String pattern) { return true; } - public List getOffendingPatterns(String pattern) { + public List getOffendingPatterns(@Nullable String pattern) { return new ArrayList(1); } @@ -61,6 +63,6 @@ public class HeaderRule return 0; } - public void addCommentPatternsToList(List list) { + public void addCommentPatternsToList(@Nullable List list) { } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java index 80ebd47b7766..5410312ca393 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java @@ -28,6 +28,7 @@ import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.settings.atomicAttributes.AbstractAttribute; import com.wrq.rearranger.settings.atomicAttributes.EnumAttribute; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -72,11 +73,11 @@ public final class InnerClassAttributes // ------------------------ CANONICAL METHODS ------------------------ public final String toString() { - final StringBuffer sb = new StringBuffer(70); + final StringBuilder sb = new StringBuilder(70); sb.append(abAttr.getDescriptiveString()); - sb.append(plAttr.getProtectionLevelString()); - sb.append(stAttr.getDescriptiveString()); - sb.append(fAttr.getDescriptiveString()); + sb.append(getProtectionLevelAttributes().getProtectionLevelString()); + sb.append(getStaticAttribute().getDescriptiveString()); + sb.append(getFinalAttribute().getDescriptiveString()); sb.append(enumAttr.getDescriptiveString()); if (sb.length() == 0) { sb.append("all inner classes"); @@ -84,11 +85,11 @@ public final class InnerClassAttributes else { sb.append("inner classes"); } - if (nameAttr.isMatch()) { + if (getNameAttribute().isMatch()) { sb.append(' '); - sb.append(nameAttr.getDescriptiveString()); + sb.append(getNameAttribute().getDescriptiveString()); } - sb.append(sortAttr.getDescriptiveString()); + sb.append(getSortOptions().getDescriptiveString()); return sb.toString(); } @@ -97,6 +98,7 @@ public final class InnerClassAttributes // --------------------- Interface AttributeGroup --------------------- + @NotNull public final /*InnerClassAttributes*/AttributeGroup deepCopy() { final InnerClassAttributes result = new InnerClassAttributes(); deepCopyCommonItems(result); @@ -105,7 +107,8 @@ public final class InnerClassAttributes return result; } - public final void writeExternal(final Element parent) { + @SuppressWarnings("unchecked") + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("InnerClass"); writeExternalCommonAttributes(me); abAttr.appendAttributes(me); @@ -138,27 +141,27 @@ public final class InnerClassAttributes constraints.weighty = 0.0d; constraints.gridx = constraints.gridy = 0; constraints.insets = new Insets(0, 0, 5, 0); - caPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + caPanel.add(getProtectionLevelAttributes().getProtectionLevelPanel(), constraints); constraints.gridy = 1; constraints.gridheight = 1; - caPanel.add(getStAttr().getAndNotPanel(), constraints); + caPanel.add(getStaticAttribute().getAndNotPanel(), constraints); constraints.gridy++; caPanel.add(getAbAttr().getAndNotPanel(), constraints); constraints.gridy++; - caPanel.add(getfAttr().getAndNotPanel(), constraints); + caPanel.add(getFinalAttribute().getAndNotPanel(), constraints); constraints.gridy++; caPanel.add(getEnumAttr().getAndNotPanel(), constraints); constraints.gridy++; - caPanel.add(getNameAttr().getStringPanel(), constraints); + caPanel.add(getNameAttribute().getStringPanel(), constraints); constraints.gridy++; constraints.gridheight = GridBagConstraints.REMAINDER; constraints.weighty = 1.0d; constraints.insets = new Insets(0, 0, 0, 0); - caPanel.add(sortAttr.getSortOptionsPanel(), constraints); + caPanel.add(getSortOptions().getSortOptionsPanel(), constraints); return caPanel; } - public final boolean isMatch(RangeEntry entry) { + public final boolean isMatch(@NotNull RangeEntry entry) { // return entry.getEnd() instanceof PsiClass && // entry.getEnd() should be the LBrace of a class. return entry.getEnd().getParent() instanceof PsiClass && diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java index 910c0c0d2dfb..fa38d741ed16 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java @@ -31,6 +31,7 @@ import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.atomicAttributes.NameAttribute; import com.wrq.rearranger.util.Constraints; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -136,11 +137,12 @@ public class InterfaceAttributes return priority; } + @NotNull public RuleInstance createRuleInstance() { return new InterfaceRuleInstance(this); } - public final boolean isMatch(RangeEntry rangeEntry) { + public final boolean isMatch(@NotNull RangeEntry rangeEntry) { if (rangeEntry instanceof MethodEntry) { MethodEntry me = (MethodEntry)rangeEntry; if (me.getInterfaceName() != null) { @@ -191,6 +193,7 @@ public class InterfaceAttributes return sb.toString(); } + @NotNull public final /*InterfaceAttributes*/AttributeGroup deepCopy() { final InterfaceAttributes result = new InterfaceAttributes(); result.nameAttr = (NameAttribute)nameAttr.deepCopy(); @@ -225,7 +228,7 @@ public class InterfaceAttributes priority = RearrangerSettings.getIntAttribute(item, "priority", 1); } - public final void writeExternal(final Element parent) { + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("Interface"); parent.getChildren().add(me); nameAttr.appendAttributes(me); diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java index 369c97c14cea..6b1465536b6f 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java @@ -23,14 +23,15 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.settings.CommentRule; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** Routines to handle attributes common to class members (fields, methods, and inner classes.) */ -abstract public class ItemAttributes - extends CommonAttributes -{ +abstract public class ItemAttributes extends CommonAttributes { // -------------------------- STATIC METHODS -------------------------- + @Nullable public static AttributeGroup readExternal(final Element element) { if (element.getName().equals("Field")) { return FieldAttributes.readExternal(element); @@ -57,6 +58,7 @@ abstract public class ItemAttributes // --------------------- Interface AttributeGroup --------------------- + @NotNull abstract public /*ItemAttributes*/AttributeGroup deepCopy(); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java index 79161877cbf8..886ab1d6c46f 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java @@ -29,6 +29,7 @@ import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.atomicAttributes.*; import com.wrq.rearranger.util.MethodUtil; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -252,11 +253,11 @@ public final class MethodAttributes public final String toString() { // convert settings to readable English description of the method. // - final StringBuffer sb = new StringBuffer(80); + final StringBuilder sb = new StringBuilder(80); - sb.append(plAttr.getProtectionLevelString()); - sb.append(stAttr.getDescriptiveString()); - sb.append(fAttr.getDescriptiveString()); + sb.append(getProtectionLevelAttributes().getProtectionLevelString()); + sb.append(getStaticAttribute().getDescriptiveString()); + sb.append(getFinalAttribute().getDescriptiveString()); sb.append(staticInitAttr.getDescriptiveString()); sb.append(nativeAttr.getDescriptiveString()); sb.append(syncAttr.getDescriptiveString()); @@ -332,32 +333,32 @@ public final class MethodAttributes } } } - if (nameAttr.isMatch()) { + if (getNameAttribute().isMatch()) { checkPredicate(sb, false); - nextPredicate = nameAttr.getDescriptiveString(); + nextPredicate = getNameAttribute().getDescriptiveString(); } if (returnTypeAttr.isMatch()) { checkPredicate(sb, false); nextPredicate = returnTypeAttr.getDescriptiveString(); } checkPredicate(sb, true); - sb.append(sortAttr.getDescriptiveString()); + sb.append(getSortOptions().getDescriptiveString()); if (noExtractedMethods) { sb.append(" (no extracted methods)"); } return sb.toString(); } - private void checkPredicate(StringBuffer sb, boolean finalPredicate) { + private void checkPredicate(@NotNull StringBuilder buffer, boolean finalPredicate) { if (predicateAdded && nextPredicate != null) { - sb.append(','); + buffer.append(','); if (finalPredicate) { - sb.append(" and"); + buffer.append(" and"); } } if (nextPredicate != null) { - sb.append(' '); - sb.append(nextPredicate); + buffer.append(' '); + buffer.append(nextPredicate); predicateAdded = true; nextPredicate = null; } @@ -369,6 +370,7 @@ public final class MethodAttributes // --------------------- Interface AttributeGroup --------------------- // Start Methods of Interface AttributeGroup + @NotNull public final /*ItemAttributes*/AttributeGroup deepCopy() { final MethodAttributes result = new MethodAttributes(); deepCopyCommonItems(result); @@ -393,7 +395,8 @@ public final class MethodAttributes return result; } - public final void writeExternal(final Element parent) { + @SuppressWarnings("unchecked") + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("Method"); writeExternalCommonAttributes(me); abstractAttr.appendAttributes(me); @@ -459,7 +462,7 @@ public final class MethodAttributes constraints.weightx = 0.0d; constraints.weighty = 0.0d; constraints.gridx = constraints.gridy = 0; - methodPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + methodPanel.add(getProtectionLevelAttributes().getProtectionLevelPanel(), constraints); constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.gridheight = 1; constraints.gridx = 1; @@ -470,12 +473,12 @@ public final class MethodAttributes constraints.gridx = 0; constraints.gridheight = 1; constraints.gridwidth = 1; - methodPanel.add(getStAttr().getAndNotPanel(), constraints); + methodPanel.add(getStaticAttribute().getAndNotPanel(), constraints); constraints.gridx++; methodPanel.add(getAbstractAttr().getAndNotPanel(), constraints); constraints.gridx = 0; constraints.gridy++; - methodPanel.add(getfAttr().getAndNotPanel(), constraints); + methodPanel.add(getFinalAttribute().getAndNotPanel(), constraints); constraints.gridx++; methodPanel.add(getSyncAttr().getAndNotPanel(), constraints); constraints.gridx = 0; @@ -500,7 +503,7 @@ public final class MethodAttributes constraints.gridy++; methodPanel.add(getMaxParamsAttr().getIntegerPanel(), constraints); constraints.gridy++; - methodPanel.add(getNameAttr().getStringPanel(), constraints); + methodPanel.add(getNameAttribute().getStringPanel(), constraints); constraints.gridy++; methodPanel.add(getReturnTypeAttr().getStringPanel(), constraints); constraints.gridy++; @@ -509,7 +512,7 @@ public final class MethodAttributes constraints.gridy++; constraints.gridheight = GridBagConstraints.REMAINDER; constraints.weighty = 1.0d; - methodPanel.add(sortAttr.getSortOptionsPanel(), constraints); + methodPanel.add(getSortOptions().getSortOptionsPanel(), constraints); return methodPanel; } @@ -601,8 +604,8 @@ public final class MethodAttributes }); gsDefButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - GetterSetterDefinition tempgsd = getterSetterDefinition.deepCopy(); - final JPanel gsDefPanel = tempgsd.getGSDefinitionPanel(); + GetterSetterDefinition tmpDefinition = getterSetterDefinition.deepCopy(); + final JPanel gsDefPanel = tmpDefinition.getGSDefinitionPanel(); final JOptionPane op = new JOptionPane( gsDefPanel, JOptionPane.PLAIN_MESSAGE, @@ -614,7 +617,7 @@ public final class MethodAttributes if (result != null && ((Integer)result) == JOptionPane.OK_OPTION) { - getterSetterDefinition = tempgsd; + getterSetterDefinition = tmpDefinition; } } }); @@ -625,7 +628,7 @@ public final class MethodAttributes // End Methods of Interface AttributeGroup // Start Methods of Interface IRule - public final boolean isMatch(RangeEntry entry) { + public final boolean isMatch(@NotNull RangeEntry entry) { final boolean result = (entry.getEnd() instanceof PsiMethod || entry.getEnd() instanceof PsiClassInitializer) && super.isMatch(entry) && @@ -640,12 +643,12 @@ public final class MethodAttributes returnTypeAttr.isMatch(entry.getType()) && minParamsAttr.isMatch(entry.getEnd()) && maxParamsAttr.isMatch(entry.getEnd()); - if (result == false) { + if (!result) { return false; } boolean typeResult = false; if (isConstructorMethodType()) { - typeResult |= (entry.getModifiers() & ModifierConstants.CONSTRUCTOR) == ModifierConstants.CONSTRUCTOR; + typeResult = (entry.getModifiers() & ModifierConstants.CONSTRUCTOR) == ModifierConstants.CONSTRUCTOR; } if (isGetterSetterMethodType() && entry.getEnd() instanceof PsiMethod) @@ -674,7 +677,7 @@ public final class MethodAttributes { typeResult = true; // true if no method type options are selected. } - return result && typeResult; + return typeResult; } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/Rule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/Rule.java index 7cffb45bad01..586b58c9d5a0 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/Rule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/Rule.java @@ -23,20 +23,23 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; import java.util.List; /** Interface which all rules implement. */ public interface Rule { + + @NotNull RuleInstance createRuleInstance(); // all rules have a priority; but some are not settable by the user. Those that are user settable implement - // the marker interface IPrioritizableRule. + // the marker interface PrioritizedRule. int getPriority(); void setPriority(int priority); - boolean isMatch(RangeEntry rangeEntry); + boolean isMatch(@NotNull RangeEntry rangeEntry); /** * @param pattern global pattern to which all comments should conform. diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java index b7d42af98487..1f4ac75175ad 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java @@ -24,6 +24,7 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.HeaderTrailerRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -32,6 +33,7 @@ import java.util.List; public class TrailerRule implements Rule { + @NotNull public RuleInstance createRuleInstance() { return new HeaderTrailerRuleInstance(this); } @@ -45,7 +47,7 @@ public class TrailerRule // does nothing } - public boolean isMatch(RangeEntry rangeEntry) { + public boolean isMatch(@NotNull RangeEntry rangeEntry) { return rangeEntry.isFixedTrailer(); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java b/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java index 2ba03562ded4..f9d179c2a714 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java +++ b/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java @@ -21,8 +21,10 @@ */ package com.wrq.rearranger.util; +import com.intellij.openapi.util.text.StringUtil; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.attributeGroups.Rule; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -30,40 +32,38 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class CommentUtil { - final RearrangerSettings settings; - static CommentUtil singleton; - List commentStrings; - List commentMatchers; + private final RearrangerSettings mySettings; + static CommentUtil singleton; + private final List myCommentStrings = new ArrayList(); + private final List myCommentMatchers = new ArrayList(); - public CommentUtil(RearrangerSettings settings) { - this.settings = settings; + public CommentUtil(@NotNull RearrangerSettings settings) { + mySettings = settings; createCommentPatternList(); createCommentMatcherList(); singleton = this; } public static List getCommentStrings() { - return singleton.commentStrings; + return singleton.myCommentStrings; } public static List getCommentMatchers() { - return singleton.commentMatchers; + return singleton.myCommentMatchers; } private void createCommentMatcherList() { - if (settings.getGlobalCommentPattern() != null && - settings.getGlobalCommentPattern().length() > 0) - { - // create only one Matcher for the global comment pattern. - commentMatchers = new ArrayList(1); - commentMatchers.add((getMatcher(settings.getGlobalCommentPattern()))); + if (StringUtil.isEmpty(mySettings.getGlobalCommentPattern())) { + myCommentMatchers.clear(); + for (String comment : myCommentStrings) { + Matcher matcher = getMatcher(comment); + myCommentMatchers.add(matcher); + } } else { - commentMatchers = new ArrayList(commentStrings.size()); - for (String comment : commentStrings) { - Matcher matcher = getMatcher(comment); - commentMatchers.add(matcher); - } + // create only one Matcher for the global comment pattern. + myCommentMatchers.clear(); + myCommentMatchers.add((getMatcher(mySettings.getGlobalCommentPattern()))); } } @@ -78,7 +78,7 @@ public class CommentUtil { * any leading space. */ private Matcher getMatcher(String comment) { - StringBuffer sb = new StringBuffer(comment); + StringBuilder sb = new StringBuilder(comment); /** * remove any literal newline characters or escaped equivalent ('\n') at beginning of comment. */ @@ -122,20 +122,19 @@ public class CommentUtil { } private void createCommentPatternList() { - commentStrings = new ArrayList(); - for (Rule rule : settings.getClassOrderAttributeList()) { - rule.addCommentPatternsToList(commentStrings); + for (Rule rule : mySettings.getClassOrderAttributeList()) { + rule.addCommentPatternsToList(myCommentStrings); } - for (Rule rule : settings.getItemOrderAttributeList()) { - rule.addCommentPatternsToList(commentStrings); + for (Rule rule : mySettings.getItemOrderAttributeList()) { + rule.addCommentPatternsToList(myCommentStrings); } - settings.getExtractedMethodsSettings().addCommentPatternsToList(commentStrings); + mySettings.getExtractedMethodsSettings().addCommentPatternsToList(myCommentStrings); } /** * Calculate the apparent length of a string if tabs are expanded. * Leading tabs are no problem; embedded tabs would be, if the %FS% fill string expansions are not multiples of - * "%FS%".length() == 4, because after expansion the embedded tabs would misalign. However, I'm not going to + * "%FS%".length() == 4, because after expansion the embedded tabs would mis-align. However, I'm not going to * address that yet. (This is just to fix Thomas Singer's bug with leading tab.) * * @param s @@ -171,9 +170,9 @@ public class CommentUtil { int tabSize, String fillString) { - StringBuffer result = new StringBuffer(comment.length() * 2); + StringBuilder result = new StringBuilder(comment.length() * 2); int EOLindex = 0; - StringBuffer fillChars = new StringBuffer(); + StringBuilder fillChars = new StringBuilder(); if (fillString.length() == 0) { fillString = " "; // fill with spaces if no pattern supplied } diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy index a0667d6e1593..66d7b516f84f 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy +++ b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy @@ -25,6 +25,9 @@ package com.wrq.rearranger; import com.intellij.openapi.application.ApplicationManager import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.wrq.rearranger.settings.RearrangerSettings +import com.wrq.rearranger.settings.attributeGroups.ClassAttributes +import com.wrq.rearranger.settings.attributeGroups.FieldAttributes +import com.wrq.rearranger.settings.attributeGroups.MethodAttributes import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable @@ -46,82 +49,57 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase { mySettings.showParameterNames = true mySettings.showParameterTypes = true mySettings.showRules = true - mySettings.rearrangeInnerClasses =true + mySettings.rearrangeInnerClasses = true } public final void testNoRearrangement() throws Exception { doTest('RearrangementTest', 'NoRearrangementResult1') } -// public final void testPublicFieldRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final FieldAttributes fa; -// fa = new FieldAttributes(); -// fa.getPlAttr().setPlPublic(true); -// rs.addItem(fa, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult2.java"); -// } -// -// public final void testNotPublicFieldRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final FieldAttributes fa; -// fa = new FieldAttributes(); -// fa.getPlAttr().setPlPublic(true); -// fa.getPlAttr().setInvertProtectionLevel(true); -// rs.addItem(fa, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult3.java"); -// } -// -// public final void testConstructorRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final MethodAttributes ma; -// ma = new MethodAttributes(); -// ma.getPlAttr().setPlPackage(true); -// ma.getPlAttr().setPlPublic(true); -// ma.setConstructorMethodType(true); -// rs.addItem(ma, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult4.java"); -// } -// -// public final void testClassRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final ClassAttributes ca = new ClassAttributes(); -// ca.getPlAttr().setPlPackage(true); -// rs.addClass(ca, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult5.java"); -// } -// -// public final void testPSFRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest2.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final FieldAttributes fa; -// fa = new FieldAttributes(); -// fa.getPlAttr().setPlPublic(true); -// fa.getfAttr().setValue(true); -// fa.getStAttr().setValue(true); -// rs.addItem(fa, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult6.java"); -// } -// + public final void testPublicFieldRearrangement() throws Exception { + doTest('RearrangementTest', 'RearrangementResult2') { + def attributes = new FieldAttributes() + attributes.protectionLevelAttributes.plPublic = true + mySettings.addItem(attributes, 0) + } + } + + public final void testNotPublicFieldRearrangement() throws Exception { + doTest('RearrangementTest', 'RearrangementResult3') { + def attributes = new FieldAttributes() + attributes.protectionLevelAttributes.plPublic = true + attributes.protectionLevelAttributes.invertProtectionLevel = true + mySettings.addItem(attributes, 0) + } + } + + public final void testConstructorRearrangement() throws Exception { + doTest('RearrangementTest', 'RearrangementResult4') { + def attributes = new MethodAttributes() + attributes.protectionLevelAttributes.plPackage = true + attributes.protectionLevelAttributes.plPublic = true + attributes.constructorMethodType = true + mySettings.addItem(attributes, 0) + } + } + + public final void testClassRearrangement() throws Exception { + doTest('RearrangementTest', 'RearrangementResult5') { + def attributes = new ClassAttributes() + attributes.protectionLevelAttributes.plPackage = true + mySettings.addClass(attributes, 0) + } + } + + public final void testPSFRearrangement() throws Exception { + doTest('RearrangementTest2', 'RearrangementResult6') { + def attributes = new FieldAttributes() + attributes.finalAttribute.value = true + attributes.staticAttribute.value = true + mySettings.addItem(attributes, 0) + } + } + // public final void testAnonClassInit() throws Exception { // configureByFile("/com/wrq/rearranger/RearrangementTest7.java"); // final PsiFile file = getFile(); @@ -2178,8 +2156,11 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase { // super.checkResultByFile("/com/wrq/rearranger/BitFieldResult.java"); // } - private void doTest(@NotNull String srcFileName, @Nullable String expectedResultFileName) { + private void doTest(@NotNull String srcFileName, @Nullable String expectedResultFileName, @Nullable Closure adjustment = null) { myFixture.configureByFile("${srcFileName}.java") + if (adjustment) { + adjustment.call() + } ApplicationManager.application.runWriteAction { new RearrangerActionHandler().rearrangeDocument(myFixture.project, myFixture.file, mySettings, myFixture.editor.document); } diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java b/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java index ccb6a4281ad3..e854f418c2e7 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java +++ b/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java @@ -14,7 +14,7 @@ public class MethodAttributesTest public void testToString() throws Exception { ma = new MethodAttributes(); // test various combinations of min/max parameters, name, and return type. - ma.getPlAttr().setPlPublic(true); + ma.getProtectionLevelAttributes().setPlPublic(true); // min = ? max = ? name = ? return = ? setma(false, 0, false, 0, null, null, "public methods"); // min = 1 max = ? name = ? return = ? @@ -57,8 +57,8 @@ public class MethodAttributesTest ma.getMinParamsAttr().setValue(min); ma.getMaxParamsAttr().setMatch(maxMatch); ma.getMaxParamsAttr().setValue(max); - ma.getNameAttr().setMatch(name != null); - ma.getNameAttr().setExpression(name); + ma.getNameAttribute().setMatch(name != null); + ma.getNameAttribute().setExpression(name); ma.getReturnTypeAttr().setMatch(returnValue != null); ma.getReturnTypeAttr().setExpression(returnValue); assertEquals("wrong description", description, ma.toString()); diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java index 186f0581ef94..1c4b9471883d 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java @@ -10,8 +10,8 @@ public class RearrangementTest { /** field 1. */ private int field1; private int field2; - final int field5 = 5; - protected int field6 = 6; + final int field5 = 5; + protected int field6 = 6; /** method 1 comment. */ void method1() { diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java index 12b241aa0be4..014128616905 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java @@ -9,7 +9,6 @@ public class RearrangementTest { NoRearrangementTest() { // constructor body } - /** field 1. */ private int field1; private int field2; diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java index 84252bc72ceb..ad906364d310 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java @@ -1,8 +1,8 @@ public class Test { public static final String sillyField = ""; public static final String sillyField2 = ""; - private String wibble; - protected String wobble; - public String hitandmiss; + private String wibble; + protected String wobble; + public String hitandmiss; public static int hithere; } diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java index c94e9d4546f9..3a4ccb580857 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java @@ -1,8 +1,8 @@ public class Test { private String wibble; protected String wobble; - public static final String sillyField = ""; - public String hitandmiss; + public static final String sillyField = ""; + public String hitandmiss; public static int hithere; public static final String sillyField2 = ""; } diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index afcfce689893..540078755e40 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -317,7 +317,7 @@ class.filters.dialog.inclusion.filters.group=Class Filters class.filters.dialog.exclusion.filters.group=Class Exclusion Filters instance.filters.dialog.title=Instance Filters instance.filters.dialog.instance.filters.group=Instance Filters -breakpoint.exception.breakpoint.display.name=Exception breakpoint, class ''{0}'' +breakpoint.exception.breakpoint.display.name=''{0}'' exception.breakpoints.tab.title=Exception Breakpoints field.watchpoints.tab.title=Field Watchpoints line.breakpoints.tab.title=Line Breakpoints