From b7c197055f361b5109bd777f033713c4cbf6e011 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 20 Aug 2014 02:18:31 +0200 Subject: [PATCH 01/31] fix VMDisconnectedException and others --- .../impl/evaluate/XDebuggerEditorLinePainter.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java index 32ab0f968c1e..d15180a2c3b4 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java @@ -60,10 +60,14 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter { XValueTextRendererImpl renderer = new XValueTextRendererImpl(text); final XValuePresentation presentation = value.getValuePresentation(); if (presentation == null) continue; - if (presentation instanceof XValueCompactPresentation) { - ((XValueCompactPresentation)presentation).renderValue(renderer, value); - } else { - presentation.renderValue(renderer); + try { + if (presentation instanceof XValueCompactPresentation) { + ((XValueCompactPresentation)presentation).renderValue(renderer, value); + } else { + presentation.renderValue(renderer); + } + } catch (Exception e) { + continue; } final Color color = new JBColor(new Color(61, 128, 101), new Color(61, 128, 101)); final String name = value.getName(); From cae17c62f6145f6bbeb183eae36286ccbacb902b Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 20 Aug 2014 19:13:29 +0400 Subject: [PATCH 02/31] asynchronously refresh roots under source content according to "files_generated" build events (IDEA-128703 IDEA does not refresh sources files generated by an external builder) --- .../compiler/server/BuildManager.java | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index c40135db7c5f..f176f87373bc 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -34,7 +34,9 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.compiler.CompilationStatusListener; import com.intellij.openapi.compiler.CompileContext; +import com.intellij.openapi.compiler.CompilerTopics; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.EditorFactory; @@ -64,16 +66,14 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.openapi.vfs.newvfs.impl.FileNameCache; import com.intellij.openapi.wm.IdeFrame; -import com.intellij.util.Alarm; -import com.intellij.util.Function; -import com.intellij.util.PathUtil; -import com.intellij.util.SmartList; +import com.intellij.util.*; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.concurrency.SequentialTaskExecutor; import com.intellij.util.containers.IntArrayList; @@ -1117,6 +1117,44 @@ public class BuildManager implements ApplicationComponent{ scheduleAutoMake(); } }); + conn.subscribe(CompilerTopics.COMPILATION_STATUS, new CompilationStatusListener() { + private final Set myRootsToRefresh = new THashSet(FileUtil.PATH_HASHING_STRATEGY); + @Override + public void compilationFinished(boolean aborted, int errors, int warnings, CompileContext compileContext) { + synchronized (myRootsToRefresh) { + final String[] roots = ArrayUtil.toStringArray(myRootsToRefresh); + myRootsToRefresh.clear(); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + if (project.isDisposed()) { + return; + } + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + final LocalFileSystem lfs = LocalFileSystem.getInstance(); + final Set filesToRefresh = new HashSet(); + for (String root : roots) { + final VirtualFile rootFile = lfs.refreshAndFindFileByPath(root); + if (rootFile != null && fileIndex.isInSourceContent(rootFile)) { + filesToRefresh.add(rootFile); + } + } + if (!filesToRefresh.isEmpty()) { + lfs.refreshFiles(filesToRefresh, true, true, null); + } + } + }); + } + + } + + @Override + public void fileGenerated(String outputRoot, String relativePath) { + synchronized (myRootsToRefresh) { + myRootsToRefresh.add(outputRoot); + } + } + }); final String projectPath = getProjectPath(project); Disposer.register(project, new Disposable() { @Override From 9609ba85dcbdee8e51b53632485a6b8cb28d5f95 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 20 Aug 2014 19:51:41 +0400 Subject: [PATCH 03/31] Refactoring: extract SettingsFilter from OptionsTree. --- .../options/newEditor/OptionsEditor.java | 365 +++++------------- .../options/newEditor/OptionsTree.java | 58 +-- .../options/newEditor/SettingsFilter.java | 211 ++++++++++ .../options/newEditor/SettingsTreeView.java | 83 ++-- .../util/resources/misc/registry.properties | 1 - 5 files changed, 341 insertions(+), 377 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java index eb70cf0a01f2..e1c8e34077a9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java @@ -16,9 +16,7 @@ package com.intellij.openapi.options.newEditor; import com.intellij.icons.AllIcons; -import com.intellij.ide.ui.search.ConfigurableHit; import com.intellij.ide.ui.search.SearchUtil; -import com.intellij.ide.ui.search.SearchableOptionsRegistrar; import com.intellij.ide.util.PropertiesComponent; import com.intellij.internal.statistic.UsageTrigger; import com.intellij.internal.statistic.beans.ConvertUsagesUtil; @@ -38,9 +36,7 @@ import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.EdtRunnable; import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeGlassPaneUtil; -import com.intellij.ui.DocumentAdapter; import com.intellij.ui.LightColors; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.SearchTextField; @@ -49,7 +45,6 @@ import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.navigation.History; import com.intellij.ui.navigation.Place; -import com.intellij.ui.speedSearch.ElementFilter; import com.intellij.ui.treeStructure.SimpleNode; import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.util.ui.UIUtil; @@ -63,7 +58,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.*; import java.beans.PropertyChangeEvent; @@ -79,23 +73,18 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat @NonNls private static final String MAIN_SPLITTER_PROPORTION = "options.splitter.main.proportions"; @NonNls private static final String DETAILS_SPLITTER_PROPORTION = "options.splitter.details.proportions"; - @NonNls private static final String SEARCH_VISIBLE = "options.searchVisible"; - @NonNls private static final String NOT_A_NEW_COMPONENT = "component.was.already.instantiated"; - private final Project myProject; - - private final OptionsEditorContext myContext; - private final History myHistory = new History(this); private final OptionsTree myTree; private final SettingsTreeView myTreeView; - private final MySearchField mySearch; + private final SearchTextField mySearch; private final Splitter myMainSplitter; //[back/forward] JComponent myToolbarComponent; - private final DetailsComponent myOwnDetails = new DetailsComponent().setEmptyContentText("Select configuration element in the tree to edit its settings"); + private final DetailsComponent myOwnDetails = + new DetailsComponent().setEmptyContentText("Select configuration element in the tree to edit its settings"); private final ContentWrapper myContentWrapper = new ContentWrapper(); @@ -103,29 +92,53 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat private final Map myConfigurable2LoadCallback = new HashMap(); private final MergingUpdateQueue myModificationChecker; - private final ConfigurableGroup[] myGroups; private final SpotlightPainter mySpotlightPainter = new SpotlightPainter(); private final MergingUpdateQueue mySpotlightUpdate; private final LoadingDecorator myLoadingDecorator; - private final Filter myFilter; + private final SettingsFilter myFilter; private final Wrapper mySearchWrapper = new Wrapper(); private final JPanel myLeftSide; - private boolean myFilterDocumentWasChanged; //[back/forward] private ActionToolbar myToolbar; private Window myWindow; private final PropertiesComponent myProperties; private volatile boolean myDisposed; - public OptionsEditor(Project project, ConfigurableGroup[] groups, Configurable preselectedConfigurable) { - myProject = project; - myGroups = groups; - myProperties = PropertiesComponent.getInstance(project); + private final KeyListener myTreeKeyListener = new KeyListener() { + @Override + public void keyPressed(KeyEvent event) { + keyTyped(event); + } - myFilter = new Filter(); - myContext = new OptionsEditorContext(myFilter); + @Override + public void keyReleased(KeyEvent event) { + keyTyped(event); + } + + @Override + public void keyTyped(KeyEvent event) { + Object source = event.getSource(); + if (source instanceof JTree) { + JTree tree = (JTree)source; + if (tree.getInputMap().get(KeyStroke.getKeyStrokeForEvent(event)) == null) { + myFilter.myDocumentWasChanged = false; + try { + mySearch.keyEventToTextField(event); + } + finally { + if (myFilter.myDocumentWasChanged && !isFilterFieldVisible()) { + setFilterFieldVisible(true, false, false); + } + } + } + } + } + }; + + public OptionsEditor(Project project, ConfigurableGroup[] groups, Configurable preselectedConfigurable) { + myProperties = PropertiesComponent.getInstance(project); mySearch = new MySearchField() { @Override @@ -139,67 +152,53 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat } }; - mySearch.getTextEditor().addMouseListener(new MouseAdapter() { + myFilter = new SettingsFilter(project, groups, mySearch) { @Override - public void mousePressed(MouseEvent e) { - boolean hasText = mySearch.getText().length() > 0; - if (!myContext.isHoldingFilter() && hasText) { - myFilter.reenable(); - } - - if (!isSearchFieldFocused() && hasText) { - mySearch.selectText(); - } - } - }); - - final KeyListener listener = new KeyListener() { - @Override - public void keyTyped(KeyEvent event) { - myFilterDocumentWasChanged = false; - try { - mySearch.keyEventToTextField(event); - } - finally { - if (myFilterDocumentWasChanged && !isFilterFieldVisible()) { - setFilterFieldVisible(true, false, false); - } + Configurable getConfigurable(SimpleNode node) { + if (node instanceof OptionsTree.EditorNode) { + return ((OptionsTree.EditorNode)node).getConfigurable(); } + return SettingsTreeView.getConfigurable(node); } @Override - public void keyPressed(KeyEvent event) { - keyTyped(event); + SimpleNode findNode(Configurable configurable) { + return myTreeView != null + ? myTreeView.findNode(configurable) + : myTree.findNodeFor(configurable); } @Override - public void keyReleased(KeyEvent event) { - keyTyped(event); + void updateSpotlight(boolean now) { + if (!now) { + mySpotlightUpdate.queue(new Update(this) { + @Override + public void run() { + if (!mySpotlightPainter.updateForCurrentConfigurable()) { + updateSpotlight(false); + } + } + }); + } + else if (!mySpotlightPainter.updateForCurrentConfigurable()) { + updateSpotlight(false); + } } }; - if (Registry.is("ide.file.settings.tree.new")) { - myTreeView = new SettingsTreeView(listener, getContext(), groups); + + if (Registry.is("ide.new.settings.dialog")) { + myTreeView = new SettingsTreeView(myFilter, groups); + myTreeView.myTree.addKeyListener(myTreeKeyListener); myTree = null; } else { myTreeView = null; - myTree = new OptionsTree(myProject, groups, getContext()) { - @Override - protected void onTreeKeyEvent(final KeyEvent e) { - listener.keyTyped(e); - } - }; + myTree = new OptionsTree(myFilter, groups); + myTree.addKeyListener(myTreeKeyListener); } getContext().addColleague(myTreeView != null ? myTreeView : myTree); Disposer.register(this, myTreeView != null ? myTreeView : myTree); - mySearch.addDocumentListener(new DocumentAdapter() { - @Override - protected void textChanged(DocumentEvent e) { - myFilter.update(e.getType(), true, false); - } - }); - /* [back/forward] final DefaultActionGroup toolbarActions = new DefaultActionGroup(); @@ -266,13 +265,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat mySpotlightUpdate = new MergingUpdateQueue("OptionsSpotlight", 200, false, this, this, this); if (preselectedConfigurable != null) { - if (myTreeView != null) { - myTreeView.select(preselectedConfigurable); - } - else { - myTree.select(preselectedConfigurable); - } - } else { + selectInTree(preselectedConfigurable); + } + else { if (myTreeView != null) { myTreeView.selectFirst(); } @@ -324,6 +319,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat }); } + private ActionCallback selectInTree(Configurable configurable) { + return myTreeView != null + ? myTreeView.select(configurable) + : myTree.select(configurable); + } + /** @see #select(com.intellij.openapi.options.Configurable) */ @Deprecated public ActionCallback select(Class configurableClass) { @@ -356,18 +357,17 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat } public ActionCallback select(Configurable configurable) { - if (StringUtil.isEmpty(mySearch.getText())) { + if (myFilter.getFilterText().isEmpty()) { return select(configurable, ""); - } else { - return myFilter.refilterFor(mySearch.getText(), true, true); + } + else { + return myFilter.update(true, true); } } public ActionCallback select(Configurable configurable, final String text) { - myFilter.refilterFor(text, false, true); - return myTreeView != null - ? myTreeView.select(configurable) - : myTree.select(configurable); + myFilter.update(text, false, true); + return selectInTree(configurable); } private float readProportion(final float defaultValue, final String propertyName) { @@ -392,7 +392,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat if (configurable == null) { myOwnDetails.setContent(null); - updateSpotlight(true); + myFilter.updateSpotlight(true); checkModified(oldConfigurable); result.setDone(); @@ -432,7 +432,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat myLoadingDecorator.stopLoading(); - updateSpotlight(false); + myFilter.updateSpotlight(false); checkModified(oldConfigurable); checkModified(configurable); @@ -482,7 +482,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat ((ApplicationEx)app).runEdtSafeAction(new Runnable() { @Override public void run() { - if (myProject.isDisposed()) { + if (myFilter.myProject.isDisposed()) { result.setRejected(); } else { @@ -539,26 +539,6 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat return result; } - - private void updateSpotlight(boolean now) { - if (now) { - final boolean success = mySpotlightPainter.updateForCurrentConfigurable(); - if (!success) { - updateSpotlight(false); - } - } else { - mySpotlightUpdate.queue(new Update(this) { - @Override - public void run() { - final boolean success = mySpotlightPainter.updateForCurrentConfigurable(); - if (!success) { - updateSpotlight(false); - } - } - }); - } - } - private String[] getBannerText(Configurable configurable) { if (myTreeView != null) { return myTreeView.getPathNames(configurable); @@ -714,7 +694,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat @Override public boolean isEnabled() { - return myContext.isModified(myConfigurable) || getContext().getErrors().containsKey(myConfigurable); + return myFilter.myContext.isModified(myConfigurable) || getContext().getErrors().containsKey(myConfigurable); } } @@ -851,12 +831,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat getContext().fireErrorsChanged(errors, null); if (!errors.isEmpty()) { - if (myTreeView != null) { - myTreeView.select(errors.keySet().iterator().next()); - } - else { - myTree.select(errors.keySet().iterator().next()); - } + selectInTree(errors.keySet().iterator().next()); } } @@ -878,145 +853,6 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat return new Dimension(1200, 768); } - private class Filter extends ElementFilter.Active.Impl { - - SearchableOptionsRegistrar myIndex = SearchableOptionsRegistrar.getInstance(); - Set myFiltered = null; - ConfigurableHit myHits; - - boolean myUpdateEnabled = true; - private Configurable myLastSelected; - - @Override - public boolean shouldBeShowing(final SimpleNode value) { - if (myFiltered == null) return true; - - if (value instanceof OptionsTree.EditorNode) { - final OptionsTree.EditorNode node = (OptionsTree.EditorNode)value; - return myFiltered.contains(node.getConfigurable()) || isChildOfNameHit(node); - } - - return SettingsTreeView.isFiltered(myFiltered, myHits, value); - } - - private boolean isChildOfNameHit(OptionsTree.EditorNode node) { - if (myHits != null) { - OptionsTree.Base eachParent = node; - while (eachParent != null) { - if (eachParent instanceof OptionsTree.EditorNode) { - final OptionsTree.EditorNode eachEditorNode = (OptionsTree.EditorNode)eachParent; - if (myHits.getNameFullHits().contains(eachEditorNode.myConfigurable)) return true; - } - eachParent = (OptionsTree.Base)eachParent.getParent(); - } - - return false; - } - - return false; - } - - public ActionCallback refilterFor(String text, boolean adjustSelection, final boolean now) { - try { - myUpdateEnabled = false; - mySearch.setText(text); - } - finally { - myUpdateEnabled = true; - } - - return update(DocumentEvent.EventType.CHANGE, adjustSelection, now); - } - - public void clearTemporary() { - myContext.setHoldingFilter(false); - updateSpotlight(false); - } - - public void reenable() { - myContext.setHoldingFilter(true); - updateSpotlight(false); - } - - public ActionCallback update(DocumentEvent.EventType type, boolean adjustSelection, boolean now) { - if (!myUpdateEnabled) return new ActionCallback.Rejected(); - - final String text = mySearch.getText(); - if (getFilterText().length() == 0) { - myContext.setHoldingFilter(false); - myFiltered = null; - } else { - myContext.setHoldingFilter(true); - myHits = myIndex.getConfigurables(myGroups, type, myFiltered, text, myProject); - myFiltered = myHits.getAll(); - } - - if (myFiltered != null && myFiltered.isEmpty()) { - mySearch.getTextEditor().setBackground(LightColors.RED); - } else { - mySearch.getTextEditor().setBackground(UIUtil.getTextFieldBackground()); - } - - - final Configurable current = getContext().getCurrentConfigurable(); - - boolean shouldMoveSelection = true; - - if (myHits != null && (myHits.getNameFullHits().contains(current) || myHits.getContentHits().contains(current))) { - shouldMoveSelection = false; - } - - if (shouldMoveSelection && type != DocumentEvent.EventType.INSERT && (myFiltered == null || myFiltered.contains(current))) { - shouldMoveSelection = false; - } - - Configurable toSelect = adjustSelection ? current : null; - if (shouldMoveSelection && myHits != null) { - if (!myHits.getNameHits().isEmpty()) { - toSelect = suggestToSelect(myHits.getNameHits(), myHits.getNameFullHits()); - } else if (!myHits.getContentHits().isEmpty()) { - toSelect = suggestToSelect(myHits.getContentHits(), null); - } - } - - updateSpotlight(false); - - if ((myFiltered == null || !myFiltered.isEmpty()) && toSelect == null && myLastSelected != null) { - toSelect = myLastSelected; - myLastSelected = null; - } - - if (toSelect == null && current != null) { - myLastSelected = current; - } - - SimpleNode node = !adjustSelection ? null : myTreeView != null ? myTreeView.findNode(toSelect) : myTree.findNodeFor(toSelect); - final ActionCallback callback = fireUpdate(node, adjustSelection, now); - - myFilterDocumentWasChanged = true; - - return callback; - } - - private boolean isEmptyParent(Configurable configurable) { - return configurable instanceof SearchableConfigurable.Parent && !((SearchableConfigurable.Parent)configurable).hasOwnContent(); - } - - @Nullable - private Configurable suggestToSelect(Set set, Set fullHits) { - Configurable candidate = null; - for (Configurable each : set) { - if (fullHits != null && fullHits.contains(each)) return each; - if (!isEmptyParent(each) && candidate == null) { - candidate = each; - } - } - - return candidate; - } - - } - @Override public ActionCallback navigateTo(@Nullable final Place place, final boolean requestFocus) { final Configurable config = (Configurable)place.getPath("configurable"); @@ -1024,15 +860,10 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat final ActionCallback result = new ActionCallback(); - myFilter.refilterFor(filter, false, true).doWhenDone(new Runnable() { + myFilter.update(filter, false, true).doWhenDone(new Runnable() { @Override public void run() { - if (myTreeView != null) { - myTreeView.select(config).notifyWhenDone(result); - } - else { - myTree.select(config).notifyWhenDone(result); - } + selectInTree(config).notifyWhenDone(result); } }); @@ -1043,7 +874,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat public void queryPlace(@NotNull final Place place) { final Configurable current = getContext().getCurrentConfigurable(); place.putPath("configurable", current); - place.putPath("filter", getFilterText()); + place.putPath("filter", myFilter.getFilterText()); if (current instanceof Place.Navigator) { ((Place.Navigator)current).queryPlace(place); @@ -1062,7 +893,6 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat myProperties.setValue(MAIN_SPLITTER_PROPORTION, String.valueOf(myMainSplitter.getProportion())); myProperties.setValue(DETAILS_SPLITTER_PROPORTION, String.valueOf(myContentWrapper.myLastSplitterProportion)); - myProperties.setValue(SEARCH_VISIBLE, Boolean.valueOf(isFilterFieldVisible()).toString()); Toolkit.getDefaultToolkit().removeAWTEventListener(this); @@ -1089,7 +919,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat } public OptionsEditorContext getContext() { - return myContext; + return myFilter.myContext; } private class MyColleague extends OptionsEditorColleague.Adapter { @@ -1139,7 +969,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat final MouseEvent me = (MouseEvent)event; if (SwingUtilities.isDescendingFrom(me.getComponent(), SwingUtilities.getWindowAncestor(myContentWrapper)) || isPopupOverEditor(me.getComponent())) { queueModificationCheck(); - myFilter.clearTemporary(); + myFilter.setHoldingFilter(false); } } else if (event.getID() == KeyEvent.KEY_PRESSED || event.getID() == KeyEvent.KEY_RELEASED) { @@ -1238,7 +1068,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat return ApplicationManager.getApplication().isUnitTestMode(); } - String text = getFilterText(); + String text = myFilter.getFilterText(); try { final boolean sameText = @@ -1265,14 +1095,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat myVisible = true;//myContext.isHoldingFilter(); runnable.run(); - boolean pushFilteringFurther = true; - if (sameText) { - pushFilteringFurther = false; - } else { - if (myFilter.myHits != null) { - pushFilteringFurther = !myFilter.myHits.getNameHits().contains(current); - } - } + boolean pushFilteringFurther = !sameText && !myFilter.contains(current); final Runnable ownSearch = searchable.enableSearch(text); if (pushFilteringFurther && ownSearch != null) { @@ -1297,10 +1120,6 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat } } - private String getFilterText() { - return mySearch.getText() != null ? mySearch.getText().trim() : ""; - } - private static class SearachableWrappper implements SearchableConfigurable { private final Configurable myConfigurable; diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java index df72340d1cd1..18a953593275 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java @@ -59,23 +59,20 @@ import java.util.*; import java.util.List; public class OptionsTree extends JPanel implements Disposable, OptionsEditorColleague { - Project myProject; + private final SettingsFilter myFilter; final SimpleTree myTree; List myGroups; FilteringTreeBuilder myBuilder; Root myRoot; - OptionsEditorContext myContext; Map myConfigurable2Node = new HashMap(); MergingUpdateQueue mySelection; private final OptionsTree.Renderer myRenderer; - public OptionsTree(Project project, ConfigurableGroup[] groups, OptionsEditorContext context) { - myProject = project; + public OptionsTree(SettingsFilter filter, ConfigurableGroup... groups) { + myFilter = filter; myGroups = Arrays.asList(groups); - myContext = context; - myRoot = new Root(); final SimpleTreeStructure structure = new SimpleTreeStructure() { @@ -132,35 +129,8 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl } } }); - myTree.addKeyListener(new KeyListener() { - public void keyTyped(final KeyEvent e) { - _onTreeKeyEvent(e); - } - - public void keyPressed(final KeyEvent e) { - _onTreeKeyEvent(e); - } - - public void keyReleased(final KeyEvent e) { - _onTreeKeyEvent(e); - } - }); } - protected void _onTreeKeyEvent(KeyEvent e) { - final KeyStroke stroke = KeyStroke.getKeyStrokeForEvent(e); - - final Object action = myTree.getInputMap().get(stroke); - if (action == null) { - onTreeKeyEvent(e); - } - } - - protected void onTreeKeyEvent(KeyEvent e) { - - } - - ActionCallback select(@Nullable Configurable configurable) { return queueSelection(configurable); } @@ -191,7 +161,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl if (configurable == null) { myTree.getSelectionModel().clearSelection(); - myContext.fireSelected(null, OptionsTree.this); + myFilter.myContext.fireSelected(null, OptionsTree.this); } else { myBuilder.getReady(this).doWhenDone(new Runnable() { @@ -232,7 +202,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl } private void fireSelected(Configurable configurable, final ActionCallback callback) { - myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable()); + myFilter.myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable()); } @@ -538,7 +508,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl final List result = new ArrayList(kids.length); for (Configurable child : kids) { result.add(new EditorNode(parent, child, group)); - myContext.registerKid(configurable, child); + myFilter.myContext.registerKid(configurable, child); } return result; // TODO: DECIDE IF INNERS SHOULD BE SORTED: sort(result); } @@ -602,12 +572,12 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl @Override boolean isModified() { - return myContext.getModified().contains(myConfigurable); + return myFilter.myContext.getModified().contains(myConfigurable); } @Override boolean isError() { - return myContext.getErrors().containsKey(myConfigurable); + return myFilter.myContext.getErrors().containsKey(myConfigurable); } } @@ -810,7 +780,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl boolean myWasHoldingFilter; public MyBuilder(SimpleTreeStructure structure) { - super(OptionsTree.this.myTree, myContext.getFilter(), structure, new WeightBasedComparator(false)); + super(myTree, myFilter, structure, new WeightBasedComparator(false)); myTree.addTreeExpansionListener(new TreeExpansionListener() { public void treeExpanded(TreeExpansionEvent event) { invalidateExpansions(); @@ -835,7 +805,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl @Override public boolean isAutoExpandNode(final NodeDescriptor nodeDescriptor) { - return myContext.isHoldingFilter(); + return myFilter.myContext.isHoldingFilter(); } @Override @@ -846,21 +816,21 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl @Override protected ActionCallback refilterNow(Object preferredSelection, boolean adjustSelection) { final List toRestore = new ArrayList(); - if (myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) { + if (myFilter.myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) { myToExpandOnResetFilter = myBuilder.getUi().getExpandedElements(); - } else if (!myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) { + } else if (!myFilter.myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) { toRestore.addAll(myToExpandOnResetFilter); myToExpandOnResetFilter = null; } - myWasHoldingFilter = myContext.isHoldingFilter(); + myWasHoldingFilter = myFilter.myContext.isHoldingFilter(); ActionCallback result = super.refilterNow(preferredSelection, adjustSelection); myRefilteringNow = true; return result.doWhenDone(new Runnable() { public void run() { myRefilteringNow = false; - if (!myContext.isHoldingFilter() && getSelectedElements().isEmpty()) { + if (!myFilter.myContext.isHoldingFilter() && getSelectedElements().isEmpty()) { restoreExpandedState(toRestore); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java new file mode 100644 index 000000000000..1885a852c5da --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java @@ -0,0 +1,211 @@ +/* + * Copyright 2000-2014 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.openapi.options.newEditor; + +import com.intellij.ide.ui.search.ConfigurableHit; +import com.intellij.ide.ui.search.SearchableOptionsRegistrar; +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableGroup; +import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ActionCallback; +import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.LightColors; +import com.intellij.ui.SearchTextField; +import com.intellij.ui.speedSearch.ElementFilter; +import com.intellij.ui.treeStructure.SimpleNode; +import com.intellij.util.ui.UIUtil; + +import javax.swing.event.DocumentEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Set; + +abstract class SettingsFilter extends ElementFilter.Active.Impl { + final OptionsEditorContext myContext = new OptionsEditorContext(this); + final Project myProject; + + boolean myDocumentWasChanged; + + private final SearchTextField mySearch; + private final ConfigurableGroup[] myGroups; + + private SearchableOptionsRegistrar myRegistrar = SearchableOptionsRegistrar.getInstance(); + private Set myFiltered; + private ConfigurableHit myHits; + + private boolean myUpdateRejected; + private Configurable myLastSelected; + + SettingsFilter(Project project, ConfigurableGroup[] groups, SearchTextField search) { + myProject = project; + myGroups = groups; + mySearch = search; + mySearch.addDocumentListener(new DocumentAdapter() { + @Override + protected void textChanged(DocumentEvent event) { + update(event.getType(), true, false); + } + }); + mySearch.getTextEditor().addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent event) { + if (!mySearch.getText().isEmpty()) { + if (!myContext.isHoldingFilter()) { + setHoldingFilter(true); + } + if (!mySearch.getTextEditor().isFocusOwner()) { + mySearch.selectText(); + } + } + } + }); + } + + abstract Configurable getConfigurable(SimpleNode node); + + abstract SimpleNode findNode(Configurable configurable); + + abstract void updateSpotlight(boolean now); + + @Override + public boolean shouldBeShowing(SimpleNode node) { + if (myFiltered != null) { + Configurable configurable = getConfigurable(node); + if (configurable != null) { + if (!myFiltered.contains(configurable)) { + if (myHits != null) { + Set configurables = myHits.getNameFullHits(); + while (node != null) { + if (configurable != null) { + if (configurables.contains(configurable)) { + return true; + } + } + node = node.getParent(); + configurable = getConfigurable(node); + } + } + return false; + } + } + } + return true; + } + + String getFilterText() { + String text = mySearch.getText(); + return text == null ? "" : text.trim(); + } + + void setHoldingFilter(boolean holding) { + myContext.setHoldingFilter(holding); + updateSpotlight(false); + } + + boolean contains(Configurable configurable) { + return myHits != null && myHits.getNameHits().contains(configurable); + } + + ActionCallback update(boolean adjustSelection, boolean now) { + return update(DocumentEvent.EventType.CHANGE, adjustSelection, now); + } + + ActionCallback update(String text, boolean adjustSelection, boolean now) { + try { + myUpdateRejected = true; + mySearch.setText(text); + } + finally { + myUpdateRejected = false; + } + return update(adjustSelection, now); + } + + private ActionCallback update(DocumentEvent.EventType type, boolean adjustSelection, boolean now) { + if (myUpdateRejected) { + return new ActionCallback.Rejected(); + } + String text = getFilterText(); + if (text.isEmpty()) { + myContext.setHoldingFilter(false); + myFiltered = null; + } + else { + myContext.setHoldingFilter(true); + myHits = myRegistrar.getConfigurables(myGroups, type, myFiltered, text, myProject); + myFiltered = myHits.getAll(); + } + mySearch.getTextEditor().setBackground(myFiltered != null && myFiltered.isEmpty() + ? LightColors.RED + : UIUtil.getTextFieldBackground()); + + + Configurable current = myContext.getCurrentConfigurable(); + + boolean shouldMoveSelection = myHits == null || ( + !myHits.getNameFullHits().contains(current) && + !myHits.getContentHits().contains(current)); + + if (shouldMoveSelection && type != DocumentEvent.EventType.INSERT && (myFiltered == null || myFiltered.contains(current))) { + shouldMoveSelection = false; + } + + Configurable candidate = adjustSelection ? current : null; + if (shouldMoveSelection && myHits != null) { + if (!myHits.getNameHits().isEmpty()) { + candidate = findConfigurable(myHits.getNameHits(), myHits.getNameFullHits()); + } + else if (!myHits.getContentHits().isEmpty()) { + candidate = findConfigurable(myHits.getContentHits(), null); + } + } + updateSpotlight(false); + + if ((myFiltered == null || !myFiltered.isEmpty()) && candidate == null && myLastSelected != null) { + candidate = myLastSelected; + myLastSelected = null; + } + if (candidate == null && current != null) { + myLastSelected = current; + } + SimpleNode node = !adjustSelection ? null : findNode(candidate); + ActionCallback callback = fireUpdate(node, adjustSelection, now); + myDocumentWasChanged = true; + return callback; + } + + private static Configurable findConfigurable(Set configurables, Set hits) { + Configurable candidate = null; + for (Configurable configurable : configurables) { + if (hits != null && hits.contains(configurable)) { + return configurable; + } + if (candidate == null && !isEmptyParent(configurable)) { + candidate = configurable; + } + } + return candidate; + } + + private static boolean isEmptyParent(Configurable configurable) { + if (configurable instanceof SearchableConfigurable.Parent) { + SearchableConfigurable.Parent parent = (SearchableConfigurable.Parent)configurable; + return !parent.hasOwnContent(); + } + return false; + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java index 855165d86283..0f4b4f4ea465 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java @@ -16,7 +16,6 @@ package com.intellij.openapi.options.newEditor; import com.intellij.icons.AllIcons; -import com.intellij.ide.ui.search.ConfigurableHit; import com.intellij.ide.util.treeView.NodeDescriptor; import com.intellij.openapi.Disposable; import com.intellij.openapi.options.*; @@ -60,18 +59,19 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd final SimpleTree myTree; final FilteringTreeBuilder myBuilder; - private final OptionsEditorContext myContext; + private final SettingsFilter myFilter; private final MyRoot myRoot; private final JScrollPane myScroller; private JLabel mySeparator; private final MyRenderer myRenderer = new MyRenderer(); private final IdentityHashMap myConfigurableToNodeMap = new IdentityHashMap(); - private final MergingUpdateQueue myQueue = new MergingUpdateQueue("OptionsTree", 150, false, this, this, this).setRestartTimerOnAdd(true); + private final MergingUpdateQueue myQueue = new MergingUpdateQueue("SettingsTreeView", 150, false, this, this, this) + .setRestartTimerOnAdd(true); private Configurable myQueuedConfigurable; - SettingsTreeView(final KeyListener listener, OptionsEditorContext context, ConfigurableGroup... groups) { - myContext = context; + SettingsTreeView(SettingsFilter filter, ConfigurableGroup... groups) { + myFilter = filter; myRoot = new MyRoot(groups); myTree = new MyTree(); @@ -116,29 +116,6 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd } }); - myTree.addKeyListener(new KeyListener() { - public void keyTyped(KeyEvent event) { - if (listener != null && isValid(event)) { - listener.keyTyped(event); - } - } - - public void keyPressed(KeyEvent event) { - if (listener != null && isValid(event)) { - listener.keyPressed(event); - } - } - - public void keyReleased(KeyEvent event) { - if (listener != null && isValid(event)) { - listener.keyReleased(event); - } - } - - private boolean isValid(KeyEvent event) { - return null == myTree.getInputMap().get(KeyStroke.getKeyStrokeForEvent(event)); - } - }); myBuilder = new MyBuilder(new SimpleTreeStructure.Impl(myRoot)); myBuilder.setFilteringMerge(300, null); Disposer.register(this, myBuilder); @@ -158,9 +135,15 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd return ArrayUtil.toStringArray(path); } + static Configurable getConfigurable(SimpleNode node) { + return node instanceof MyNode + ? ((MyNode)node).myConfigurable + : null; + } + @Nullable - SimpleNode findNode(Configurable toSelect) { - return myConfigurableToNodeMap.get(toSelect); + SimpleNode findNode(Configurable configurable) { + return myConfigurableToNodeMap.get(configurable); } @Nullable @@ -250,24 +233,6 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd : null; } - static boolean isFiltered(Set configurables, ConfigurableHit hits, SimpleNode value) { - if (value instanceof MyNode && !configurables.contains(((MyNode)value).myConfigurable)) { - if (hits != null) { - configurables = hits.getNameFullHits(); - while (value != null) { - if (value instanceof MyNode) { - if (configurables.contains(((MyNode)value).myConfigurable)) { - return true; - } - } - value = value.getParent(); - } - } - return false; - } - return true; - } - @Override public void doLayout() { myScroller.setBounds(0, 0, getWidth(), getHeight()); @@ -375,7 +340,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd } private void fireSelected(Configurable configurable, ActionCallback callback) { - myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable()); + myFilter.myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable()); } @Override @@ -463,7 +428,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd for (int i = 0; i < configurables.length; i++) { result[i] = new MyNode(this, configurables[i]); if (myConfigurable != null) { - myContext.registerKid(myConfigurable, configurables[i]); + myFilter.myContext.registerKid(myConfigurable, configurables[i]); } } return result; @@ -553,10 +518,10 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd if (!selected && node != null) { Configurable configurable = node.myConfigurable; if (configurable != null) { - if (myContext.getErrors().containsKey(configurable)) { + if (myFilter.myContext.getErrors().containsKey(configurable)) { myTextLabel.setForeground(JBColor.RED); } - else if (myContext.getModified().contains(configurable)) { + else if (myFilter.myContext.getModified().contains(configurable)) { myTextLabel.setForeground(JBColor.BLUE); } } @@ -608,7 +573,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd } int getSeparatorHeight() { - return mySeparatorComponent.getPreferredSize().height; + return mySeparatorComponent.getParent() == null ? 0 : mySeparatorComponent.getPreferredSize().height; } public boolean isUnderHandle(Point point) { @@ -779,7 +744,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd boolean myWasHoldingFilter; public MyBuilder(SimpleTreeStructure structure) { - super(myTree, myContext.getFilter(), structure, new WeightBasedComparator(false)); + super(myTree, myFilter, structure, new WeightBasedComparator(false)); myTree.addTreeExpansionListener(new TreeExpansionListener() { public void treeExpanded(TreeExpansionEvent event) { invalidateExpansions(); @@ -804,7 +769,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd @Override public boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) { - return myContext.isHoldingFilter(); + return myFilter.myContext.isHoldingFilter(); } @Override @@ -815,22 +780,22 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd @Override protected ActionCallback refilterNow(Object preferredSelection, boolean adjustSelection) { final List toRestore = new ArrayList(); - if (myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) { + if (myFilter.myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) { myToExpandOnResetFilter = myBuilder.getUi().getExpandedElements(); } - else if (!myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) { + else if (!myFilter.myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) { toRestore.addAll(myToExpandOnResetFilter); myToExpandOnResetFilter = null; } - myWasHoldingFilter = myContext.isHoldingFilter(); + myWasHoldingFilter = myFilter.myContext.isHoldingFilter(); ActionCallback result = super.refilterNow(preferredSelection, adjustSelection); myRefilteringNow = true; return result.doWhenDone(new Runnable() { public void run() { myRefilteringNow = false; - if (!myContext.isHoldingFilter() && getSelectedElements().isEmpty()) { + if (!myFilter.myContext.isHoldingFilter() && getSelectedElements().isEmpty()) { restoreExpandedState(toRestore); } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 5f739b2464e9..af18241016d5 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -395,7 +395,6 @@ console.too.much.text.buffer.ratio.description=Used for disabling of console pro The ratio is used against the console cycle buffer size (idea.cycle.buffer.size/theRatio=maxTextLength). ide.new.settings.dialog=false ide.new.settings.dialog.description=New settings dialog -ide.file.settings.tree.new=false ide.new.project.settings=true ide.new.project.settings.description=Temporary key for new project settings dialog UI From c3296e013dfcca07fe9957dbafef2372b293a336 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 20 Aug 2014 19:42:40 +0400 Subject: [PATCH 04/31] Better handling for NavigatableWithText in GotoSource actions --- .../documentation/DocumentationComponent.java | 11 +++-------- .../ide/actions/BaseNavigateToSourceAction.java | 11 ++++------- .../com/intellij/ide/actions/ViewSourceAction.java | 12 ++++++++++++ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index df304aa484e8..791b82a0043f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -634,15 +634,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr private class EditDocumentationSourceAction extends BaseNavigateToSourceAction { - protected EditDocumentationSourceAction() { + EditDocumentationSourceAction() { super(true); - } - - @Override - public void update(AnActionEvent event) { - super.update(event); - event.getPresentation().setIcon(AllIcons.Actions.EditSource); - event.getPresentation().setText("Edit Source"); + getTemplatePresentation().setIcon(AllIcons.Actions.EditSource); + getTemplatePresentation().setText("Edit Source"); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java b/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java index 1c7855d2eedb..f35db7e186f9 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java @@ -49,13 +49,10 @@ public abstract class BaseNavigateToSourceAction extends AnAction implements Dum else { event.getPresentation().setEnabled(enabled); } - if (target != null && target instanceof NavigatableWithText) { - //as myFocusEditor is always ignored - Main Menu|View always contains 2 actions with the same name and actually same behaviour - if (!myFocusEditor) { - event.getPresentation().setVisible(false); - return; - } - final String navigateActionText = ((NavigatableWithText)target).getNavigateActionText(myFocusEditor); + //as myFocusEditor is always ignored - Main Menu|View always contains 2 actions with the same name and actually same behaviour + event.getPresentation().setVisible(target == null || myFocusEditor); + if (myFocusEditor && target instanceof NavigatableWithText) { + String navigateActionText = ((NavigatableWithText)target).getNavigateActionText(true); if (navigateActionText != null) { event.getPresentation().setText(navigateActionText); } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java index a9461422f747..825db992b218 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java @@ -17,9 +17,21 @@ package com.intellij.ide.actions; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; public class ViewSourceAction extends BaseNavigateToSourceAction { public ViewSourceAction() { super(false); } + + @Override + public void update(AnActionEvent e) { + if (CommonDataKeys.EDITOR.getData(e.getDataContext()) != null) { + e.getPresentation().setEnabledAndVisible(false); + } + else { + super.update(e); + } + } } From b5a2b1f4f1abc01b5a3e9838236bc48ca5abbb56 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 20 Aug 2014 20:21:56 +0400 Subject: [PATCH 05/31] FilteringIterator: improve generics --- .../com/intellij/openapi/util/Conditions.java | 8 ++++++++ .../intellij/util/containers/ContainerUtil.java | 3 ++- .../util/containers/FilteringIterator.java | 17 ++++------------- .../util/containers/InternalIterator.java | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/platform/util-rt/src/com/intellij/openapi/util/Conditions.java b/platform/util-rt/src/com/intellij/openapi/util/Conditions.java index 791a5a9756dd..633802d3408b 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/Conditions.java +++ b/platform/util-rt/src/com/intellij/openapi/util/Conditions.java @@ -34,6 +34,14 @@ public class Conditions { return (Condition)FALSE; } + public static Condition instanceOf(final Class clazz) { + return new Condition() { + public boolean value(T t) { + return clazz.isInstance(t); + } + }; + } + public static Condition is(final T option) { return new Condition() { public boolean value(T t) { diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index dca7a0e6b30d..f4e9981ad219 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -1073,7 +1073,8 @@ public class ContainerUtil extends ContainerUtilRt { } public static U findInstance(@NotNull Iterator iterator, @NotNull Class aClass) { - @SuppressWarnings("unchecked") U u = (U)find(iterator, new FilteringIterator.InstanceOf(aClass)); + //noinspection unchecked + U u = (U)find(iterator, FilteringIterator.instanceOf(aClass)); return u; } diff --git a/platform/util/src/com/intellij/util/containers/FilteringIterator.java b/platform/util/src/com/intellij/util/containers/FilteringIterator.java index c6b7173b4db2..3e146441d6ab 100644 --- a/platform/util/src/com/intellij/util/containers/FilteringIterator.java +++ b/platform/util/src/com/intellij/util/containers/FilteringIterator.java @@ -17,7 +17,6 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Conditions; -import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -30,7 +29,7 @@ import java.util.NoSuchElementException; */ public class FilteringIterator implements Iterator { private final Iterator myBaseIterator; - private final Condition myFilter; + private final Condition myFilter; private boolean myNextObtained = false; private boolean myCurrentIsValid = false; private Dom myCurrent; @@ -42,7 +41,7 @@ public class FilteringIterator implements Iterator { } }; - public FilteringIterator(@NotNull Iterator baseIterator, @NotNull Condition filter) { + public FilteringIterator(@NotNull Iterator baseIterator, @NotNull Condition filter) { myBaseIterator = baseIterator; myFilter = filter; } @@ -103,7 +102,7 @@ public class FilteringIterator implements Iterator { return create(iterator, NOT_NULL); } - public static Iterator create(Iterator iterator, Condition condition) { + public static Iterator create(Iterator iterator, Condition condition) { return new FilteringIterator(iterator, condition); } @@ -119,7 +118,7 @@ public class FilteringIterator implements Iterator { return create((Iterator)iterator, instanceOf(aClass)); } - public static class InstanceOf implements Condition { + public static class InstanceOf implements Condition { private final Class myInstancesClass; public InstanceOf(Class instancesClass) { @@ -130,13 +129,5 @@ public class FilteringIterator implements Iterator { public boolean value(Object object) { return myInstancesClass.isInstance(object); } - - public boolean isClassAcceptable(Class hintClass) { - return ReflectionUtil.isAssignable(myInstancesClass, hintClass); - } - - public T cast(Object object) { - return (T)object; - } } } diff --git a/platform/util/src/com/intellij/util/containers/InternalIterator.java b/platform/util/src/com/intellij/util/containers/InternalIterator.java index 9b7d1da8f156..49c84ece6a48 100644 --- a/platform/util/src/com/intellij/util/containers/InternalIterator.java +++ b/platform/util/src/com/intellij/util/containers/InternalIterator.java @@ -70,10 +70,10 @@ public interface InternalIterator{ } class Filtering implements InternalIterator { - private final Condition myFilter; + private final Condition myFilter; private final InternalIterator myIterator; - public Filtering(InternalIterator iterator, Condition filter) { + public Filtering(InternalIterator iterator, Condition filter) { myIterator = iterator; myFilter = filter; } From 36d70ee8c5c7b886c1b973ceb49c0a9f6c3a0ca7 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 20 Aug 2014 21:12:09 +0400 Subject: [PATCH 06/31] Crush on OSX: Assertion failed: (winRgnBounds.size.width <= 1000000), function CGSNewWindowWithOpaqueShape, file Services/Windows/CGSWindow.c, line 592. --- .../src/com/intellij/ui/AbstractExpandableItemsHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java index 1fc23e5f4055..d9ebeefa7acc 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java @@ -368,6 +368,7 @@ public abstract class AbstractExpandableItemsHandler Date: Wed, 20 Aug 2014 21:18:04 +0400 Subject: [PATCH 07/31] IDEA-128606 (use standard event processing until app components are loaded) --- .../src/com/intellij/ide/IdeEventQueue.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index a7d07c9fa1e8..d9d147a4dac0 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -344,8 +344,21 @@ public class IdeEventQueue extends EventQueue { } } + private static boolean ourAppIsLoaded = false; + + private static boolean appIsLoaded() { + if (ourAppIsLoaded) return true; + boolean loaded = IdeaApplication.isLoaded(); + if (loaded) ourAppIsLoaded = true; + return loaded; + } + @Override public void dispatchEvent(AWTEvent e) { + if (!appIsLoaded()) { + super.dispatchEvent(e); + return; + } fixNonEnglishKeyboardLayouts(e); @@ -760,7 +773,7 @@ public class IdeEventQueue extends EventQueue { } private static boolean typeAheadDispatchToFocusManager(AWTEvent e) { - if (e instanceof KeyEvent && appIsLoaded()) { + if (e instanceof KeyEvent) { final KeyEvent event = (KeyEvent)e; if (!event.isConsumed()) { final IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(event.getComponent()); @@ -771,15 +784,6 @@ public class IdeEventQueue extends EventQueue { return false; } - private static boolean ourAppIsLoaded = false; - - private static boolean appIsLoaded() { - if (ourAppIsLoaded) return true; - boolean loaded = IdeaApplication.isLoaded(); - if (loaded) ourAppIsLoaded = true; - return loaded; - } - public void flushQueue() { while (true) { AWTEvent event = peekEvent(); From f8c52f43ca2de45161275a064be6fa21645bc469 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 20 Aug 2014 21:18:19 +0400 Subject: [PATCH 08/31] provide proper highlighting for extracted elements #WEB-13079 fixed --- .../lang/xml/XmlEnclosingTagUnwrapper.java | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/xml/impl/src/com/intellij/lang/xml/XmlEnclosingTagUnwrapper.java b/xml/impl/src/com/intellij/lang/xml/XmlEnclosingTagUnwrapper.java index b40ca4b64f60..400c822241bf 100644 --- a/xml/impl/src/com/intellij/lang/xml/XmlEnclosingTagUnwrapper.java +++ b/xml/impl/src/com/intellij/lang/xml/XmlEnclosingTagUnwrapper.java @@ -16,18 +16,19 @@ package com.intellij.lang.xml; import com.intellij.codeInsight.unwrap.Unwrapper; -import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.XmlChildRole; -import com.intellij.psi.xml.XmlTag; -import com.intellij.xml.XmlBundle; +import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; +import com.intellij.psi.xml.XmlChildRole; +import com.intellij.psi.xml.XmlTag; import com.intellij.util.IncorrectOperationException; -import com.intellij.lang.ASTNode; +import com.intellij.xml.XmlBundle; -import java.util.Set; +import java.util.ArrayList; import java.util.List; -import java.util.Collections; +import java.util.Set; public class XmlEnclosingTagUnwrapper implements Unwrapper { @Override @@ -45,23 +46,34 @@ public class XmlEnclosingTagUnwrapper implements Unwrapper { } @Override - public PsiElement collectAffectedElements(PsiElement e, List toExtract) { - return e; - } - - @Override - public List unwrap(Editor editor, PsiElement element) throws IncorrectOperationException { + public PsiElement collectAffectedElements(PsiElement element, List toExtract) { final TextRange range = element.getTextRange(); final ASTNode startTagNameEnd = XmlChildRole.START_TAG_END_FINDER.findChild(element.getNode()); final ASTNode endTagNameStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(element.getNode()); - if (endTagNameStart != null) { - editor.getDocument().replaceString(endTagNameStart.getTextRange().getStartOffset(), range.getEndOffset(), ""); - editor.getDocument().replaceString(range.getStartOffset(), startTagNameEnd.getTextRange().getEndOffset(), ""); + int start = startTagNameEnd != null ? startTagNameEnd.getTextRange().getEndOffset() : range.getStartOffset(); + int end = endTagNameStart != null ? endTagNameStart.getTextRange().getStartOffset() : range.getEndOffset(); + + for (PsiElement child : element.getChildren()) { + final TextRange childRange = child.getTextRange(); + if (childRange.getStartOffset() >= start && childRange.getEndOffset() <= end) { + toExtract.add(child); + } } - else { - editor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), ""); + return element; + } + + @Override + public List unwrap(Editor editor, PsiElement element) throws IncorrectOperationException { + final ArrayList toExtract = new ArrayList(); + collectAffectedElements(element, toExtract); + for (int i = 0; i < toExtract.size(); i++) { + PsiElement psiElement = toExtract.get(i); + psiElement = element.getParent().addBefore(psiElement, element); + CodeEditUtil.markToReformat(psiElement.getNode(), true); + toExtract.set(i, psiElement); } - return Collections.emptyList(); + element.delete(); + return toExtract; } } From ba6a24ef3282690a24a850537ca92fa0add45fbd Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 20 Aug 2014 21:34:57 +0400 Subject: [PATCH 09/31] IDEA-128517 (possible race condition on app shutdown) --- .../src/com/intellij/ui/LibNotifyWrapper.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java index e8c6f49f8088..7e613982a406 100644 --- a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java +++ b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java @@ -50,6 +50,8 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier { private final LibNotify myLibNotify; private final String myIcon; + private final Object myLock = new Object(); + private boolean myDisposed = false; private LibNotifyWrapper() { myLibNotify = (LibNotify)Native.loadLibrary("libnotify.so.4", LibNotify.class); @@ -66,14 +68,21 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier { connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() { @Override public void appClosing() { - myLibNotify.notify_uninit(); + synchronized (myLock) { + myDisposed = true; + myLibNotify.notify_uninit(); + } } }); } @Override public void notify(@NotNull Set allNames, @NotNull String name, @NotNull String title, @NotNull String description) { - Pointer notification = myLibNotify.notify_notification_new(title, description, myIcon); - myLibNotify.notify_notification_show(notification, null); + synchronized (myLock) { + if (!myDisposed) { + Pointer notification = myLibNotify.notify_notification_new(title, description, myIcon); + myLibNotify.notify_notification_show(notification, null); + } + } } } From c453ffe01550228560cc43154b7eaf45721f91bd Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Wed, 20 Aug 2014 22:19:47 +0400 Subject: [PATCH 10/31] renamed win installation for PyCharm Edu. PE -> EDU. --- python/edu/build/pycharm_edu_build.gant | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index 3422707bd5fb..0f6cad50cc52 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -199,12 +199,12 @@ public layoutEducational(String classesPath, Set usedJars) { buildNSIS([paths.distAll, paths.distWin], "$pythonEduHome/build/strings.nsi", "$pythonEduHome/build/paths.nsi", - "pycharmPE-", false, true, ".py", system_selector) + "pycharmEDU-", false, true, ".py", system_selector) String tarRoot = isEap() ? "pycharm-pe-$buildNumber" : "pycharm-pe-${p("component.version.major")}.${p("component.version.minor")}" buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix]) - String macAppRoot = isEap() ? "PyCharm PE ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm PE.app/Contents" + String macAppRoot = isEap() ? "PyCharm EDU ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm EDU.app/Contents" buildMacZip(macAppRoot, "${paths.artifacts}/pycharm${buildName}.sit", [paths.distAll], paths.distMac) ant.copy(file: "${paths.artifacts}/pycharm${buildName}.sit", tofile: "${paths.artifacts}/pycharm${buildName}-jdk-bundled.sit") ant.delete(file: "${paths.artifacts}/pycharm${buildName}.sit") From 4fe03a79dde99988eda41ce3c9bac10cb71978b5 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Wed, 20 Aug 2014 22:21:33 +0400 Subject: [PATCH 11/31] renamed win installation for PyCharm Edu. PE -> EDU. --- python/edu/build/pycharm_edu_build.gant | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index 0f6cad50cc52..b593e62f6000 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -22,7 +22,7 @@ includeTargets << new File("$home/community/build/scripts/libLicenses.gant") includeTargets << new File("$home/build/scripts/ultimate_utils.gant") requireProperty("buildNumber", requireProperty("build.number", snapshot)) -setProperty("buildName", "PE-$buildNumber") +setProperty("buildName", "EDU-$buildNumber") setProperty("ch", "$home/community") setProperty("pythonCommunityHome", "$ch/python") setProperty("pythonEduHome", "$ch/python/edu") @@ -92,7 +92,7 @@ class Paths { } setProperty("paths", new Paths(home)) -setProperty("buildName", "PE-$buildNumber") +setProperty("buildName", "EDU-$buildNumber") target('default': "Build artifacts") { @@ -146,7 +146,7 @@ target('default': "Build artifacts") { layoutEducational("${paths.sandbox}/classes/production", usedJars) - def extraArgs = ["build.code": "pycharm${buildName}", "build.number": "PE-$buildNumber", "artifacts.path": "${paths.artifacts}"] + def extraArgs = ["build.code": "pycharm${buildName}", "build.number": ${buildName}, "artifacts.path": "${paths.artifacts}"] signMacZip("pycharm", extraArgs + ["sitFileName": "pycharm${buildName}-jdk-bundled", "jdk_archive_name": "jdk_mac_redist_for_${buildNumber}.tar"]) buildDmg("pycharm", "${pythonEduHome}/build/DMG_background.png", extraArgs + ["sitFileName": "pycharm${buildName}-jdk-bundled", "jdk_archive_name": "jdk_mac_redist_for_${buildNumber}.tar"]) @@ -168,11 +168,11 @@ public layoutEducational(String classesPath, Set usedJars) { }, "-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true") if (!dryRun) { - wireBuildDate("PE-${buildNumber}", appInfo) + wireBuildDate("EDU-${buildNumber}", appInfo) } Map args = [ - buildNumber: "PE-${buildNumber}", + buildNumber: "EDU-${buildNumber}", system_selector: system_selector, ide_jvm_args: "-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true"] @@ -183,7 +183,7 @@ public layoutEducational(String classesPath, Set usedJars) { layoutUnix(args, paths.distUnix) layoutMac(args, paths.distMac) - ant.echo(message: "PE-${buildNumber}", file: "${paths.distAll}/build.txt") + ant.echo(message: "EDU-${buildNumber}", file: "${paths.distAll}/build.txt") def launcher = "${paths.distWin}/bin/pycharm.exe" List resourcePaths = ["$ch/community-resources/src", @@ -201,7 +201,7 @@ public layoutEducational(String classesPath, Set usedJars) { "$pythonEduHome/build/strings.nsi", "$pythonEduHome/build/paths.nsi", "pycharmEDU-", false, true, ".py", system_selector) - String tarRoot = isEap() ? "pycharm-pe-$buildNumber" : "pycharm-pe-${p("component.version.major")}.${p("component.version.minor")}" + String tarRoot = isEap() ? "pycharm-edu-$buildNumber" : "pycharm-edu-${p("component.version.major")}.${p("component.version.minor")}" buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix]) String macAppRoot = isEap() ? "PyCharm EDU ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm EDU.app/Contents" From 37fde57f1101b809519251e4a232cb6dc105e459 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Wed, 20 Aug 2014 22:34:37 +0400 Subject: [PATCH 12/31] renamed win installation for PyCharm Edu. PE -> EDU. --- python/edu/build/pycharm_edu_build.gant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index bdddfbe90e9b..81a7faca8606 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -198,7 +198,7 @@ public layoutEducational(String classesPath, Set usedJars) { buildNSIS([paths.distAll, paths.distWin], "$pythonEduHome/build/strings.nsi", "$pythonEduHome/build/paths.nsi", - "pycharmPE-", false, true, ".py", system_selector) + "pycharmEDU-", false, true, ".py", system_selector) String tarRoot = isEap() ? "pycharm-edu-$buildNumber" : "pycharm-edu-${p("component.version.major")}.${p("component.version.minor")}" buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix]) From f2f2c49c653ff1e63e7e2a969a6baffbbfe43747 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 20 Aug 2014 21:47:40 +0400 Subject: [PATCH 13/31] use concurrent interner --- .../configuration/RunConfigurationExtensionsManager.java | 3 ++- platform/util/src/com/intellij/openapi/util/JDOMUtil.java | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java b/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java index c52f6c9da729..b42cd249ca8e 100644 --- a/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java +++ b/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java @@ -16,6 +16,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.StringInterner; +import com.intellij.util.containers.WeakStringInterner; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,7 +34,7 @@ public class RunConfigurationExtensionsManager myExtensionPointName; - private final StringInterner myInterner = new StringInterner(); + private final StringInterner myInterner = new WeakStringInterner(); public RunConfigurationExtensionsManager(ExtensionPointName extensionPointName) { myExtensionPointName = extensionPointName; diff --git a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java index 2cd5ed09bfdc..d877558e8961 100644 --- a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java +++ b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java @@ -204,9 +204,7 @@ public class JDOMUtil { @NotNull private static String intern(@NotNull final StringInterner interner, @NotNull final String s) { - synchronized (interner) { - return interner.intern(s); - } + return interner.intern(s); } @NotNull From c9fc173579b45b5de22caac8b9e318980868e753 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 20 Aug 2014 22:44:16 +0400 Subject: [PATCH 14/31] hectic focus transfers on project loading handling --- .../masterKey/MasterKeyPasswordSafe.java | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java index 6b0b9814698b..2f7406af196b 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java @@ -15,6 +15,8 @@ */ package com.intellij.ide.passwordSafe.impl.providers.masterKey; +import com.intellij.concurrency.AsyncFutureFactory; +import com.intellij.concurrency.AsyncFutureResult; import com.intellij.ide.passwordSafe.MasterPasswordUnavailableException; import com.intellij.ide.passwordSafe.PasswordSafeException; import com.intellij.ide.passwordSafe.impl.PasswordSafeTimed; @@ -23,14 +25,11 @@ import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper; import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil; import com.intellij.ide.passwordSafe.impl.providers.masterKey.windows.WindowsCryptUtils; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,6 +37,7 @@ import org.jetbrains.annotations.Nullable; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ExecutionException; /** * The password safe that stores information in configuration file encrypted by master password @@ -200,35 +200,41 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } private static final Object ourEDTLock = new Object(); - public T invokeAndWait(@NotNull final ThrowableComputable computable, @NotNull final Condition expired) throws E { + public T invokeAndWait(@NotNull final ThrowableComputable computable, @NotNull final Condition expired) throws E { if (ApplicationManager.getApplication().isDispatchThread()) { return computable.compute(); } - final Ref exRef = Ref.create(); - final Ref ref = Ref.create(); + + final AsyncFutureResult future = AsyncFutureFactory.getInstance().createAsyncFutureResult(); synchronized (ourEDTLock) { - if (expired.value(null)) { - throw new ProcessCanceledException(); - } - ApplicationManager.getApplication().invokeAndWait(new Runnable() { + IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(new ExpirableRunnable() { + @Override + public boolean isExpired() { + boolean b = expired.value(null); + if (b) future.setException(new ProcessCanceledException()); + return b; + } + @Override public void run() { - if (expired.value(null)) { - exRef.set(new ProcessCanceledException()); - return; - } - try { - ref.set(computable.compute()); + future.set(computable.compute()); } catch (Throwable e) { - exRef.set(e); + future.setException(e); } } - }, ModalityState.any()); + }); + } + try { + return (T)future.get(); + } + catch (InterruptedException e) { + throw new ProcessCanceledException(e); + } + catch (ExecutionException e) { + throw (E) e.getCause(); } - if (!exRef.isNull()) throw (E)exRef.get(); - return ref.get(); } @Override From 62fc009129eeb2d77dd5845ea211715281d74372 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 20 Aug 2014 22:44:31 +0400 Subject: [PATCH 15/31] cleanup --- .../com/intellij/openapi/util/JDOMUtil.java | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java index d877558e8961..6ff354015918 100644 --- a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java +++ b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java @@ -209,27 +209,23 @@ public class JDOMUtil { @NotNull public static String legalizeText(@NotNull final String str) { - StringReader reader = new StringReader(str); - StringBuilder result = new StringBuilder(); - - while(true) { - try { - int each = reader.read(); - if (each == -1) break; - - if (Verifier.isXMLCharacter(each)) { - result.append((char)each); - } else { - result.append("0x").append(StringUtil.toUpperCase(Long.toHexString(each))); - } - } - catch (IOException ignored) { - } + StringBuilder result = new StringBuilder(str.length()); + for (int i = 0, len = str.length(); i < len; i ++) { + result.append(str.charAt(i)); + legalizeChar(result, result.length() - 1); } - - return result.toString().replaceAll("<", "<").replaceAll(">", ">"); + return result.toString(); } + public static void legalizeChar(@NotNull StringBuilder sb, int pos) { + char each = sb.charAt(pos); + if (each == '<' || each == '>') { + sb.replace(pos, pos + 1, each == '<' ? "<" : ">"); + } + else if (!Verifier.isXMLCharacter(each)) { + sb.replace(pos, pos + 1, "0x").insert(pos + 2, StringUtil.toUpperCase(Long.toHexString(each))); + } + } private static class EmptyTextFilter implements Filter { @Override From 743215e5460c4abbb55b0e2e3ec9d88e1561edaf Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 20 Aug 2014 23:26:09 +0400 Subject: [PATCH 16/31] cleanup --- .../actions/BaseNavigateToSourceAction.java | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java b/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java index f35db7e186f9..3e644468f282 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java @@ -17,9 +17,12 @@ package com.intellij.ide.actions; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.Navigatable; import com.intellij.pom.NavigatableWithText; +import com.intellij.pom.PomTargetPsiElement; import com.intellij.util.OpenSourceUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class BaseNavigateToSourceAction extends AnAction implements DumbAware { @@ -37,7 +40,7 @@ public abstract class BaseNavigateToSourceAction extends AnAction implements Dum public void update(AnActionEvent event) { DataContext dataContext = event.getDataContext(); - final Navigatable target = getTarget(dataContext); + final Navigatable target = findTargetForUpdate(dataContext); boolean enabled = target != null; if (ActionPlaces.isPopupPlace(event.getPlace())) { event.getPresentation().setVisible(enabled); @@ -51,31 +54,19 @@ public abstract class BaseNavigateToSourceAction extends AnAction implements Dum } //as myFocusEditor is always ignored - Main Menu|View always contains 2 actions with the same name and actually same behaviour event.getPresentation().setVisible(target == null || myFocusEditor); - if (myFocusEditor && target instanceof NavigatableWithText) { - String navigateActionText = ((NavigatableWithText)target).getNavigateActionText(true); - if (navigateActionText != null) { - event.getPresentation().setText(navigateActionText); - } - else { - event.getPresentation().setText(getTemplatePresentation().getText()); - } - } - else { - event.getPresentation().setText(getTemplatePresentation().getText()); - } + String navigateActionText = myFocusEditor && target instanceof NavigatableWithText? + ((NavigatableWithText)target).getNavigateActionText(true) : null; + event.getPresentation().setText(StringUtil.notNullize(navigateActionText, getTemplatePresentation().getText())); } @Nullable - private Navigatable getTarget(final DataContext dataContext) { - if (!myFocusEditor && CommonDataKeys.EDITOR.getData(dataContext) != null) { - // makes no sense in editor and conflicts with another action there (ctrl+enter) - return null; - } - + private Navigatable findTargetForUpdate(@NotNull DataContext dataContext) { Navigatable[] navigatables = getNavigatables(dataContext); - if (navigatables != null) { - for (Navigatable navigatable : navigatables) { - if (navigatable.canNavigate()) return navigatable; + if (navigatables == null) return null; + + for (Navigatable navigatable : navigatables) { + if (navigatable.canNavigate()) { + return navigatable instanceof PomTargetPsiElement ? ((PomTargetPsiElement)navigatable).getTarget() : navigatable; } } return null; From 577459f18eab1a68021314df0230d052ae80546b Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 21 Aug 2014 01:17:58 +0400 Subject: [PATCH 17/31] EA-59487 - IAE: ObjectUtils._assertNotNull --- .../intellij/codeInsight/intention/impl/QuickEditHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java index 2c5d8642e46d..517f23c5a198 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java @@ -360,7 +360,7 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable { private void commitToOriginal() { if (!isValid()) return; - VirtualFile origVirtualFile = PsiUtilCore.getVirtualFile(ObjectUtils.assertNotNull(myNewFile.getContext())); + VirtualFile origVirtualFile = PsiUtilCore.getVirtualFile(myNewFile.getContext()); myCommittingToOriginal = true; try { if (origVirtualFile == null || !ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(origVirtualFile).hasReadonlyFiles()) { From eb9ae8c081b0520ddf0bc70a81c812dca4a48f35 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 21 Aug 2014 01:42:59 +0400 Subject: [PATCH 18/31] EditFragment: check document when searching for existing handler --- .../intention/impl/QuickEditAction.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java index 62e3bcba3a22..d168002f97a7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java @@ -30,11 +30,15 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.*; +import com.intellij.psi.ElementManipulators; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.impl.source.tree.injected.Place; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -93,14 +97,17 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction { } public QuickEditHandler invokeImpl(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException { - final int offset = editor.getCaretModel().getOffset(); - final Pair pair = getRangePair(file, editor); - assert pair != null; - final PsiFile injectedFile = (PsiFile)pair.first; - final int injectedOffset = ((DocumentWindow)PsiDocumentManager.getInstance(project).getDocument(injectedFile)).hostToInjected(offset); + int offset = editor.getCaretModel().getOffset(); + Pair pair = ObjectUtils.assertNotNull(getRangePair(file, editor)); + + PsiFile injectedFile = (PsiFile)pair.first; QuickEditHandler handler = getHandler(project, injectedFile, editor, file); + if (!ApplicationManager.getApplication().isUnitTestMode()) { - handler.navigate(injectedOffset); + DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injectedFile); + if (documentWindow != null) { + handler.navigate(documentWindow.hostToInjected(offset)); + } } return handler; } @@ -124,12 +131,15 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction { return handler; } - public static QuickEditHandler getExistingHandler(PsiFile injectedFile) { + public static QuickEditHandler getExistingHandler(@NotNull PsiFile injectedFile) { Place shreds = InjectedLanguageUtil.getShreds(injectedFile); - if (shreds == null) return null; + DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injectedFile); + if (shreds == null || documentWindow == null) return null; + TextRange hostRange = TextRange.create(shreds.get(0).getHostRangeMarker().getStartOffset(), shreds.get(shreds.size() - 1).getHostRangeMarker().getEndOffset()); for (Editor editor : EditorFactory.getInstance().getAllEditors()) { + if (editor.getDocument() != documentWindow.getDelegate()) continue; QuickEditHandler handler = editor.getUserData(QUICK_EDIT_HANDLER); if (handler != null && handler.changesRange(hostRange)) return handler; } From e09e288c814285c12130b97cbb0780ff5e7c6da0 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 21 Aug 2014 00:09:56 +0200 Subject: [PATCH 19/31] support arrays --- .../evaluate/XDebuggerEditorLinePainter.java | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java index d15180a2c3b4..ec5c50db6e9d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java @@ -33,6 +33,7 @@ import org.jetbrains.annotations.NotNull; import java.awt.*; import java.util.*; +import java.util.List; /** * @author Konstantin Bulenkov @@ -69,7 +70,7 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter { } catch (Exception e) { continue; } - final Color color = new JBColor(new Color(61, 128, 101), new Color(61, 128, 101)); + final Color color = getForeground(); final String name = value.getName(); result.add(new LineExtensionInfo(" " + name + ": ", color, null, null, Font.PLAIN)); @@ -90,9 +91,7 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter { result.add(new LineExtensionInfo(s, color, null, null, Font.PLAIN)); } } else { - for (String s : text.getTexts()) { - result.add(new LineExtensionInfo(s, new JBColor(new Color(202, 128, 33), new Color(116, 114, 4)), null, null, Font.BOLD)); - } + variableValue.produceChangedParts(result); } } return result; @@ -102,6 +101,14 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter { return null; } + public static JBColor getForeground() { + return new JBColor(new Color(61, 128, 101), new Color(61, 128, 101)); + } + + public static JBColor getChangedForeground() { + return new JBColor(new Color(202, 128, 33), new Color(161, 131, 10)); + } + static class Variable { private int lineNumber; private String name; @@ -146,5 +153,35 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter { public boolean isChanged() { return old != null && !StringUtil.equals(actual, old); } + + public void produceChangedParts(List result) { + if (isArray(actual) && isArray(old)) { + List actualParts = getArrayParts(actual); + List oldParts = getArrayParts(old); + result.add(new LineExtensionInfo("{", getForeground(), null, null, Font.PLAIN)); + for (int i = 0; i < actualParts.size(); i++) { + if (i < oldParts.size() && StringUtil.equals(actualParts.get(i), oldParts.get(i))) { + result.add(new LineExtensionInfo(actualParts.get(i), getForeground(), null, null, Font.PLAIN)); + } else { + result.add(new LineExtensionInfo(actualParts.get(i), getChangedForeground(), null, null, Font.BOLD)); + } + if (i != actualParts.size() - 1) { + result.add(new LineExtensionInfo(", ", getForeground(), null, null, Font.PLAIN)); + } + } + result.add(new LineExtensionInfo("}", getForeground(), null, null, Font.PLAIN)); + return; + } + + result.add(new LineExtensionInfo(actual, getChangedForeground(), null, null, Font.BOLD)); + } + + private static boolean isArray(String s) { + return s != null && s.startsWith("{") && s.endsWith("}"); + } + + private static List getArrayParts(String array) { + return StringUtil.split(array.substring(1, array.length() - 1), ", "); + } } } From 88a1958b84427e5e4c941397c1f8fbe80118067b Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 21 Aug 2014 10:26:32 +0400 Subject: [PATCH 20/31] EA-53787 - fix tabulation processing for non-monospace fonts tabulation width is always calculated in terms of plain-font space now --- .../editor/colors/FontPreferences.java | 7 +++- .../openapi/editor/ex/util/EditorUtil.java | 26 ++++++------- .../openapi/editor/impl/EditorImpl.java | 35 +++++++++--------- .../mapping/SoftWrapApplianceManager.java | 37 ++++++++++--------- 4 files changed, 57 insertions(+), 48 deletions(-) diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/FontPreferences.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/FontPreferences.java index 557d41435878..5d2038d171ea 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/FontPreferences.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/FontPreferences.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -226,4 +226,9 @@ public class FontPreferences { } return null; } + + @Override + public String toString() { + return "Effective font families: " + myEffectiveFontFamilies; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index 216429557cea..7d9973fed2d3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -407,7 +407,7 @@ public final class EditorUtil { IterationState state = new IterationState(editorImpl, start, end, false); int fontType = state.getMergedAttributes().getFontType(); int column = currentColumn[0]; - int spaceSize = getSpaceWidth(fontType, editorImpl); + int plainSpaceSize = getSpaceWidth(Font.PLAIN, editorImpl); for (; column < columnNumber && offset < end; offset++) { if (offset >= state.getEndOffset()) { state.advance(); @@ -417,7 +417,7 @@ public final class EditorUtil { char c = text.charAt(offset); if (c == '\t') { final int newX = nextTabStop(x, editorImpl); - final int columns = columnsNumber(newX - x, spaceSize); + final int columns = columnsNumber(newX - x, plainSpaceSize); if (debugBuffer != null) { debugBuffer.append(String.format( "Processing tabulation at the offset %d. Current X: %d, new X: %d, current column: %d, new column: %d%n", @@ -556,11 +556,11 @@ public final class EditorUtil { return nextTabStop(x, getSpaceWidth(Font.PLAIN, editor), tabSize); } - public static int nextTabStop(int x, int spaceWidth, int tabSize) { + public static int nextTabStop(int x, int plainSpaceWidth, int tabSize) { if (tabSize <= 0) { - return x + spaceWidth; + return x + plainSpaceWidth; } - tabSize *= spaceWidth; + tabSize *= plainSpaceWidth; int nTabs = x / tabSize; return (nTabs + 1) * tabSize; @@ -617,15 +617,15 @@ public final class EditorUtil { * @param c target char * @param x 'x' coordinate of the line where given char is represented that indicates char end location * @param prevX 'x' coordinate of the line where given char is represented that indicates char start location - * @param spaceSize 'space' symbol width + * @param plainSpaceSize 'space' symbol width (in plain font style) * @return number of columns necessary for representation of the given char on a screen. */ - public static int columnsNumber(char c, int x, int prevX, int spaceSize) { + public static int columnsNumber(char c, int x, int prevX, int plainSpaceSize) { if (c != '\t') { return 1; } - int result = (x - prevX) / spaceSize; - if ((x - prevX) % spaceSize > 0) { + int result = (x - prevX) / plainSpaceSize; + if ((x - prevX) % plainSpaceSize > 0) { result++; } return result; @@ -635,12 +635,12 @@ public final class EditorUtil { * Allows to answer how many visual columns are occupied by the given width. * * @param width target width - * @param spaceSize width of the single space symbol within the target editor + * @param plainSpaceSize width of the single space symbol within the target editor (in plain font style) * @return number of visual columns are occupied by the given width */ - public static int columnsNumber(int width, int spaceSize) { - int result = width / spaceSize; - if (width % spaceSize > 0) { + public static int columnsNumber(int width, int plainSpaceSize) { + int result = width / plainSpaceSize; + if (width % plainSpaceSize > 0) { result++; } return result; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 6160ea58dcdf..81d1f1190702 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -1153,8 +1153,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int textLength = myDocument.getTextLength(); LogicalPosition logicalPosition = visualToLogicalPosition(new VisualPosition(line, 0)); int offset = logicalPositionToOffset(logicalPosition); + int plainSpaceSize = EditorUtil.getSpaceWidth(Font.PLAIN, this); - if (offset >= textLength) return new VisualPosition(line, EditorUtil.columnsNumber(p.x, EditorUtil.getSpaceWidth(Font.PLAIN, this))); + if (offset >= textLength) return new VisualPosition(line, EditorUtil.columnsNumber(p.x, plainSpaceSize)); // There is a possible case that starting logical line is split by soft-wraps and it's part after the split should be drawn. // We mark that we're under such circumstances then. @@ -1172,12 +1173,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi + "to offset %d (end offset). State: %s", p, line, line, 0, logicalPosition, offset, line + 1, 0, endLogicalPosition, endOffset, dumpState() )); - return new VisualPosition(line, EditorUtil.columnsNumber(p.x, EditorUtil.getSpaceWidth(Font.PLAIN, this))); + return new VisualPosition(line, EditorUtil.columnsNumber(p.x, plainSpaceSize)); } IterationState state = new IterationState(this, offset, endOffset, false); int fontType = state.getMergedAttributes().getFontType(); - int spaceSize = EditorUtil.getSpaceWidth(fontType, this); int x = 0; int charWidth; @@ -1221,7 +1221,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (x >= px) { break outer; } - column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); + column += EditorUtil.columnsNumber(c, x, prevX, plainSpaceSize); } // Process 'after soft wrap' sign. @@ -1261,7 +1261,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (x >= px) { break; } - column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); + column += EditorUtil.columnsNumber(c, x, prevX, plainSpaceSize); offset++; } @@ -1272,16 +1272,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } if (charWidth < 0) { - charWidth = spaceSize; + charWidth = plainSpaceSize; } if (x >= px && c == '\t' && !onSoftWrapDrawing) { if (mySettings.isCaretInsideTabs()) { - column += (px - prevX) / spaceSize; - if ((px - prevX) % spaceSize > spaceSize / 2) column++; + column += (px - prevX) / plainSpaceSize; + if ((px - prevX) % plainSpaceSize > plainSpaceSize / 2) column++; } else if ((x - px) * 2 < x - prevX) { - column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); + column += EditorUtil.columnsNumber(c, x, prevX, plainSpaceSize); } } else { @@ -1290,8 +1290,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } else { int diff = px - x; - column += diff / spaceSize; - if (diff % spaceSize * 2 >= spaceSize) { + column += diff / plainSpaceSize; + if (diff % plainSpaceSize * 2 >= plainSpaceSize) { column++; } } @@ -1549,7 +1549,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi // so, we can't just use 'startOffset + targetColumn' as a max end offset. IterationState state = new IterationState(this, startOffset, calcEndOffset(startOffset, targetColumn), false); int fontType = state.getMergedAttributes().getFontType(); - int spaceSize = EditorUtil.getSpaceWidth(fontType, this); + int plainSpaceSize = EditorUtil.getSpaceWidth(Font.PLAIN, this); int column = 0; outer: @@ -1588,8 +1588,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (c == '\t') { int prevX = x; x = EditorUtil.nextTabStop(x, this); - int columnDiff = (x - prevX) / spaceSize; - if ((x - prevX) % spaceSize > 0) { + int columnDiff = (x - prevX) / plainSpaceSize; + if ((x - prevX) % plainSpaceSize > 0) { // There is a possible case that tabulation symbol takes more than one visual column to represent and it's shown at // soft-wrapped line. Soft wrap sign width may be not divisible by space size, hence, part of tabulation symbol represented // as a separate visual column may take less space than space width. @@ -2895,7 +2895,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi + ", soft wraps: " + (mySoftWrapModel.isSoftWrappingEnabled() ? "on" : "off") + ", soft wraps data: " + getSoftWrapModel().dumpState() + "\n\nfolding data: " + getFoldingModel().dumpState() - + (myDocument instanceof DocumentImpl ? "\n\ndocument info: " + ((DocumentImpl)myDocument).dumpState() : ""); + + (myDocument instanceof DocumentImpl ? "\n\ndocument info: " + ((DocumentImpl)myDocument).dumpState() : "") + + "\nfont preferences: " + myScheme.getFontPreferences(); } private class CachedFontContent { @@ -6623,7 +6624,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int fontType = state.getMergedAttributes().getFontType(); int column = 0; int x = 0; - int spaceSize = EditorUtil.getSpaceWidth(fontType, this); + int plainSpaceSize = EditorUtil.getSpaceWidth(Font.PLAIN, this); for (int i = start; i < offset; i++) { if (i >= state.getEndOffset()) { state.advance(); @@ -6639,7 +6640,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (c == '\t') { int prevX = x; x = EditorUtil.nextTabStop(x, this); - column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); + column += EditorUtil.columnsNumber(c, x, prevX, plainSpaceSize); } else { x += EditorUtil.charWidth(c, fontType, this); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 3a819d88a370..881dc4100204 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -270,8 +270,9 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { EditorPosition position = new EditorPosition(logical, start, myEditor); position.x = point.x; int spaceWidth = EditorUtil.getSpaceWidth(myContext.fontType, myEditor); + int plainSpaceWidth = EditorUtil.getSpaceWidth(Font.PLAIN, myEditor); - myContext.logicalLineData.update(logical.line, spaceWidth, myEditor); + myContext.logicalLineData.update(logical.line, spaceWidth, plainSpaceWidth); myContext.currentPosition = position; myContext.lineStartPosition = position.clone(); @@ -363,8 +364,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { revertListeners(softWrap.getStart(), myContext.currentPosition.visualLine); for (int j = foldRegion.getStartOffset() - 1; j >= softWrap.getStart(); j--) { int pixelsDiff = myOffset2widthInPixels.data[j - myOffset2widthInPixels.anchor]; - int tmpFontType = myOffset2fontType.get(j); - int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getSpaceWidth(tmpFontType)); + int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getPlainSpaceWidth()); myContext.currentPosition.offset--; myContext.currentPosition.logicalColumn -= columnsDiff; myContext.currentPosition.visualColumn -= columnsDiff; @@ -582,8 +582,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { revertListeners(actualSoftWrapOffset, myContext.currentPosition.visualLine); for (int j = offset - 1; j >= actualSoftWrapOffset; j--) { int pixelsDiff = myOffset2widthInPixels.data[j - myOffset2widthInPixels.anchor]; - int tmpFontType = myOffset2fontType.get(j); - int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getSpaceWidth(tmpFontType)); + int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getPlainSpaceWidth()); myContext.currentPosition.offset--; myContext.currentPosition.logicalColumn -= columnsDiff; myContext.currentPosition.visualColumn -= columnsDiff; @@ -630,12 +629,12 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { return Math.max(start, end); } - private static int calculateWidthInColumns(char c, int widthInPixels, int spaceWithInPixels) { + private static int calculateWidthInColumns(char c, int widthInPixels, int plainSpaceWithInPixels) { if (c != '\t') { return 1; } - int result = widthInPixels / spaceWithInPixels; - if (widthInPixels % spaceWithInPixels > 0) { + int result = widthInPixels / plainSpaceWithInPixels; + if (widthInPixels % plainSpaceWithInPixels > 0) { result++; } return result; @@ -869,7 +868,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { } } updateLastTopLeftCornerOffset(); - return result; + return true; } private void updateLastTopLeftCornerOffset() { @@ -1035,7 +1034,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { public int endLineOffset; public int nonWhiteSpaceSymbolOffset; - public void update(int logicalLine, int spaceWidth, Editor editor) { + public void update(int logicalLine, int spaceWidth, int plainSpaceWidth) { Document document = myEditor.getDocument(); int startLineOffset; if (logicalLine >= document.getLineCount()) { @@ -1055,8 +1054,8 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { switch (c) { case ' ': indentInColumns += 1; indentInPixels += spaceWidth; break; case '\t': - int x = EditorUtil.nextTabStop(indentInPixels, editor); - indentInColumns += calculateWidthInColumns(c, x - indentInPixels, spaceWidth); + int x = EditorUtil.nextTabStop(indentInPixels, myEditor); + indentInColumns += calculateWidthInColumns(c, x - indentInPixels, plainSpaceWidth); indentInPixels = x; break; default: nonWhiteSpaceSymbolOffset = i; return; @@ -1270,8 +1269,12 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { public int getSpaceWidth() { return getSpaceWidth(fontType); } - - public int getSpaceWidth(@JdkConstants.FontStyle int fontType) { + + public int getPlainSpaceWidth() { + return getSpaceWidth(Font.PLAIN); + } + + private int getSpaceWidth(@JdkConstants.FontStyle int fontType) { int result = fontType2spaceWidth.get(fontType); if (result <= 0) { result = EditorUtil.getSpaceWidth(fontType, myEditor); @@ -1280,7 +1283,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { assert result > 0; return result; } - + /** * Asks current context to update its state assuming that it begins to point to the line next to its current position. */ @@ -1293,7 +1296,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { lastFoldEndPosition = null; lastFold = null; lineStartPosition.from(currentPosition); - logicalLineData.update(currentPosition.logicalLine, getSpaceWidth(), myEditor); + logicalLineData.update(currentPosition.logicalLine, getSpaceWidth(), getPlainSpaceWidth()); fontType = myOffset2fontType.get(currentPosition.offset); myOffset2fontType.clear(); @@ -1330,7 +1333,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { myOffset2widthInPixels.data[currentPosition.offset - myOffset2widthInPixels.anchor] = widthInPixels; myOffset2widthInPixels.end++; - int widthInColumns = calculateWidthInColumns(c, widthInPixels, myContext.getSpaceWidth()); + int widthInColumns = calculateWidthInColumns(c, widthInPixels, myContext.getPlainSpaceWidth()); if (c == '\t') { notifyListenersOnVisualLineStart(myContext.lineStartPosition); notifyListenersOnTabulation(widthInColumns); From 14d5241b0d6b1bc330da25bd0c1f6c80ab283c5b Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 20 Aug 2014 17:54:16 +0400 Subject: [PATCH 21/31] icons optimized --- platform/icons/src/actions/GroupByClass.png | Bin 494 -> 366 bytes platform/icons/src/actions/GroupByFile.png | Bin 266 -> 176 bytes .../icons/src/general/projectConfigurable.png | Bin 1076 -> 122 bytes platform/icons/src/gutter/extAnnotation.png | Bin 322 -> 224 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/platform/icons/src/actions/GroupByClass.png b/platform/icons/src/actions/GroupByClass.png index dddca942c295d82a98f4f68807f6b211daa33e0a..8370b26019d19ca76f1d7a00a314076fe7dc32ea 100644 GIT binary patch delta 340 zcmV-a0jvJ*1MUKlBYy!kNklTG*3VEvbpWRlV@!QpZx-3Aba}hmyPI#U^Srk$g_h}PQCuW`QA4a3=#v$;Wc2& z$rp_iPrUxW;qEuA7$gT&(~Q%A#yyXpt-by2KL~fPIq*NDx_|w@hhOmj(1eWtFmaF? zoCehGdGc%Jt*`$Kdh1b6P2jRL!+x{n2wETAmc_BIHKTN!8=Of%+=sNnmx$)r3|8uW?!HPk0 zAT@ZSv3~E9gG~(wUjCnT`3njLiGkz@rUMXeKm4q%Wc$NsgBvvy6RLusc z9tIYuAc|(Y!U@gqzx_^TU}O>j3;h50Mv$9z_MyIldL%NV>gRuGd{hG%{=ND0@4qC7ZQv2c zuy^4EhNsugGw_K@GWZmCKn?!)2B!f6+^lmSy#87vBf`xfZ)^v~Fz^THgC}pkG6?Xn z&czuE=cg3a{`>R$(Bs!%!2yYkL1G{|kQ$r@fWWOerB3$j%zxW&J$d{5`lENhK^Vja zinW5|aODMaAbUNLNg0+O0)ctqB+LaTK>|<-qBKMGKwLlx00=Mu=fAa<5B{T100000 LNkvXXu0mjfT$$9O diff --git a/platform/icons/src/actions/GroupByFile.png b/platform/icons/src/actions/GroupByFile.png index b79988d3f0ed13449da3938ceece86dc810554da..56a2d76c9e0f9bbe14cf05684d9649294f0ffe8a 100644 GIT binary patch delta 148 zcmV;F0Biq>0tZaUugg3{nGCi(&w> z=Kol5BQ`^j4FCx+;4z>9h&zxB0P7)S05YEeYDho11|VaS4Zsj5+5nG9d;Wtk*#-=K z7vRFQF~FRde1Mje&CxTHIm{&l@H41dL}sD{0|1uKE1V&bkquM;0000J#Yg+0{CnO8Pb8ohZzDl02^S0Vi0Hm;vYcVk7qRuhychTU5G5fM1*E! zmtX+A25e{4{tvu38R}am}neuQ71>i*W(Ty2!l=9_tF3F_xpb?j*eXJ?mX4W zaa?z9$Skn6BYcmvv+w7n_G4`6rI`{PBNbYMKIYPhlrf)k;3O_!h~{QCa6iW#p0SH1 zTFMXW7I7jlw29OmkD)oPf1vI`YYJ1oj3;e3CH#E(O5kmj62@bBIqw;`Y7fo(cx-;8 zXw6Sq8WILB@%?q35jdDazV1xBfnHAu4PKq?!)r<48zyurCG0v?%8&8}@i8BZ#6(L5 zQ9hwXKnz5a;3BWcK$T=w0;&iUUDk9E!KUR2!7DnQYnsX;m{+Biq8}+<-#Y!Yyr^X*aRTfmq$}F{H#V5;EQDg3&6WB&ZUP zHw^y#xa}fR3oe8e+6~ymzI_9utWO-ikz(E6M;>TMj>B?XOlX!RT9v3KCX-r4RH8Dr zqA`qtk`$VF^uMW-m{U^NC;#+K>xwmFxZRrqcG#OE?6TqU*_3?Qyt&LKY$9i-i}jD? z&Dz%YTkV^--(Q`$yU_OT^+RrL<@ogzk3QVrO6E~Iadvg_+r6Ic?cZIArInT5CyO1c z7VLR^=!jJW*=lFFFy*au3OBntd&T%d?Vy+EdyYmOd CR$cA@ diff --git a/platform/icons/src/gutter/extAnnotation.png b/platform/icons/src/gutter/extAnnotation.png index 83bfdd350f5ca5dd4847abd54c6665a36799e569..456eb7171faaeabf8712bd5f73e5a23cdc22a56b 100644 GIT binary patch delta 196 zcmV;#06YJ}0^k9VB!8z#L_t(|+Lh4D2?8+`h2a7FaAg4&;UdChz_Aotn5~;sVg*^- zf)8AX4fp^zLi{5q8pRQ3@eP-oIhWiNA%vof$Hy3xSa_Tz)@6477HF`8LnThV<}*<0 zpw6dBtuvbkyr#u^gcUZ}s^|32GjK{1u*L*^T-BSZ?tKd!F+Idsi^tv^x3(+Iu*VV$ y9CWoo9 Date: Thu, 21 Aug 2014 11:17:01 +0400 Subject: [PATCH 22/31] test fixed --- .../testSrc/com/intellij/roots/libraries/LibraryTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java b/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java index 3f5435f2f714..d1943d6144ce 100644 --- a/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/libraries/LibraryTest.java @@ -69,13 +69,13 @@ public class LibraryTest extends ModuleRootManagerTestCase { LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTable(myProject); Library library = table.createLibrary("native"); Library.ModifiableModel model = library.getModifiableModel(); - model.addRoot("file://native", NativeLibraryOrderRootType.getInstance()); + model.addRoot("file://native-lib-root", NativeLibraryOrderRootType.getInstance()); commit(model); Element element = serialize(library); PlatformTestUtil.assertElementEquals( "" + - "" + + "" + "", element); } From 0b95ecd42924ad83cef79dcfd1610ab49921f0c0 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 21 Aug 2014 11:24:02 +0400 Subject: [PATCH 23/31] resource bundles configuration: added storage specification for ipr-based projects --- .../intellij/lang/properties/ResourceBundleManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java index 9bfdde619655..fd43b9dc0dda 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -15,8 +15,6 @@ */ package com.intellij.lang.properties; -import com.intellij.lang.properties.CustomResourceBundle; -import com.intellij.lang.properties.PropertiesImplUtil; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; @@ -39,7 +37,10 @@ import java.util.regex.Matcher; */ @State( name = "ResourceBundleManager", - storages = {@Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/resourceBundles.xml")}) + storages = { + @Storage(file = StoragePathMacros.PROJECT_FILE), + @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/resourceBundles.xml") + }) public class ResourceBundleManager implements PersistentStateComponent { private final static Logger LOG = Logger.getInstance(ResourceBundleManager.class); private final static Locale DEFAULT_LOCALE = new Locale("", "", ""); From f7ac9a889bee839a335ee49a8b4d9b861cc46277 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 21 Aug 2014 11:29:44 +0400 Subject: [PATCH 24/31] resource bundles configuration: added storage specification for ipr-based projects - 2 --- .../src/com/intellij/lang/properties/ResourceBundleManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java index fd43b9dc0dda..a01c123f8763 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -39,7 +39,7 @@ import java.util.regex.Matcher; name = "ResourceBundleManager", storages = { @Storage(file = StoragePathMacros.PROJECT_FILE), - @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/resourceBundles.xml") + @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/resourceBundles.xml", scheme = StorageScheme.DIRECTORY_BASED) }) public class ResourceBundleManager implements PersistentStateComponent { private final static Logger LOG = Logger.getInstance(ResourceBundleManager.class); From 192157a001d2864bec8407f6add57a1063ddb647 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Thu, 21 Aug 2014 12:33:58 +0400 Subject: [PATCH 25/31] EDU-124 added opportunity to copy from task text --- .../python/edu/editor/StudyEditor.java | 74 ++++++++++++++++--- 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java b/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java index c48395543c8e..083cc4a91f25 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java @@ -4,6 +4,7 @@ import com.intellij.codeHighlighting.BackgroundEditorHighlighter; import com.intellij.icons.AllIcons; import com.intellij.ide.structureView.StructureViewBuilder; import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; @@ -18,10 +19,15 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowId; +import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.pom.Navigatable; import com.intellij.ui.BrowserHyperlinkListener; import com.intellij.ui.HideableTitledPanel; import com.intellij.ui.JBColor; +import com.intellij.util.ui.EmptyClipboardOwner; import com.intellij.util.ui.UIUtil; import com.jetbrains.python.edu.StudyDocumentListener; import com.jetbrains.python.edu.StudyTaskManager; @@ -38,8 +44,8 @@ import javax.swing.text.MutableAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import java.awt.datatransfer.StringSelection; +import java.awt.event.*; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Map; @@ -58,7 +64,7 @@ public class StudyEditor implements TextEditor { private JButton myPrevTaskButton; private JButton myRefreshButton; private static final Map myDocumentListeners = new HashMap(); - private Project myProject; + private final Project myProject; public JButton getCheckButton() { return myCheckButton; @@ -111,8 +117,53 @@ public class StudyEditor implements TextEditor { } } - private static void initializeTaskText(JPanel studyPanel, @Nullable String taskText) { + class CopyListener extends MouseAdapter { + final JTextPane myTextPane; + + public CopyListener(JTextPane textPane) { + myTextPane = textPane; + } + + @Override + public void mouseReleased(MouseEvent e) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + ToolWindow projectView = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PROJECT_VIEW); + if (projectView == null) { + return; + } + final Component focusComponent = projectView.getComponent(); + IdeFocusManager.getInstance(myProject).requestFocus(focusComponent, true); + final String text = myTextPane.getSelectedText(); + if (text == null) { + return; + } + KeyAdapter keyAdapter = new KeyAdapter() { + @Override + public void keyPressed(KeyEvent ev) { + if (ev.getKeyCode() == KeyEvent.VK_C + && ev.getModifiers() == InputEvent.CTRL_MASK) { + StringSelection selection = new StringSelection(text); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, EmptyClipboardOwner.INSTANCE); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + IdeFocusManager.getInstance(myProject).requestFocus(myDefaultEditor.getComponent(), true); + } + }); + } + } + }; + focusComponent.addKeyListener(keyAdapter); + } + }); + } + } + + private void initializeTaskText(JPanel studyPanel, @Nullable String taskText) { JTextPane taskTextPane = new JTextPane(); + taskTextPane.addMouseListener(new CopyListener(taskTextPane)); taskTextPane.setContentType("text/html"); taskTextPane.setEditable(false); taskTextPane.setText(taskText); @@ -157,7 +208,8 @@ public class StudyEditor implements TextEditor { watchInputButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - StudyEditInputAction studyEditInputAction = (StudyEditInputAction)ActionManager.getInstance().getAction("WatchInputAction"); + StudyEditInputAction studyEditInputAction = + (StudyEditInputAction)ActionManager.getInstance().getAction("WatchInputAction"); studyEditInputAction.showInput(myProject); } }); @@ -173,7 +225,8 @@ public class StudyEditor implements TextEditor { myNextTaskButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - StudyNextStudyTaskAction studyNextTaskAction = (StudyNextStudyTaskAction)ActionManager.getInstance().getAction("NextTaskAction"); + StudyNextStudyTaskAction studyNextTaskAction = + (StudyNextStudyTaskAction)ActionManager.getInstance().getAction("NextTaskAction"); studyNextTaskAction.navigateTask(myProject); } }); @@ -188,7 +241,8 @@ public class StudyEditor implements TextEditor { myRefreshButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - StudyRefreshTaskAction studyRefreshTaskAction = (StudyRefreshTaskAction)ActionManager.getInstance().getAction("RefreshTaskAction"); + StudyRefreshTaskAction studyRefreshTaskAction = + (StudyRefreshTaskAction)ActionManager.getInstance().getAction("RefreshTaskAction"); studyRefreshTaskAction.refresh(myProject); } }); @@ -308,7 +362,8 @@ public class StudyEditor implements TextEditor { if (fileEditor instanceof StudyEditor) { return (StudyEditor)fileEditor; } - } catch (Exception e) { + } + catch (Exception e) { return null; } return null; @@ -333,8 +388,9 @@ public class StudyEditor implements TextEditor { @NotNull @Override public Editor getEditor() { - if (myDefaultEditor instanceof TextEditor) + if (myDefaultEditor instanceof TextEditor) { return ((TextEditor)myDefaultEditor).getEditor(); + } return EditorFactory.getInstance().createViewer(new DocumentImpl(""), myProject); } From a76066a96a9c50598830514401311fc96a60c69f Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 20 Aug 2014 20:27:43 +0400 Subject: [PATCH 26/31] validation changed: invalid target rendered as error_text --- .../src/com/intellij/dvcs/push/PushController.java | 8 +++----- .../src/com/intellij/dvcs/push/ui/RepositoryNode.java | 8 ++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java index 2a409e12c854..c34864a2044f 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -38,7 +38,6 @@ import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -82,13 +81,10 @@ public class PushController implements Disposable { if (model.isSelected()) { //has one or more selected roots validInfo = null; - RepositoryNode node = entry.getKey(); PushTarget target = model.getSpec().getTarget(); //todo add validation for model -> hasErrors, too if (target == null) { - JComponent editingComponent = myPushLog.startEditNode(node); - return new ValidationInfo("Invalid remote for repository " + DvcsUtil.getShortRepositoryName(model.getRepository()), - editingComponent); + return new ValidationInfo("Invalid remote for repository " + DvcsUtil.getShortRepositoryName(model.getRepository())); } } } @@ -160,11 +156,13 @@ public class PushController implements Disposable { public void onTargetChanged(String newValue) { VcsError validationError = support.validate(model.getRepository(), newValue); if (validationError == null) { + repoNode.markTargetValid(true); myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), support.createTarget(repository, newValue))); loadCommits(model, repoNode, false); } else { //todo may be should store validation errors in model and get errors during dialog validation + repoNode.markTargetValid(false); myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), null)); } myDialog.updateButtons(); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java index 24a26ece96d9..b62eda6ec07a 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java @@ -33,6 +33,7 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode @NotNull private final RepositoryWithBranchPanel myRepositoryPanel; private ProgressIndicator myCurrentIndicator; + protected boolean myTargetIsValid = true; public RepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) { super(repositoryPanel); @@ -61,6 +62,9 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode if (StringUtil.isEmptyOrSpaces(targetName)) { renderer.append(ENTER_REMOTE, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES, textField); } + else if (!myTargetIsValid) { + renderer.append(targetName, SimpleTextAttributes.ERROR_ATTRIBUTES, textField); + } else { renderer.append(targetName, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, textField); } @@ -94,4 +98,8 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode public ProgressIndicator startLoading() { return myCurrentIndicator = new EmptyProgressIndicator(); } + + public void markTargetValid(boolean isValid) { + myTargetIsValid = isValid; + } } From f1d4ca661ad31c6921d8db1ade68a989b56265f1 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Thu, 21 Aug 2014 12:34:30 +0400 Subject: [PATCH 27/31] Provide cancel editing for repository targets. * target changed successfully only whe editing stopped and reverted to previous value if editing cancelled; * targetChanged event handling simplified: unnecessary parameter 'value' removed --- .../dvcs/push/ui/EditableTreeNode.java | 4 +++- .../com/intellij/dvcs/push/ui/PushLog.java | 19 +++++++++++-------- .../intellij/dvcs/push/ui/RepositoryNode.java | 14 ++++++++++++-- .../push/ui/RepositoryWithBranchPanel.java | 11 +++++++++-- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java index 5d0d20cdc4c0..b5747de91bf7 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java @@ -20,7 +20,9 @@ import org.jetbrains.annotations.NotNull; public interface EditableTreeNode extends CustomRenderedTreeNode { - void fireOnChange(@NotNull String value); + void fireOnChange(); + + void fireOnCancel(); void fireOnSelectionChange(boolean isSelected); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java index b07bf9243f8a..0b35702c9220 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java @@ -31,7 +31,6 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.CellEditorListener; @@ -56,6 +55,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { private final ChangesBrowser myChangesBrowser; private final CheckboxTree myTree; private final MyTreeCellRenderer myTreeCellRenderer; + //private final AtomicBoolean myIgnoreStopEditing = new AtomicBoolean(false); public PushLog(Project project, CheckedTreeNode root) { DefaultTreeModel treeModel = new DefaultTreeModel(root); @@ -96,14 +96,17 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { treeCellEditor.addCellEditorListener(new CellEditorListener() { @Override public void editingStopped(ChangeEvent e) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent(); + if (node != null && node instanceof EditableTreeNode) { + ((EditableTreeNode)node).fireOnChange(); + } } @Override public void editingCanceled(ChangeEvent e) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent(); if (node != null && node instanceof EditableTreeNode) { - //todo restore from appropriate editor - ((EditableTreeNode)node).fireOnChange(((EditableTreeNode)node).getValue()); + ((EditableTreeNode)node).fireOnCancel(); } } }); @@ -173,7 +176,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { @Override protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { if (e.getKeyCode() == KeyEvent.VK_ENTER && myTree.isEditing()) { - myTree.cancelEditing(); + myTree.stopEditing(); return true; } return super.processKeyBinding(ks, e, condition, pressed); @@ -265,6 +268,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { final DefaultTreeModel model = ((DefaultTreeModel)myTree.getModel()); model.nodeStructureChanged(parentNode); TreePath path = TreeUtil.getPathFromRoot(parentNode); + //myIgnoreStopEditing.set(true); if (shouldExpand) { myTree.expandPath(path); } @@ -274,16 +278,15 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { } finally { TREE_CONSTRUCTION_LOCK.writeLock().unlock(); + //myIgnoreStopEditing.set(false); } } - @Nullable - public JComponent startEditNode(@NotNull TreeNode node) { + public void startEditNode(@NotNull TreeNode node) { TreePath path = TreeUtil.getPathFromRoot(node); if (!myTree.isEditing()) { + myTree.setSelectionPath(path); myTree.startEditingAtPath(path); } - return (JComponent)myTree.getCellEditor() - .getTreeCellEditorComponent(myTree, node, false, false, false, myTree.getRowForPath(path)); } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java index b62eda6ec07a..d2fa0e249f07 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java @@ -70,6 +70,11 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode } } + @Override + public Object getUserObject() { + return myRepositoryPanel; + } + @Override @NotNull public String getValue() { @@ -77,8 +82,13 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode } @Override - public void fireOnChange(@NotNull String value) { - myRepositoryPanel.fireOnChange(value); + public void fireOnChange() { + myRepositoryPanel.fireOnChange(); + } + + @Override + public void fireOnCancel() { + myRepositoryPanel.fireOnCancel(); } @Override diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java index 131c8e2a19a8..5532568c9cf9 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java @@ -48,6 +48,7 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel private final JLabel myRepositoryLabel; private final ColoredTreeCellRenderer myTextRenderer; @NotNull private final List myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); + private String myOldDestination; public RepositoryWithBranchPanel(Project project, @NotNull String repoName, @NotNull String sourceName, String targetName, @NotNull Collection targetVariants) { @@ -65,6 +66,7 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel myRepositoryLabel = new JLabel(repoName); myLocalBranch = new JBLabel(sourceName); myArrowLabel = new JLabel(" -> "); + myOldDestination = targetName; TextFieldWithAutoCompletionListProvider provider = new TextFieldWithAutoCompletion.StringsCompletionProvider(targetVariants, null); myDestBranchTextField = new TextFieldWithAutoCompletion(project, provider, true, targetName) { @@ -172,9 +174,10 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel myListeners.add(listener); } - public void fireOnChange(@NotNull String newValue) { + public void fireOnChange() { + myOldDestination = myDestBranchTextField.getText(); for (RepositoryNodeListener listener : myListeners) { - listener.onTargetChanged(newValue); + listener.onTargetChanged(myOldDestination); } } @@ -183,6 +186,10 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel listener.onSelectionChanged(isSelected); } } + + public void fireOnCancel() { + myDestBranchTextField.setText(myOldDestination); + } } From 786a88f583f6f0c8b264e1eb2f2d4b4fce91bd5f Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 20 Aug 2014 15:37:20 +0200 Subject: [PATCH 28/31] highlight unused LowMemoryWatcher.register call results and create a less error-prone overload with parentDisposable --- .../BaseExternalAnnotationsManager.java | 15 +++++++------- .../psi/impl/file/impl/FileManagerImpl.java | 13 ++++++------ .../com/intellij/semantic/SemServiceImpl.java | 12 ++--------- .../newvfs/persistent/PersistentFSImpl.java | 13 ++++++------ .../openapi/roots/impl/RootIndex.java | 14 ++++++------- .../openapi/util/LowMemoryWatcher.java | 20 +++++++++++++++++++ 6 files changed, 48 insertions(+), 39 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java index 05b516e47ee5..966504719826 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java @@ -49,21 +49,20 @@ import java.util.concurrent.ConcurrentMap; public abstract class BaseExternalAnnotationsManager extends ExternalAnnotationsManager { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.BaseExternalAnnotationsManager"); + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") @NotNull private static final List NULL_LIST = new ArrayList(0); @NotNull private final ConcurrentMap> myExternalAnnotations = new ConcurrentSoftValueHashMap>(10, 0.75f, 2); protected final PsiManager myPsiManager; - @SuppressWarnings("UnusedDeclaration") - private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() { - @Override - public void run() { - dropCache(); - } - }); - public BaseExternalAnnotationsManager(final PsiManager psiManager) { myPsiManager = psiManager; + LowMemoryWatcher.register(new Runnable() { + @Override + public void run() { + dropCache(); + } + }, psiManager.getProject()); } @Nullable diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java index 7b4e9ec210ac..80d10dd2c1b3 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java @@ -71,13 +71,6 @@ public class FileManagerImpl implements FileManager { private final FileDocumentManager myFileDocumentManager; private final MessageBusConnection myConnection; - @SuppressWarnings("UnusedDeclaration") - private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() { - @Override - public void run() { - processQueue(); - } - }); public FileManagerImpl(PsiManagerImpl manager, FileDocumentManager fileDocumentManager, FileIndexFacade fileIndex) { myManager = manager; @@ -98,6 +91,12 @@ public class FileManagerImpl implements FileManager { } }); Disposer.register(manager.getProject(), this); + LowMemoryWatcher.register(new Runnable() { + @Override + public void run() { + processQueue(); + } + }, this); } private static final VirtualFile NULL = new LightVirtualFile(); diff --git a/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java b/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java index 102a439e11f8..1624c48f2ae5 100644 --- a/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java @@ -17,8 +17,6 @@ package com.intellij.semantic; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.util.LowMemoryWatcher; import com.intellij.openapi.util.RecursionGuard; import com.intellij.openapi.util.RecursionManager; @@ -83,7 +81,7 @@ public class SemServiceImpl extends SemService{ }); - final LowMemoryWatcher watcher = LowMemoryWatcher.register(new Runnable() { + LowMemoryWatcher.register(new Runnable() { @Override public void run() { if (myCreatingSem.get() == 0) { @@ -91,13 +89,7 @@ public class SemServiceImpl extends SemService{ } //System.out.println("SemService cache flushed"); } - }); - ProjectManager.getInstance().addProjectManagerListener(project, new ProjectManagerAdapter() { - @Override - public void projectClosing(Project project) { - watcher.stop(); - } - }); + }, project); } private static MultiMap cacheKeyHierarchy(Collection allKeys) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java index d7b90178e7e8..db5de4258d41 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java @@ -67,15 +67,16 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone private final Object myInputLock = new Object(); private final AtomicBoolean myShutDown = new AtomicBoolean(false); + @SuppressWarnings("FieldCanBeLocal") + private final LowMemoryWatcher myWatcher = LowMemoryWatcher.register(new Runnable() { + @Override + public void run() { + clearIdCache(); + } + }); public PersistentFSImpl(@NotNull MessageBus bus) { myEventBus = bus; - LowMemoryWatcher.register(new Runnable() { - @Override - public void run() { - clearIdCache(); - } - }); ShutDownTracker.getInstance().registerShutdownTask(new Runnable() { @Override public void run() { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java index bc85dabc9aec..bd9531a2d888 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java @@ -71,14 +71,6 @@ public class RootIndex { private final TObjectIntHashMap> myRootTypeId = new TObjectIntHashMap>(); @NotNull private final Project myProject; private volatile Map myOrderEntries; - @SuppressWarnings("UnusedDeclaration") - private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() { - @Override - public void run() { - myNonExistentPackages.clear(); - } - }); - // made public for Upsource public RootIndex(@NotNull Project project, @NotNull InfoCache cache) { @@ -98,6 +90,12 @@ public class RootIndex { myProjectExcludedRoots.add(root); } } + LowMemoryWatcher.register(new Runnable() { + @Override + public void run() { + myNonExistentPackages.clear(); + } + }, project); } @NotNull diff --git a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java index 33bd953d422f..f6c7b924590a 100644 --- a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java +++ b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.util; +import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.containers.WeakList; @@ -93,10 +94,29 @@ public class LowMemoryWatcher { }, null, null); } + /** + * Registers a runnable to run on low memory events + * @return a LowMemoryWatcher instance holding the runnable. This instance should be kept in memory while the + * low memory notification functionality is needed. As soon as it's garbage-collected, the runnable won't receive any further notifications. + */ public static LowMemoryWatcher register(Runnable runnable) { return new LowMemoryWatcher(runnable); } + /** + * Registers a runnable to run on low memory events. The notifications will be issued until parentDisposable is disposed. + */ + public static void register(Runnable runnable, Disposable parentDisposable) { + final Ref watcher = Ref.create(new LowMemoryWatcher(runnable)); + Disposer.register(parentDisposable, new Disposable() { + @Override + public void dispose() { + watcher.get().stop(); + watcher.set(null); + } + }); + } + private LowMemoryWatcher(Runnable runnable) { myRunnable = runnable; ourInstances.add(this); From d6ff9b7629d3da2df16b3c5cef00cbee09b64caa Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 21 Aug 2014 10:40:48 +0200 Subject: [PATCH 29/31] cglib: don't override jdk 8 default methods as it causes jre to go crazy --- .../src/net/sf/cglib/proxy/AdvancedEnhancer.java | 10 ++++++++++ .../tests/com/intellij/util/xml/ProxyTest.java | 2 ++ 2 files changed, 12 insertions(+) diff --git a/platform/platform-impl/src/net/sf/cglib/proxy/AdvancedEnhancer.java b/platform/platform-impl/src/net/sf/cglib/proxy/AdvancedEnhancer.java index 5b22e706508a..92d98a708036 100644 --- a/platform/platform-impl/src/net/sf/cglib/proxy/AdvancedEnhancer.java +++ b/platform/platform-impl/src/net/sf/cglib/proxy/AdvancedEnhancer.java @@ -26,6 +26,7 @@ import org.objectweb.asm.Type; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.*; /** @@ -61,6 +62,7 @@ import java.util.*; * java.lang.reflect.Proxy, see the {@link Proxy} class. */ +@SuppressWarnings("StaticFieldReferencedViaSubclass") public class AdvancedEnhancer extends AbstractClassGenerator { private static final CallbackFilter ALL_ZERO = new CallbackFilter(){ @@ -520,6 +522,9 @@ public class AdvancedEnhancer extends AbstractClassGenerator } final Map methodInfoMap = new HashMap(); for (Method method : actualMethods) { + if (isJdk8DefaultMethod(method)) { + continue; + } int modifiers = Constants.ACC_FINAL | (method.getModifiers() & ~Constants.ACC_ABSTRACT & ~Constants.ACC_NATIVE & ~Constants.ACC_SYNCHRONIZED); if (forcePublic.contains(MethodWrapper.create(method))) { @@ -551,6 +556,11 @@ public class AdvancedEnhancer extends AbstractClassGenerator e.end_class(); } + private static boolean isJdk8DefaultMethod(Method method) { + return ((method.getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == + Modifier.PUBLIC) && method.getDeclaringClass().isInterface(); + } + private static void removeAllCovariantMethods(final List actualMethods, final Method method, final Map covariantMethods) { if ((method.getModifiers() & Constants.ACC_SYNTHETIC) != 0) { return; diff --git a/xml/dom-tests/tests/com/intellij/util/xml/ProxyTest.java b/xml/dom-tests/tests/com/intellij/util/xml/ProxyTest.java index 3db1009c15de..c44d9e74eb45 100644 --- a/xml/dom-tests/tests/com/intellij/util/xml/ProxyTest.java +++ b/xml/dom-tests/tests/com/intellij/util/xml/ProxyTest.java @@ -107,6 +107,8 @@ public class ProxyTest extends TestCase { public abstract String getBar(); + @Override + public abstract String foo(); } public void testAddInterfaces() throws Throwable { From 05c86c2af1b4c7cb40d95edf3c4f647f007d45aa Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Thu, 21 Aug 2014 10:46:09 +0200 Subject: [PATCH 30/31] Logo --- .../edu/build/resources/{logo.bmp => edulogo.bmp} | Bin python/edu/build/strings.nsi | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename python/edu/build/resources/{logo.bmp => edulogo.bmp} (100%) diff --git a/python/edu/build/resources/logo.bmp b/python/edu/build/resources/edulogo.bmp similarity index 100% rename from python/edu/build/resources/logo.bmp rename to python/edu/build/resources/edulogo.bmp diff --git a/python/edu/build/strings.nsi b/python/edu/build/strings.nsi index fa10d421024c..649fed1c4f80 100644 --- a/python/edu/build/strings.nsi +++ b/python/edu/build/strings.nsi @@ -4,7 +4,7 @@ !define PRODUCT_EXE_FILE "pycharm.exe" !define PRODUCT_ICON_FILE "PC_instCom.ico" !define PRODUCT_UNINST_ICON_FILE "PC_uninstCom.ico" -!define PRODUCT_LOGO_FILE "logo.bmp" +!define PRODUCT_LOGO_FILE "edulogo.bmp" !define PRODUCT_HEADER_FILE "headerlogo.bmp" ; if SHOULD_SET_DEFAULT_INSTDIR != 0 then default installation directory will be directory where highest-numbered PyCharm build has been installed From 93abe01096b0aa7f86f4f1f1fbd673a6c99a40f3 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Thu, 21 Aug 2014 12:56:54 +0400 Subject: [PATCH 31/31] cosmetics --- .../compiler/server/BuildManager.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index f176f87373bc..669cf92d37da 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -1121,31 +1121,31 @@ public class BuildManager implements ApplicationComponent{ private final Set myRootsToRefresh = new THashSet(FileUtil.PATH_HASHING_STRATEGY); @Override public void compilationFinished(boolean aborted, int errors, int warnings, CompileContext compileContext) { + final String[] roots; synchronized (myRootsToRefresh) { - final String[] roots = ArrayUtil.toStringArray(myRootsToRefresh); + roots = ArrayUtil.toStringArray(myRootsToRefresh); myRootsToRefresh.clear(); - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - @Override - public void run() { - if (project.isDisposed()) { - return; - } - final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); - final LocalFileSystem lfs = LocalFileSystem.getInstance(); - final Set filesToRefresh = new HashSet(); - for (String root : roots) { - final VirtualFile rootFile = lfs.refreshAndFindFileByPath(root); - if (rootFile != null && fileIndex.isInSourceContent(rootFile)) { - filesToRefresh.add(rootFile); - } - } - if (!filesToRefresh.isEmpty()) { - lfs.refreshFiles(filesToRefresh, true, true, null); + } + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + if (project.isDisposed()) { + return; + } + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + final LocalFileSystem lfs = LocalFileSystem.getInstance(); + final Set filesToRefresh = new HashSet(); + for (String root : roots) { + final VirtualFile rootFile = lfs.refreshAndFindFileByPath(root); + if (rootFile != null && fileIndex.isInSourceContent(rootFile)) { + filesToRefresh.add(rootFile); } } - }); - } - + if (!filesToRefresh.isEmpty()) { + lfs.refreshFiles(filesToRefresh, true, true, null); + } + } + }); } @Override