mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[vcs-log] showing repository names IDEA-105467
some magic to make root column to un-shrink merge repository cells tooltip for root column suggests to collapse/expand
This commit is contained in:
@@ -96,16 +96,30 @@ public class TableScrollingUtil {
|
||||
}
|
||||
|
||||
private static int getLeadingRow(JTable table,Rectangle visibleRect) {
|
||||
Point leadingPoint;
|
||||
return table.rowAtPoint(getLeadingPoint(table, visibleRect));
|
||||
}
|
||||
|
||||
private static Point getLeadingPoint(JTable table, Rectangle visibleRect) {
|
||||
if (table.getComponentOrientation().isLeftToRight()) {
|
||||
return new Point(visibleRect.x, visibleRect.y);
|
||||
}
|
||||
else {
|
||||
return new Point(visibleRect.x + visibleRect.width,
|
||||
visibleRect.y);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getReadableRow(JTable table, int maximumHiddenPart) {
|
||||
Rectangle visibleRect = table.getVisibleRect();
|
||||
Point leadingPoint = getLeadingPoint(table, visibleRect);
|
||||
int row = table.rowAtPoint(leadingPoint);
|
||||
int column = table.columnAtPoint(leadingPoint);
|
||||
if (leadingPoint.y - table.getCellRect(row, column, true).getY() <= maximumHiddenPart) {
|
||||
return row;
|
||||
} else {
|
||||
return Math.min(row + 1, table.getRowCount() - 1); // just in case
|
||||
}
|
||||
|
||||
if (table.getComponentOrientation().isLeftToRight()) {
|
||||
leadingPoint = new Point(visibleRect.x, visibleRect.y);
|
||||
}
|
||||
else {
|
||||
leadingPoint = new Point(visibleRect.x + visibleRect.width,
|
||||
visibleRect.y);
|
||||
}
|
||||
return table.rowAtPoint(leadingPoint);
|
||||
}
|
||||
|
||||
private static int getTrailingRow(JTable table,Rectangle visibleRect) {
|
||||
|
||||
@@ -43,6 +43,7 @@ public class VcsLogUiProperties implements PersistentStateComponent<VcsLogUiProp
|
||||
public boolean SHOW_DETAILS = true;
|
||||
public boolean LONG_EDGES_VISIBLE = false;
|
||||
public boolean BEK_SORT = false;
|
||||
public boolean SHOW_ROOT_NAMES = false;
|
||||
public Deque<UserGroup> RECENTLY_FILTERED_USER_GROUPS = new ArrayDeque<UserGroup>();
|
||||
public Deque<UserGroup> RECENTLY_FILTERED_BRANCH_GROUPS = new ArrayDeque<UserGroup>();
|
||||
}
|
||||
@@ -126,6 +127,14 @@ public class VcsLogUiProperties implements PersistentStateComponent<VcsLogUiProp
|
||||
myState.BEK_SORT = isBek;
|
||||
}
|
||||
|
||||
public boolean isShowRootNames() {
|
||||
return myState.SHOW_ROOT_NAMES;
|
||||
}
|
||||
|
||||
public void setShowRootNames(boolean isShowRootNames) {
|
||||
myState.SHOW_ROOT_NAMES = isShowRootNames;
|
||||
}
|
||||
|
||||
public static class UserGroup {
|
||||
public List<String> users = new ArrayList<String>();
|
||||
|
||||
|
||||
@@ -185,6 +185,14 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
|
||||
return myUiProperties.isBek();
|
||||
}
|
||||
|
||||
public void setShowRootNames(boolean isShowRootNames) {
|
||||
myUiProperties.setShowRootNames(isShowRootNames);
|
||||
}
|
||||
|
||||
public boolean isShowRootNames() {
|
||||
return myUiProperties.isShowRootNames();
|
||||
}
|
||||
|
||||
public void jumpToCommit(@NotNull Hash commitHash) {
|
||||
jumpTo(commitHash, new PairFunction<GraphTableModel, Hash, Integer>() {
|
||||
@Override
|
||||
|
||||
@@ -91,7 +91,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
myToolbar = createActionsToolbar();
|
||||
|
||||
myDetailsSplitter = new Splitter(true, 0.7f);
|
||||
myDetailsSplitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myGraphTable));
|
||||
myDetailsSplitter.setFirstComponent(setupScrolledGraph());
|
||||
setupDetailsSplitter(myUiProperties.isShowDetails());
|
||||
|
||||
JComponent toolbars = new JPanel(new BorderLayout());
|
||||
@@ -156,6 +156,12 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
myDetailsSplitter.setSecondComponent(state ? myDetailsPanel : null);
|
||||
}
|
||||
|
||||
private JScrollPane setupScrolledGraph() {
|
||||
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myGraphTable);
|
||||
myGraphTable.viewportSet(scrollPane.getViewport());
|
||||
return scrollPane;
|
||||
}
|
||||
|
||||
private static void setDefaultEmptyText(ChangesBrowser changesBrowser) {
|
||||
changesBrowser.getViewer().setEmptyText("");
|
||||
}
|
||||
|
||||
@@ -18,14 +18,17 @@ package com.intellij.vcs.log.ui.frame;
|
||||
import com.intellij.ide.CopyProvider;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser;
|
||||
import com.intellij.openapi.vcs.changes.issueLinks.TableLinkMouseListener;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.ColoredTableCellRenderer;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.PopupHandler;
|
||||
import com.intellij.ui.TableScrollingUtil;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
@@ -49,6 +52,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.TableModelEvent;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableModel;
|
||||
@@ -67,6 +74,7 @@ import static com.intellij.vcs.log.printer.idea.PrintParameters.HEIGHT_CELL;
|
||||
public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, CopyProvider {
|
||||
|
||||
private static final int ROOT_INDICATOR_WIDTH = 5;
|
||||
private static final int ROOT_NAME_MAX_WIDTH = 200;
|
||||
private static final int MAX_DEFAULT_AUTHOR_COLUMN_WIDTH = 200;
|
||||
private static final int MAX_ROWS_TO_CALC_WIDTH = 1000;
|
||||
private static final int MAX_ROWS_TO_CALC_OFFSET = 100;
|
||||
@@ -97,7 +105,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
myGraphCommitCellRender = new GraphCommitCellRender(myUI.getColorManager(), logDataHolder, myGraphCellPainter,
|
||||
myDataPack.getVisibleGraph(), this);
|
||||
|
||||
setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI, myLogDataHolder.isMultiRoot()));
|
||||
setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI));
|
||||
setDefaultRenderer(GraphCommitCell.class, myGraphCommitCellRender);
|
||||
setDefaultRenderer(String.class, new StringCellRenderer());
|
||||
|
||||
@@ -127,12 +135,8 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
private void setColumnPreferredSize() {
|
||||
for (int i = 0; i < getColumnCount(); i++) {
|
||||
TableColumn column = getColumnModel().getColumn(i);
|
||||
if (i == GraphTableModel.ROOT_COLUMN) { // thin stripe or nothing
|
||||
int rootWidth = myUI.getColorManager().isMultipleRoots() ? ROOT_INDICATOR_WIDTH : 0;
|
||||
// NB: all further instructions and their order are important, otherwise the minimum size which is less than 15 won't be applied
|
||||
column.setMinWidth(rootWidth);
|
||||
column.setMaxWidth(rootWidth);
|
||||
column.setPreferredWidth(rootWidth);
|
||||
if (i == GraphTableModel.ROOT_COLUMN) { // thin stripe, or root name, or nothing
|
||||
setRootColumnSize(column);
|
||||
}
|
||||
else if (i == GraphTableModel.COMMIT_COLUMN) { // let commit message occupy as much as possible
|
||||
column.setPreferredWidth(Short.MAX_VALUE);
|
||||
@@ -155,6 +159,33 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
}
|
||||
}
|
||||
|
||||
private void setRootColumnSize(TableColumn column) {
|
||||
int rootWidth;
|
||||
if (!myUI.getColorManager().isMultipleRoots()) {
|
||||
rootWidth = 0;
|
||||
}
|
||||
else if (!myUI.isShowRootNames()) {
|
||||
rootWidth = ROOT_INDICATOR_WIDTH;
|
||||
}
|
||||
else {
|
||||
rootWidth = Math.min(calculateMaxRootWidth(), ROOT_NAME_MAX_WIDTH);
|
||||
}
|
||||
|
||||
// NB: all further instructions and their order are important, otherwise the minimum size which is less than 15 won't be applied
|
||||
column.setMinWidth(rootWidth);
|
||||
column.setMaxWidth(rootWidth);
|
||||
column.setPreferredWidth(rootWidth);
|
||||
}
|
||||
|
||||
private int calculateMaxRootWidth() {
|
||||
int width = 0;
|
||||
for (VirtualFile file : myLogDataHolder.getRoots()) {
|
||||
Font tableFont = UIManager.getFont("Table.font");
|
||||
width = Math.max(getFontMetrics(tableFont).stringWidth(file.getName() + " "), width);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
private int calcMaxContentColumnWidth(int columnIndex, int maxRowsToCheck) {
|
||||
int maxWidth = 0;
|
||||
for (int row = 0; row < maxRowsToCheck; row++) {
|
||||
@@ -175,7 +206,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
if (column == GraphTableModel.ROOT_COLUMN) {
|
||||
Object at = getValueAt(row, column);
|
||||
if (at instanceof VirtualFile) {
|
||||
return ((VirtualFile)at).getPresentableUrl();
|
||||
return "<html><b>" + ((VirtualFile)at).getPresentableUrl() + "</b><br/>Click to " + (myUI.isShowRootNames() ? "collapse" : "expand") + "</html>";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -292,6 +323,19 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
}
|
||||
}
|
||||
|
||||
public void viewportSet(JViewport viewport) {
|
||||
viewport.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
TableModel model = getModel();
|
||||
if (model instanceof AbstractTableModel) {
|
||||
Couple<Integer> visibleRows = TableScrollingUtil.getVisibleRows(VcsLogGraphTable.this);
|
||||
((AbstractTableModel)model).fireTableChanged(new TableModelEvent(model, visibleRows.first - 1, visibleRows.second, GraphTableModel.ROOT_COLUMN));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class MyMouseAdapter extends MouseAdapter {
|
||||
private final TableLinkMouseListener myLinkListener;
|
||||
|
||||
@@ -306,6 +350,8 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
}
|
||||
|
||||
if (e.getClickCount() == 1) {
|
||||
if (expandOrCollapseRoots(e)) return;
|
||||
|
||||
performAction(e, MyGraphMouseAction.Type.CLICK);
|
||||
}
|
||||
}
|
||||
@@ -320,6 +366,17 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
}
|
||||
}
|
||||
|
||||
private boolean expandOrCollapseRoots(MouseEvent e) {
|
||||
int column = convertColumnIndexToModel(columnAtPoint(e.getPoint()));
|
||||
if (column == GraphTableModel.ROOT_COLUMN && myLogDataHolder.isMultiRoot()) {
|
||||
myUI.setShowRootNames(!myUI.isShowRootNames());
|
||||
setColumnPreferredSize();
|
||||
setRootColumnSize(getColumnModel().getColumn(column));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void performAction(@NotNull MouseEvent e, @NotNull final MyGraphMouseAction.Type actionType) {
|
||||
int row = PositionUtil.getRowIndex(e.getPoint());
|
||||
if (row > getRowCount() - 1) {
|
||||
@@ -381,34 +438,78 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
return myLogDataHolder.isMultiRoot() ? rootColumn.getWidth() : 0;
|
||||
}
|
||||
|
||||
private static class RootCellRenderer extends JPanel implements TableCellRenderer {
|
||||
|
||||
private static class RootCellRenderer extends JBLabel implements TableCellRenderer {
|
||||
@NotNull private final VcsLogUiImpl myUi;
|
||||
|
||||
@NotNull private Color myColor = UIUtil.getTableBackground();
|
||||
private boolean myHasBorder;
|
||||
|
||||
RootCellRenderer(@NotNull VcsLogUiImpl ui, boolean multiRoot) {
|
||||
RootCellRenderer(@NotNull VcsLogUiImpl ui) {
|
||||
super("", CENTER);
|
||||
myUi = ui;
|
||||
int rootWidth = multiRoot ? ROOT_INDICATOR_WIDTH : 0;
|
||||
setPreferredSize(new Dimension(rootWidth, -1));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
g.setColor(myColor);
|
||||
g.fillRect(0, 0, ROOT_INDICATOR_WIDTH - 1, HEIGHT_CELL);
|
||||
UIUtil.drawLine((Graphics2D)g, ROOT_INDICATOR_WIDTH - 1, 0, ROOT_INDICATOR_WIDTH - 1, HEIGHT_CELL, null,
|
||||
myUi.getColorManager().getRootIndicatorBorder());
|
||||
|
||||
int width = getWidth();
|
||||
|
||||
if (myHasBorder) {
|
||||
g.fillRect(0, 0, width - 1, HEIGHT_CELL);
|
||||
UIUtil.drawLine((Graphics2D)g, width - 1, 0, width - 1, HEIGHT_CELL, null, myUi.getColorManager().getRootIndicatorBorder());
|
||||
}
|
||||
else {
|
||||
g.fillRect(0, 0, width, HEIGHT_CELL);
|
||||
}
|
||||
super.paintComponent(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
String text;
|
||||
Color color;
|
||||
|
||||
if (value instanceof VirtualFile) {
|
||||
myColor = myUi.getColorManager().getRootColor((VirtualFile)value);
|
||||
VirtualFile root = (VirtualFile)value;
|
||||
int readableRow = TableScrollingUtil.getReadableRow(table, Math.round(HEIGHT_CELL * 0.5f));
|
||||
if (row < readableRow) {
|
||||
text = "";
|
||||
} else if (row == 0 || !value.equals(table.getModel().getValueAt(row - 1, column)) || readableRow == row) {
|
||||
text = root.getName();
|
||||
} else {
|
||||
text = "";
|
||||
}
|
||||
color = myUi.getColorManager().getRootColor(root);
|
||||
}
|
||||
else {
|
||||
myColor = UIUtil.getTableBackground(isSelected);
|
||||
text = null;
|
||||
color = UIUtil.getTableBackground(isSelected);
|
||||
}
|
||||
|
||||
if (myUi.isShowRootNames()) {
|
||||
// pale colors, honors selection, does not have border
|
||||
if (isSelected) {
|
||||
myColor = UIUtil.getTableBackground(isSelected);
|
||||
}
|
||||
else {
|
||||
//we create JBColor later
|
||||
//noinspection UseJBColor
|
||||
Color transparentColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 50);
|
||||
myColor = new JBColor(transparentColor, transparentColor);
|
||||
}
|
||||
|
||||
setForeground(UIUtil.getTableForeground(isSelected));
|
||||
setText(text);
|
||||
myHasBorder = false;
|
||||
}
|
||||
else {
|
||||
// bright colors, does not know about the selection, has border
|
||||
setForeground(UIUtil.getTableForeground(false));
|
||||
myColor = color;
|
||||
setText("");
|
||||
myHasBorder = true;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user