mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -48,7 +48,7 @@ public class SLRUMap<K,V> {
|
||||
myProtectedQueueSize = protectedQueueSize * FACTOR;
|
||||
myProbationalQueueSize = probationalQueueSize * FACTOR;
|
||||
|
||||
myProtectedQueue = new LinkedHashMap<K,V>(10, 0.6f, hashingStrategy) {
|
||||
myProtectedQueue = new LinkedHashMap<K,V>(10, 0.6f, hashingStrategy, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest, K key, V value) {
|
||||
if (size() > myProtectedQueueSize) {
|
||||
@@ -58,15 +58,9 @@ public class SLRUMap<K,V> {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
myProbationalQueue = new LinkedHashMap<K,V>(10, 0.6f, hashingStrategy) {
|
||||
myProbationalQueue = new LinkedHashMap<K,V>(10, 0.6f, hashingStrategy, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(final Map.Entry<K, V> eldest, K key, V value) {
|
||||
if (size() > myProbationalQueueSize) {
|
||||
@@ -75,12 +69,6 @@ public class SLRUMap<K,V> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public class LinkedHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>
|
||||
private int size;
|
||||
private final float loadFactor;
|
||||
private final EqualityPolicy<K> hashingStrategy;
|
||||
|
||||
private final boolean accessOrder;
|
||||
|
||||
public LinkedHashMap() {
|
||||
this(0);
|
||||
@@ -38,19 +38,30 @@ public class LinkedHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>
|
||||
public LinkedHashMap(int capacity) {
|
||||
this(capacity, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
public LinkedHashMap(int capacity, boolean accessOrder) {
|
||||
this(capacity, HashUtil.DEFAULT_LOAD_FACTOR, accessOrder);
|
||||
}
|
||||
|
||||
public LinkedHashMap(int capacity, float loadFactor) {
|
||||
this(capacity, loadFactor, (EqualityPolicy)EqualityPolicy.CANONICAL);
|
||||
}
|
||||
|
||||
public LinkedHashMap(int capacity, float loadFactor, boolean accessOrder) {
|
||||
this(capacity, loadFactor, (EqualityPolicy)EqualityPolicy.CANONICAL, accessOrder);
|
||||
}
|
||||
|
||||
public LinkedHashMap(EqualityPolicy hashingStrategy) {
|
||||
this(0, HashUtil.DEFAULT_LOAD_FACTOR, hashingStrategy);
|
||||
}
|
||||
|
||||
public LinkedHashMap(int capacity, float loadFactor, EqualityPolicy<K> hashingStrategy) {
|
||||
this(capacity, loadFactor, hashingStrategy, false);
|
||||
}
|
||||
public LinkedHashMap(int capacity, float loadFactor, EqualityPolicy<K> hashingStrategy, boolean accessOrder) {
|
||||
this.loadFactor = loadFactor;
|
||||
this.hashingStrategy = hashingStrategy;
|
||||
clear(capacity);
|
||||
this.accessOrder = accessOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -200,12 +211,8 @@ public class LinkedHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>
|
||||
size = 0;
|
||||
}
|
||||
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void moveToTop(final Entry<K, V> e) {
|
||||
if (!shouldMoveEntryToTopWhenReading()) {
|
||||
if (!accessOrder) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public class PagePool {
|
||||
private PoolPageKey lastFinalizedKey = null;
|
||||
|
||||
public PagePool(final int protectedPagesLimit, final int probationalPagesLimit) {
|
||||
myProbationalQueue = new LinkedHashMap<PoolPageKey,Page>(probationalPagesLimit * 2, 0.6f) {
|
||||
myProbationalQueue = new LinkedHashMap<PoolPageKey,Page>(probationalPagesLimit * 2, 0.6f, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(final Map.Entry<PoolPageKey, Page> eldest) {
|
||||
if (size() > probationalPagesLimit) {
|
||||
@@ -54,14 +54,9 @@ public class PagePool {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
myProtectedQueue = new LinkedHashMap<PoolPageKey, Page>(protectedPagesLimit, 0.6f) {
|
||||
myProtectedQueue = new LinkedHashMap<PoolPageKey, Page>(protectedPagesLimit, 0.6f, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(final Map.Entry<PoolPageKey, Page> eldest) {
|
||||
if (size() > protectedPagesLimit) {
|
||||
@@ -70,10 +65,6 @@ public class PagePool {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -484,17 +484,12 @@ public class PagedFileStorage implements Forceable {
|
||||
myDefaultStorageLockContext = new StorageLockContext(this, checkThreadAccess);
|
||||
|
||||
mySizeLimit = UPPER_LIMIT;
|
||||
mySegments = new LinkedHashMap<Integer, ByteBufferWrapper>(10, 0.75f) {
|
||||
mySegments = new LinkedHashMap<Integer, ByteBufferWrapper>(10, 0.75f, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Integer, ByteBufferWrapper> eldest) {
|
||||
return mySize > mySizeLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ByteBufferWrapper remove(Object key) {
|
||||
|
||||
@@ -135,17 +135,11 @@ public class LinkedHashMapTest {
|
||||
|
||||
@Test
|
||||
public void lru2() {
|
||||
final LinkedHashMap<Integer, String> tested = new LinkedHashMap<Integer, String>() {
|
||||
final LinkedHashMap<Integer, String> tested = new LinkedHashMap<Integer, String>(0, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
|
||||
return size() > 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
tested.put(i, Integer.toString(i));
|
||||
@@ -161,17 +155,11 @@ public class LinkedHashMapTest {
|
||||
|
||||
@Test
|
||||
public void lru3() {
|
||||
final LinkedHashMap<Integer, String> tested = new LinkedHashMap<Integer, String>() {
|
||||
final LinkedHashMap<Integer, String> tested = new LinkedHashMap<Integer, String>(0, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
|
||||
return size() > 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
tested.put(i, Integer.toString(i));
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.vcs.log;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -54,4 +55,27 @@ public interface VcsLog {
|
||||
@Nullable
|
||||
Collection<String> getContainingBranches(@NotNull Hash commitHash);
|
||||
|
||||
/**
|
||||
* Returns all {@link VcsRef commit references} available in the log.
|
||||
*/
|
||||
@NotNull
|
||||
Collection<VcsRef> getAllReferences();
|
||||
|
||||
/**
|
||||
* Selects the commit node defined by the given reference (commit hash, branch or tag).
|
||||
*/
|
||||
void jumpToReference(String reference);
|
||||
|
||||
/**
|
||||
* Returns the VCS log toolbar component.
|
||||
*/
|
||||
@NotNull
|
||||
Component getToolbar();
|
||||
|
||||
/**
|
||||
* Returns {@link VcsLogProvider VcsLogProviders} which are active in this log, i.e. which VCS roots are shown in the log.
|
||||
*/
|
||||
@NotNull
|
||||
Collection<VcsLogProvider> getLogProviders();
|
||||
|
||||
}
|
||||
|
||||
@@ -18,11 +18,14 @@
|
||||
<action class="com.intellij.vcs.log.ui.VcsLogCopyHashAction" id="Vcs.Log.CopyHash"
|
||||
icon="AllIcons.Actions.Copy" text="Copy Hash" description="Copy hash value of the selected commit to clipboard" />
|
||||
<action class="com.intellij.vcs.log.ui.VcsLogCreatePatchAction" id="Vcs.Log.CreatePatch" />
|
||||
<action class="com.intellij.vcs.log.ui.GoToRefAction" id="Vcs.Log.GoToRef" icon="AllIcons.Actions.Menu_find" use-shortcut-of="Find"
|
||||
text="Go To Reference" description="Specify hash or name of a branch or a tag to navigate to the commit it points"/>
|
||||
<action class="com.intellij.vcs.log.ui.VcsLogQuickSettingsActions" id="Vcs.Log.QuickSettings"
|
||||
icon="AllIcons.General.Gear" text="Quick Settings" description="Quick Settings" />
|
||||
|
||||
<group id="Vcs.Log.Toolbar">
|
||||
<reference id="Vcs.Log.CopyHash"/>
|
||||
<reference id="Vcs.Log.GoToRef" />
|
||||
<reference id="Vcs.Log.QuickSettings" />
|
||||
</group>
|
||||
<group id="Vcs.Log.ContextMenu">
|
||||
|
||||
@@ -135,6 +135,18 @@ public class DataPack {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Node getNodeByPartOfHash(@NotNull String hash) {
|
||||
Graph graph = getGraphModel().getGraph();
|
||||
for (int i = 0; i < graph.getNodeRows().size(); i++) {
|
||||
Node node = graph.getCommitNodeInRow(i);
|
||||
if (node != null && node.getCommitHash().asString().startsWith(hash.toLowerCase())) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Node getCommonParent(Node a, Node b) {
|
||||
List<Node> commitDiff = getCommitsDownToCommon(a, b);
|
||||
|
||||
@@ -58,4 +58,10 @@ public class RefsModel {
|
||||
public Collection<VcsRef> getBranches() {
|
||||
return myBranches;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<VcsRef> getAllRefs() {
|
||||
return new ArrayList<VcsRef>(myRefsToHashes.values());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -305,6 +305,10 @@ public class VcsLogDataHolder implements Disposable {
|
||||
}, "Building full log...");
|
||||
}
|
||||
|
||||
public boolean isFullLogShowing() {
|
||||
return myFullLogShowing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the VCS for the number of recent unordered commits, orders them and connects to the existing log structure.
|
||||
* This is done after refresh, when the whole log skeleton has been loaded.
|
||||
@@ -487,6 +491,11 @@ public class VcsLogDataHolder implements Disposable {
|
||||
return myLogProviders.keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<VcsLogProvider> getLogProviders() {
|
||||
return myLogProviders.values();
|
||||
}
|
||||
|
||||
private static class RecentCommitsInfo {
|
||||
List<TimedVcsCommit> firstBlockCommits;
|
||||
Collection<VcsRef> newRefs;
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
*/
|
||||
package com.intellij.vcs.log.impl;
|
||||
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import com.intellij.vcs.log.VcsLog;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -84,4 +84,39 @@ public class VcsLogImpl implements VcsLog {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<VcsRef> getAllReferences() {
|
||||
return myDataHolder.getDataPack().getRefsModel().getAllRefs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpToReference(final String reference) {
|
||||
Collection<VcsRef> references = getAllReferences();
|
||||
VcsRef ref = ContainerUtil.find(references, new Condition<VcsRef>() {
|
||||
@Override
|
||||
public boolean value(VcsRef ref) {
|
||||
return ref.getName().startsWith(reference);
|
||||
}
|
||||
});
|
||||
if (ref != null) {
|
||||
myUi.jumpToCommit(ref.getCommitHash());
|
||||
}
|
||||
else {
|
||||
myUi.jumpToCommitByPartOfHash(reference);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Component getToolbar() {
|
||||
return myUi.getToolbar();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<VcsLogProvider> getLogProviders() {
|
||||
return myDataHolder.getLogProviders();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.intellij.vcs.log.impl;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.actionSystem.DataSink;
|
||||
import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -124,7 +127,7 @@ public class VcsLogManager implements Disposable {
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
private static class VcsLogContainer extends JPanel {
|
||||
private class VcsLogContainer extends JPanel implements TypeSafeDataProvider {
|
||||
|
||||
private final JBLoadingPanel myLoadingPanel;
|
||||
|
||||
@@ -139,6 +142,14 @@ public class VcsLogManager implements Disposable {
|
||||
myLoadingPanel.add(mainComponent);
|
||||
myLoadingPanel.stopLoading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calcData(DataKey key, DataSink sink) {
|
||||
if (myUi != null) {
|
||||
myUi.getMainFrame().calcData(key, sink);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class PostponeableLogRefresher implements VcsLogRefresher, Disposable {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log.ui;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupListener;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.VcsLog;
|
||||
import com.intellij.vcs.log.VcsLogDataKeys;
|
||||
import com.intellij.vcs.log.VcsRef;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class GoToRefAction extends DumbAwareAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
final VcsLog log = e.getData(VcsLogDataKeys.VSC_LOG);
|
||||
if (project == null || log == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<String> refs = ContainerUtil.map(log.getAllReferences(), new Function<VcsRef, String>() {
|
||||
@Override
|
||||
public String fun(VcsRef ref) {
|
||||
return ref.getName();
|
||||
}
|
||||
});
|
||||
final PopupWithTextFieldWithAutoCompletion textField = new PopupWithTextFieldWithAutoCompletion(project, refs);
|
||||
JBPopup popup = textField.createPopup();
|
||||
popup.addListener(new JBPopupListener.Adapter() {
|
||||
@Override
|
||||
public void onClosed(LightweightWindowEvent event) {
|
||||
if (event.isOk()) {
|
||||
log.jumpToReference(textField.getText());
|
||||
}
|
||||
}
|
||||
});
|
||||
popup.showUnderneathOf(log.getToolbar());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
VcsLog log = e.getData(VcsLogDataKeys.VSC_LOG);
|
||||
getTemplatePresentation().setEnabledAndVisible(e.getProject() != null && log != null);
|
||||
}
|
||||
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log.ui;
|
||||
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization;
|
||||
import com.intellij.ui.TextFieldWithAutoCompletion;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collection;
|
||||
|
||||
public class PopupWithTextFieldWithAutoCompletion extends TextFieldWithAutoCompletion<String> {
|
||||
|
||||
@Nullable private JBPopup myPopup;
|
||||
|
||||
public PopupWithTextFieldWithAutoCompletion(@NotNull Project project, @NotNull Collection<String> variants) {
|
||||
super(project, new StringsCompletionProvider(variants, null), false, null);
|
||||
|
||||
// this hack is needed, because the preferred size is requested before createEditor(),
|
||||
// and EditorTextField#getPreferredSize() hardcodes unacceptable (100, 20)
|
||||
setPreferredSize(new JBTextField(20).getPreferredSize());
|
||||
}
|
||||
|
||||
public JBPopup createPopup() {
|
||||
myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(this, this)
|
||||
.setCancelOnClickOutside(true)
|
||||
.setCancelOnWindowDeactivation(true)
|
||||
.setCancelKeyEnabled(true)
|
||||
.setRequestFocus(true)
|
||||
.createPopup();
|
||||
return myPopup;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
if (myPopup != null) {
|
||||
myPopup.closeOk(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
if (myPopup != null) {
|
||||
myPopup.cancel(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EditorEx createEditor() {
|
||||
// spell check is not needed
|
||||
EditorEx editor = super.createEditor();
|
||||
SpellCheckingEditorCustomization.getInstance(false).customize(editor);
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.table.TableModel;
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
@@ -205,6 +206,21 @@ public class VcsLogUI {
|
||||
}
|
||||
}
|
||||
|
||||
public void jumpToCommitByPartOfHash(final String hash) {
|
||||
Node node = myLogDataHolder.getDataPack().getNodeByPartOfHash(hash);
|
||||
if (node != null) {
|
||||
jumpToRow(node.getRowIndex());
|
||||
}
|
||||
else if (!myLogDataHolder.isFullLogShowing()) {
|
||||
myLogDataHolder.showFullLog(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
jumpToCommitByPartOfHash(hash);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VcsLogColorManager getColorManager() {
|
||||
return myColorManager;
|
||||
@@ -255,4 +271,7 @@ public class VcsLogUI {
|
||||
myMainFrame.setBranchesPanelVisible(visible);
|
||||
}
|
||||
|
||||
public Component getToolbar() {
|
||||
return myMainFrame.getToolbar();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-51
@@ -18,16 +18,10 @@ package com.intellij.vcs.log.ui.filter;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupAdapter;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization;
|
||||
import com.intellij.ui.TextFieldWithAutoCompletion;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.VcsLogFilter;
|
||||
@@ -35,10 +29,9 @@ import com.intellij.vcs.log.VcsUser;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VcsLogUiProperties;
|
||||
import com.intellij.vcs.log.data.VcsLogUserFilter;
|
||||
import com.intellij.vcs.log.ui.PopupWithTextFieldWithAutoCompletion;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -104,15 +97,8 @@ class UserFilterPopupComponent extends FilterPopupComponent {
|
||||
}
|
||||
});
|
||||
|
||||
final UserTextField textField = new UserTextField(e.getProject(), users);
|
||||
|
||||
JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(textField, textField)
|
||||
.setCancelOnClickOutside(true)
|
||||
.setCancelOnWindowDeactivation(true)
|
||||
.setCancelKeyEnabled(true)
|
||||
.setRequestFocus(true)
|
||||
.createPopup();
|
||||
textField.myPopup = popup;
|
||||
final PopupWithTextFieldWithAutoCompletion textField = new PopupWithTextFieldWithAutoCompletion(e.getProject(), users);
|
||||
JBPopup popup = textField.createPopup();
|
||||
|
||||
popup.addListener(new JBPopupAdapter() {
|
||||
@Override
|
||||
@@ -127,39 +113,5 @@ class UserFilterPopupComponent extends FilterPopupComponent {
|
||||
popup.showUnderneathOf(UserFilterPopupComponent.this);
|
||||
}
|
||||
|
||||
private class UserTextField extends TextFieldWithAutoCompletion<String> {
|
||||
|
||||
private JBPopup myPopup;
|
||||
|
||||
public UserTextField(Project project, Collection<String> users) {
|
||||
super(project, new StringsCompletionProvider(users, null), false, null);
|
||||
|
||||
// this hack is needed, because the preferred size is requested before createEditor(),
|
||||
// and EditorTextField#getPreferredSize() hardcodes unacceptable (100, 20)
|
||||
setPreferredSize(new JBTextField(20).getPreferredSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
myPopup.closeOk(e);
|
||||
return true;
|
||||
}
|
||||
else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
myPopup.cancel(e);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EditorEx createEditor() {
|
||||
// spell check is not needed
|
||||
EditorEx editor = super.createEditor();
|
||||
SpellCheckingEditorCustomization.getInstance(false).customize(editor);
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
@NotNull private final BranchesPanel myBranchesPanel;
|
||||
@NotNull private final DetailsPanel myDetailsPanel;
|
||||
@NotNull private final Splitter myDetailsSplitter;
|
||||
private final JComponent myToolbar;
|
||||
|
||||
public MainFrame(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI vcsLogUI, @NotNull Project project,
|
||||
@NotNull VcsLogSettings settings, @NotNull VcsLogUiProperties uiProperties, @NotNull VcsLog log) {
|
||||
@@ -78,14 +79,14 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
updateWhenDetailsAreLoaded(selectionChangeListener);
|
||||
|
||||
// layout
|
||||
JComponent toolbar = createActionsToolbar();
|
||||
myToolbar = createActionsToolbar();
|
||||
|
||||
myDetailsSplitter = new Splitter(true, 0.7f);
|
||||
myDetailsSplitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myGraphTable));
|
||||
setupDetailsSplitter(myUiProperties.isShowDetails());
|
||||
|
||||
JComponent toolbars = new JPanel(new BorderLayout());
|
||||
toolbars.add(toolbar, BorderLayout.NORTH);
|
||||
toolbars.add(myToolbar, BorderLayout.NORTH);
|
||||
toolbars.add(myBranchesPanel, BorderLayout.CENTER);
|
||||
JComponent toolbarsAndTable = new JPanel(new BorderLayout());
|
||||
toolbarsAndTable.add(toolbars, BorderLayout.NORTH);
|
||||
@@ -234,6 +235,10 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public Component getToolbar() {
|
||||
return myToolbar;
|
||||
}
|
||||
|
||||
private class CommitSelectionListener implements ListSelectionListener {
|
||||
private final ChangesBrowser myChangesBrowser;
|
||||
|
||||
|
||||
@@ -96,6 +96,9 @@
|
||||
<psi.referenceContributor implementation="org.jetbrains.idea.devkit.references.IconsReferencesContributor"/>
|
||||
<referencesSearch implementation="org.jetbrains.idea.devkit.references.IconsReferencesContributor"/>
|
||||
<unusedDeclarationFixProvider implementation="org.jetbrains.idea.devkit.inspections.quickfix.RegisterExtensionFixProvider"/>
|
||||
|
||||
<stacktrace.fold substring="at com.intellij.testFramework."/>
|
||||
|
||||
</extensions>
|
||||
|
||||
<module-components>
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -37,7 +38,10 @@ import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.VcsLog;
|
||||
import com.intellij.vcs.log.VcsLogProvider;
|
||||
import com.intellij.vcsUtil.VcsFileUtil;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
@@ -951,4 +955,16 @@ public class GitUtil {
|
||||
repositoryManager.getRepositories()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are Git roots in the VCS log.
|
||||
*/
|
||||
public static boolean logHasGitRoot(@NotNull VcsLog log) {
|
||||
return ContainerUtil.find(log.getLogProviders(), new Condition<VcsLogProvider>() {
|
||||
@Override
|
||||
public boolean value(VcsLogProvider logProvider) {
|
||||
return logProvider.getSupportedVcs().equals(GitVcs.getKey());
|
||||
}
|
||||
}) != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public abstract class GitLogSingleCommitAction extends DumbAwareAction {
|
||||
}
|
||||
|
||||
boolean isValid() {
|
||||
return project != null && log != null;
|
||||
return project != null && log != null && GitUtil.logHasGitRoot(log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.*;
|
||||
import git4idea.GitLocalBranch;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
@@ -131,7 +132,13 @@ public class GitCherryPickAction extends DumbAwareAction {
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
super.update(e);
|
||||
e.getPresentation().setEnabled(enabled(e));
|
||||
final VcsLog log = getVcsLog(e);
|
||||
if (log != null && !GitUtil.logHasGitRoot(log)) {
|
||||
e.getPresentation().setEnabledAndVisible(false);
|
||||
}
|
||||
else {
|
||||
e.getPresentation().setEnabled(enabled(e));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean enabled(AnActionEvent e) {
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
package git4idea.repo;
|
||||
|
||||
import com.intellij.dvcs.repo.Repository;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitLocalBranch;
|
||||
import git4idea.GitRemoteBranch;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -97,8 +100,8 @@ public class GitRepoInfo {
|
||||
if (myCurrentBranch != null ? !myCurrentBranch.equals(info.myCurrentBranch) : info.myCurrentBranch != null) return false;
|
||||
if (!myRemotes.equals(info.myRemotes)) return false;
|
||||
if (!myBranchTrackInfos.equals(info.myBranchTrackInfos)) return false;
|
||||
if (!myLocalBranches.equals(info.myLocalBranches)) return false;
|
||||
if (!myRemoteBranches.equals(info.myRemoteBranches)) return false;
|
||||
if (!areEqual(myLocalBranches, info.myLocalBranches)) return false;
|
||||
if (!areEqual(myRemoteBranches, info.myRemoteBranches)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -120,4 +123,32 @@ public class GitRepoInfo {
|
||||
return String.format("GitRepoInfo{current=%s, remotes=%s, localBranches=%s, remoteBranches=%s, trackInfos=%s}",
|
||||
myCurrentBranch, myRemotes, myLocalBranches, myRemoteBranches, myBranchTrackInfos);
|
||||
}
|
||||
|
||||
private static <T extends GitBranch> boolean areEqual(Collection<T> c1, Collection<T> c2) {
|
||||
// GitBranch has perverted equals contract (see the comment there)
|
||||
// until GitBranch is created only from a single place with correctly defined Hash, we can't change its equals
|
||||
THashSet<GitBranch> set1 = new THashSet<GitBranch>(c1, new BranchesComparingStrategy());
|
||||
THashSet<GitBranch> set2 = new THashSet<GitBranch>(c2, new BranchesComparingStrategy());
|
||||
return set1.equals(set2);
|
||||
}
|
||||
|
||||
private static class BranchesComparingStrategy implements TObjectHashingStrategy<GitBranch> {
|
||||
|
||||
@Override
|
||||
public int computeHashCode(@NotNull GitBranch branch) {
|
||||
return 31 * branch.getName().hashCode() + branch.getHash().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@NotNull GitBranch b1, @NotNull GitBranch b2) {
|
||||
if (b1 == b2) {
|
||||
return true;
|
||||
}
|
||||
if (b1.getClass() != b2.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return b1.getName().equals(b2.getName()) && b1.getHash().equals(b2.getHash());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,15 +56,10 @@ public class YouTrackIntellisense {
|
||||
private final int myMaxSize;
|
||||
|
||||
private SizeLimitedCache(int max) {
|
||||
super((int)(max / 0.75) + 1);
|
||||
super((int)(max / 0.75) + 1, true);
|
||||
myMaxSize = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveEntryToTopWhenReading() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest, K key, V value) {
|
||||
return size() > myMaxSize;
|
||||
|
||||
@@ -983,16 +983,14 @@
|
||||
<langCodeStyleSettingsProvider implementation="com.intellij.ide.JavaLanguageCodeStyleSettingsProvider"/>
|
||||
|
||||
|
||||
<stacktrace.fold substring="at java.awt.EventDispatchThread.pumpEventsForFilter("/>
|
||||
<stacktrace.fold substring="at java.awt.EventDispatchThread.pumpEventsForHierarchy("/>
|
||||
<stacktrace.fold substring="at java.awt.EventDispatchThread.pumpEvents("/>
|
||||
<stacktrace.fold substring="at java.awt.EventDispatchThread"/>
|
||||
<stacktrace.fold substring="at java.awt.Window.dispatchEventImpl("/>
|
||||
<stacktrace.fold substring="at java.awt.Container.dispatchEventImpl("/>
|
||||
<stacktrace.fold substring="at java.awt.LightweightDispatcher."/>
|
||||
<stacktrace.fold substring="at java.awt.Component.dispatchEvent("/>
|
||||
<stacktrace.fold substring="at java.awt.EventQueue.dispatchEvent("/>
|
||||
<stacktrace.fold substring="at java.awt.event.InvocationEvent.dispatch("/>
|
||||
<stacktrace.fold substring="at java.awt.EventQueue"/>
|
||||
<stacktrace.fold substring="at java.awt.Component.dispatchEventImpl("/>
|
||||
<stacktrace.fold substring="at java.awt.EventDispatchThread.pumpOneEventForFilters("/>
|
||||
<stacktrace.fold substring="at java.awt.Container.processEvent("/>
|
||||
<stacktrace.fold substring="at javax.swing.JComponent.processMouseEvent("/>
|
||||
<stacktrace.fold substring="at javax.swing.plaf.basic.BasicMenuItemUI"/>
|
||||
@@ -1004,12 +1002,10 @@
|
||||
<stacktrace.fold substring="at javax.swing.DefaultButtonModel.setPressed("/>
|
||||
<stacktrace.fold substring="at javax.swing.AbstractButton.fireActionPerformed("/>
|
||||
<stacktrace.fold substring="at javax.swing.AbstractButton$Handler.actionPerformed("/>
|
||||
<stacktrace.fold substring="at java.awt.EventQueue$1.run("/>
|
||||
<stacktrace.fold substring="at java.security.AccessControlContext$1.doIntersectionPrivilege("/>
|
||||
<stacktrace.fold substring="at java.awt.EventQueue.dispatchEventImpl("/>
|
||||
<stacktrace.fold substring="at java.security.AccessController.doPrivileged(Native Method)"/>
|
||||
<stacktrace.fold substring="at java.awt.EventQueue$2.run("/>
|
||||
<stacktrace.fold substring="at java.awt.EventQueue.access$000("/>
|
||||
<stacktrace.fold substring="at java.security.ProtectionDomain$1.doIntersectionPrivilege("/>
|
||||
<stacktrace.fold substring="at com.jgoodies.binding.beans.ExtendedPropertyChangeSupport.firePropertyChange0("/>
|
||||
<stacktrace.fold substring="at javax.swing.plaf.basic.BasicComboPopup$Handler.mouseReleased("/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user