diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index 8ec833e8258b..d7a8b0c2661e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -187,23 +187,11 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } if (rearrangeEntries && file != null && editor != null) { - final ArrangementEngine engine = ServiceManager.getService(project, ArrangementEngine.class); - try { - final PsiFile finalFile = file; - SelectionModel selectionModel = editor.getSelectionModel(); - final TextRange rangeToUse = selectionModel.hasSelection() - ? TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()) - : TextRange.create(0, editor.getDocument().getTextLength()); - CommandProcessor.getInstance().executeCommand(project, new Runnable() { - @Override - public void run() { - engine.arrange(editor, finalFile, Collections.singleton(rangeToUse)); - } - }, getTemplatePresentation().getText(), null); - } - finally { - PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); - } + SelectionModel selectionModel = editor.getSelectionModel(); + final TextRange rangeToUse = selectionModel.hasSelection() + ? TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()) + : TextRange.create(0, editor.getDocument().getTextLength()); + new RearrangeCodeProcessor(project, file, Collections.singleton(rangeToUse)).run(); } } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java index d680e8a7e173..50582bdf9f90 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java @@ -24,7 +24,6 @@ import com.intellij.ui.ColorUtil; import com.intellij.ui.Gray; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.tabs.TabInfo; -import com.intellij.ui.tabs.TabsUtil; import com.intellij.ui.tabs.UiDecorator; import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.ui.tabs.impl.TabLabel; @@ -75,7 +74,7 @@ public class int _y = effectiveBounds.y + insets.top + 3; int _width = effectiveBounds.width - insets.left - insets.right; int _height = effectiveBounds.height - insets.top - insets.bottom - 3; - _height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + _height -= getActiveTabUnderlineHeight(); if (dark) { g2d.setPaint(UIUtil.getGradientPaint(_x, _y, ColorUtil.shift(UIUtil.getListBackground(), 1.3), _x, _y + effectiveBounds.height, UIUtil.getPanelBackground())); g2d.fillRect(_x, _y, _width, _height); @@ -122,7 +121,7 @@ public class Rectangle rectangle; int y = r2.y + insets.top; int height = maxLength - insets.top - insets.bottom; - height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + height -= getActiveTabUnderlineHeight(); rectangle = new Rectangle(maxOffset, y, r2.width - maxOffset - insets.left - insets.right, height); @@ -194,7 +193,7 @@ public class shape.insets = shape.path.transformInsets(getLayoutInsets()); shape.labelPath = shape.path.createTransform(r); - shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1); + shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(getActiveTabUnderlineHeight() - 1); shape.labelTopY = shape.labelPath.getY() + shape.labelPath.deltaY(1); shape.labelLeftX = shape.labelPath.getX(); shape.labelRightX = shape.labelPath.getMaxX() - shape.labelPath.deltaX(1); @@ -210,8 +209,8 @@ public class int lastX = shape.path.getWidth() - shape.path.deltaX(shape.insets.right); shape.path.lineTo(lastX, shape.labelBottomY); - shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1)); - shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1)); + shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(getActiveTabUnderlineHeight() - 1)); + shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(getActiveTabUnderlineHeight() - 1)); shape.path.closePath(); shape.fillPath = shape.path.copy(); @@ -298,7 +297,7 @@ public class @Override public Dimension getPreferredSize() { Dimension result = super.getPreferredSize(); - result.height += TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + result.height += myTabs.getActiveTabUnderlineHeight(); return result; } } diff --git a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java index 077c41e477ff..10bf53bce6bb 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java @@ -47,6 +47,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.containers.WeakList; +import com.intellij.util.ui.ButtonlessScrollBarUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -825,7 +826,7 @@ public class EditorWindowImpl extends UserDataHolderBase implements EditorWindow } @Override - public void registerScrollBarRepaintCallback(@Nullable RepaintCallback callback) { + public void registerScrollBarRepaintCallback(@Nullable ButtonlessScrollBarUI.ScrollbarRepaintCallback callback) { myDelegate.registerScrollBarRepaintCallback(callback); } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index 026032dccc02..046f0db57912 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -71,7 +71,6 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; -import com.intellij.xml.util.XmlStringUtil; import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -733,6 +732,22 @@ public class SingleInspectionProfilePanel extends JPanel { TreeUtil.sort(myRoot, new InspectionsConfigTreeComparator()); } + private boolean readHTML(String text) { + try { + myBrowser.read(new StringReader(text), null); + return true; + } + catch (IOException ignored) { + return false; + } + } + + private String toHTML(String text) { + final HintHint hintHint = new HintHint(myBrowser, new Point(0, 0)); + hintHint.setFont(UIUtil.getLabelFont()); + return HintUtil.prepareHintText(text, hintHint); + } + private void updateOptionsAndDescriptionPanel(final TreePath... paths) { if (mySelectedProfile == null || paths == null || paths.length == 0) { return; @@ -748,18 +763,8 @@ public class SingleInspectionProfilePanel extends JPanel { final Descriptor defaultDescriptor = singleNode.getDefaultDescriptor(); final String description = defaultDescriptor.loadDescription(); try { - final HintHint hintHint = new HintHint(myBrowser, new Point(0, 0)); - hintHint.setFont(myBrowser.getFont()); - myBrowser - .read(new StringReader(SearchUtil.markup(HintUtil.prepareHintText(description, hintHint), myProfileFilter.getFilter())), null); - } - catch (IOException e2) { - try { - //noinspection HardCodedStringLiteral - myBrowser.read(new StringReader(XmlStringUtil.wrapInHtml("" + UNDER_CONSTRUCTION + "")), null); - } - catch (IOException e1) { - //Can't be + if (!readHTML(SearchUtil.markup(toHTML(description), myProfileFilter.getFilter()))) { + readHTML(toHTML("" + UNDER_CONSTRUCTION + "")); } } catch (Throwable t) { @@ -771,12 +776,7 @@ public class SingleInspectionProfilePanel extends JPanel { } else { - try { - myBrowser.read(new StringReader("Multiple inspections are selected. You can edit them as a single inspection."), null); - } - catch (IOException e1) { - //Can't be - } + readHTML(toHTML("Multiple inspections are selected. You can edit them as a single inspection.")); } myOptionsPanel.removeAll(); @@ -952,12 +952,7 @@ public class SingleInspectionProfilePanel extends JPanel { private void initOptionsAndDescriptionPanel() { myOptionsPanel.removeAll(); - try { - myBrowser.read(new StringReader(EMPTY_HTML), null); - } - catch (IOException e1) { - //Can't be - } + readHTML(EMPTY_HTML); myOptionsPanel.validate(); myOptionsPanel.repaint(); } diff --git a/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java b/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java index 695bad005135..f0c00907ceaa 100644 --- a/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java +++ b/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java @@ -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) { diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java index 43f06bff2850..5b10dbfe2b43 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java @@ -26,7 +26,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.tabs.JBTabsPosition; import com.intellij.ui.tabs.TabInfo; -import com.intellij.ui.tabs.TabsUtil; import com.intellij.ui.tabs.impl.singleRow.ScrollableSingleRowLayout; import com.intellij.ui.tabs.impl.singleRow.SingleRowLayout; import com.intellij.ui.tabs.impl.table.TableLayout; @@ -98,9 +97,11 @@ public class JBEditorTabs extends JBTabsImpl { @Override public boolean hasUnderline() { - return true; + return isSingleRow(); } + + protected void doPaintInactive(Graphics2D g2d, boolean leftGhostExists, TabLabel label, @@ -116,14 +117,14 @@ public class JBEditorTabs extends JBTabsImpl { if ((!isSingleRow() /* for multiline */) || (isSingleRow() && isHorizontalTabs())) { if (isSingleRow() && getPosition() == JBTabsPosition.bottom) { - _y += TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + _y += getActiveTabUnderlineHeight(); } else { if (isSingleRow()) { - _height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + _height -= getActiveTabUnderlineHeight(); } else { TabInfo info = label.getInfo(); if (((TableLayout)getEffectiveLayout()).isLastRow(info)) { - _height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + _height -= getActiveTabUnderlineHeight(); } } } @@ -131,7 +132,19 @@ public class JBEditorTabs extends JBTabsImpl { final boolean vertical = getTabsPosition() == JBTabsPosition.left || getTabsPosition() == JBTabsPosition.right; final Color tabColor = label.getInfo().getTabColor(); + final Composite oldComposite = g2d.getComposite(); + //if (label != getSelectedLabel()) { + // g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.9f)); + //} getPainter().doPaintInactive(g2d, effectiveBounds, _x, _y, _width, _height, tabColor, row, column, vertical); + //g2d.setComposite(oldComposite); + } + + + + @Override + public int getActiveTabUnderlineHeight() { + return hasUnderline() ? super.getActiveTabUnderlineHeight() : 1; } JBEditorTabsPainter getPainter() { @@ -186,9 +199,9 @@ public class JBEditorTabs extends JBTabsImpl { int y = r2.y + insets.top; int height = maxLength - insets.top - insets.bottom; if (getTabsPosition() == JBTabsPosition.bottom) { - y = r2.height - height - insets.top + TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + y = r2.height - height - insets.top + getActiveTabUnderlineHeight(); } else { - height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + height -= getActiveTabUnderlineHeight(); } rectangle = new Rectangle(maxOffset, y, r2.width - maxOffset - insets.left - insets.right, height); @@ -229,7 +242,7 @@ public class JBEditorTabs extends JBTabsImpl { shape.insets = shape.path.transformInsets(getLayoutInsets()); shape.labelPath = shape.path.createTransform(getSelectedLabel().getBounds()); - shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1); + shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(getActiveTabUnderlineHeight() - 1); shape.labelTopY = shape.labelPath.getY() + (getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom ? shape.labelPath.deltaY(1) : 0) ; shape.labelLeftX = shape.labelPath.getX() + (getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom ? 0 : shape.labelPath.deltaX( @@ -247,8 +260,8 @@ public class JBEditorTabs extends JBTabsImpl { int lastX = shape.path.getWidth() - shape.path.deltaX(shape.insets.right); shape.path.lineTo(lastX, shape.labelBottomY); - shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1)); - shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1)); + shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(getActiveTabUnderlineHeight() - 1)); + shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(getActiveTabUnderlineHeight() - 1)); shape.path.closePath(); shape.fillPath = shape.path.copy(); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 4c6ecada830a..97c158e08d9f 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -345,6 +345,10 @@ public class JBTabsImpl extends JComponent return this; } + public int getActiveTabUnderlineHeight() { + return TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + } + public boolean isEditorTabs() { return false; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java index a360c4e9294f..8a0aa2b39473 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java @@ -53,7 +53,7 @@ public class TabLabel extends JPanel { private boolean myCentered; private final Wrapper myLabelPlaceholder = new Wrapper(false); - private final JBTabsImpl myTabs; + protected final JBTabsImpl myTabs; private BufferedImage myInactiveStateImage; private Rectangle myLastPaintedInactiveImageBounds; @@ -241,7 +241,12 @@ public class TabLabel extends JPanel { } }); + final Composite oldComposite = ((Graphics2D)g).getComposite(); + if (myTabs instanceof JBEditorTabs && !myTabs.isSingleRow() && myTabs.getSelectedInfo() != myInfo) { + ((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f)); + } super.paint(g); + ((Graphics2D)g).setComposite(oldComposite); doTranslate(new PairConsumer() { @Override @@ -253,7 +258,7 @@ public class TabLabel extends JPanel { protected int getNonSelectedOffset() { if (myTabs.isEditorTabs() && (myTabs.isSingleRow() || ((TableLayout)myTabs.getEffectiveLayout()).isLastRow(getInfo()))) { - return -TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2 + 1; + return -myTabs.getActiveTabUnderlineHeight() / 2 + 1; } return 1; } @@ -275,7 +280,7 @@ public class TabLabel extends JPanel { switch (pos) { case top: case bottom: - if (myTabs.hasUnderline()) size.height += TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1; + if (myTabs.hasUnderline()) size.height += myTabs.getActiveTabUnderlineHeight() - 1; break; case left: case right: diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java index 6bd2e1aa52bf..ca8bb535f046 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java @@ -18,7 +18,6 @@ package com.intellij.ui.tabs.impl.singleRow; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.tabs.JBTabsPosition; import com.intellij.ui.tabs.TabInfo; -import com.intellij.ui.tabs.TabsUtil; import com.intellij.ui.tabs.impl.*; import org.jetbrains.annotations.Nullable; @@ -50,8 +49,8 @@ public class SingleRowLayout extends TabLayout { protected int getIconY(Rectangle iconRec) { final int shift; switch (myTabs.getTabsPosition()) { - case bottom: shift = TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; break; - case top: shift = -(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2); break; + case bottom: shift = myTabs.getActiveTabUnderlineHeight(); break; + case top: shift = -(myTabs.getActiveTabUnderlineHeight() / 2); break; default: shift = 0; } return super.getIconY(iconRec) + shift; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java index 9b313783dea7..af45cf9b1b0d 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java @@ -16,7 +16,6 @@ package com.intellij.ui.tabs.impl.table; import com.intellij.ui.tabs.TabInfo; -import com.intellij.ui.tabs.TabsUtil; import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.ui.tabs.impl.LayoutPassInfo; import com.intellij.ui.tabs.impl.TabLabel; @@ -103,10 +102,10 @@ public class TableLayout extends TabLayout { toMove.add(data.table.get(i)); } - for (TableRow eachMove : toMove) { - data.table.remove(eachMove); - data.table.add(0, eachMove); - } + //for (TableRow eachMove : toMove) { + // data.table.remove(eachMove); + // data.table.add(0, eachMove); + //} return data; @@ -131,7 +130,7 @@ public class TableLayout extends TabLayout { int eachY = insets.top; int eachX; int row = 0; - final int tabUnderlineFix = myTabs.isEditorTabs() ? TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT : 0; + final int tabUnderlineFix = myTabs.isEditorTabs() ? myTabs.getActiveTabUnderlineHeight() : 0; for (TableRow eachRow : data.table) { eachX = insets.left; diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java index 9cd99e474c65..a816efde21c5 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java @@ -91,7 +91,8 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { private Animator myMacScrollbarFadeAnimator; private double myMacScrollbarFadeLevel = 0; private boolean myMacScrollbarHidden; - + + private ScrollbarRepaintCallback myRepaintCallback; protected ButtonlessScrollBarUI() { myAdjustmentListener = new AdjustmentListener() { @@ -264,6 +265,43 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { } } + /** + * This is overridden only to increase the invalid area. + * This ensures that whole track will be repainted in case of installed callback + */ + @Override + protected void setThumbBounds(int x, int y, int width, int height) { + if (myRepaintCallback == null) { + super.setThumbBounds(x, y, width, height); + } + else { + /* If the thumbs bounds haven't changed, we're done. + */ + if ((thumbRect.x == x) && + (thumbRect.y == y) && + (thumbRect.width == width) && + (thumbRect.height == height)) { + return; + } + + /* Update thumbRect, and repaint the union of x,y,w,h and + * the old thumbRect. + */ + int minX = Math.min(x, trackRect.x); + int minY = Math.min(y, trackRect.y); + int maxX = Math.max(x + width, trackRect.x + trackRect.width); + int maxY = Math.max(y + height, trackRect.y + trackRect.height); + + thumbRect.setBounds(x, y, width, height); + scrollbar.repaint(minX, minY, maxX - minX, maxY - minY); + + // Once there is API to determine the mouse location this will need + // to be changed. + setThumbRollover(false); + } + } + + @Override protected ModelListener createModelListener() { return new ModelListener() { @@ -615,6 +653,10 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { else { g.drawLine(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y); } + + if (myRepaintCallback != null) { + myRepaintCallback.call(g); + } } @Override @@ -774,6 +816,10 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { return myMacScrollbarHidden && Registry.is("editor.distraction.free.mode"); } + public void registerRepaintCallback(ScrollbarRepaintCallback callback) { + myRepaintCallback = callback; + } + private static class EmptyButton extends JButton { private EmptyButton() { setFocusable(false); @@ -795,4 +841,8 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { return getMaximumSize(); } } + + public interface ScrollbarRepaintCallback { + void call(Graphics g); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/EditorPlace.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/EditorPlace.java index 7e24e92c5cf1..52d46d0df04b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/EditorPlace.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/EditorPlace.java @@ -32,15 +32,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.plaf.ScrollBarUI; import java.awt.*; -import java.util.*; +import java.util.ArrayList; import java.util.List; /** * The container for an {@link Editor}, which is added then to {@link com.intellij.openapi.diff.impl.util.ThreePanels}. */ -public class EditorPlace extends JComponent implements Disposable, EditorEx.RepaintCallback { +public class EditorPlace extends JComponent implements Disposable, ButtonlessScrollBarUI.ScrollbarRepaintCallback { private static final Logger LOG = Logger.getInstance(EditorPlace.class); @NotNull private final MergePanel2.DiffEditorState myState; @@ -58,121 +57,57 @@ public class EditorPlace extends JComponent implements Disposable, EditorEx.Repa } @Override - public void paint(Graphics g) { - super.paint(g); + public void call(Graphics g) { paintThis(g); } - public void call(Graphics g) { - repaintScrollbar(); - } - - private void repaintScrollbar() { - if (myEditor == null || myColumn != MergePanelColumn.BASE) { - return; // we draw above the scrollbar only in the central column - } - Component editorComponent = myEditor.getComponent(); - JScrollBar scrollBar = myEditor.getScrollPane().getVerticalScrollBar(); - repaint(editorComponent.getWidth() - scrollBar.getWidth(), 0, scrollBar.getWidth(), scrollBar.getHeight()); - } - private void paintThis(Graphics g) { - if (myEditor != null) { - ArrayList polygons = DividerPolygon.createVisiblePolygons(myMergePanel.getSecondEditingSide(), FragmentSide.SIDE1, - DiffDivider.MERGE_DIVIDER_POLYGONS_OFFSET); - for (DividerPolygon polygon : polygons) { - int startY = polygon.getTopLeftY(); - int endY = polygon.getBottomLeftY(); - int height = endY - startY; + if (myEditor == null) return; + // painting only above the central scrollbar, because painting on edge scrollbars is not needed, and there are error stripes + if (myColumn != MergePanelColumn.BASE) return; - if (height == 0) { // draw at least a one-pixel line (e.g. for insertion or deletion), as it is done in highlighters - height = 1; - } + int offset = DiffDivider.MERGE_SCROLL_DIVIDER_POLYGONS_OFFSET; + ArrayList polygons = + DividerPolygon.createVisiblePolygons(myMergePanel.getSecondEditingSide(true), FragmentSide.SIDE1, offset); + for (DividerPolygon polygon : polygons) { + int startY = polygon.getTopLeftY(); + int endY = polygon.getBottomLeftY(); + int height = endY - startY; - drawPolygonAboveScrollBar((Graphics2D)g, startY, height, polygon.getColor(), polygon.isApplied()); + if (height == 0) { // draw at least a one-pixel line (e.g. for insertion or deletion), as it is done in highlighters + height = 1; } + + drawPolygon((Graphics2D)g, startY, height, polygon.getColor(), polygon.isApplied()); } } - private void drawPolygonAboveScrollBar(@NotNull Graphics2D g, int startY, int height, @NotNull Color color, boolean applied) { - // painting only above the central scrollbar, because painting on edge scrollbars is not needed, and there are error stripes - if (myColumn != MergePanelColumn.BASE) { - return; - } - - g.setColor(color); - JScrollBar scrollBar = myEditor.getScrollPane().getVerticalScrollBar(); - int startX = scrollBar.getX(); - int endX = startX + scrollBar.getWidth() - 1; - - Rectangle thumb = calcThumbBounds(scrollBar); + private void drawPolygon(@NotNull Graphics2D g, int startY, int height, @NotNull Color color, boolean applied) { + int scrollbarWidth = myEditor.getScrollPane().getVerticalScrollBar().getWidth(); + int startX = 0; + int endX = startX + scrollbarWidth - 1; int endY = startY + height; + + g.setColor(color); if (!applied) { if (height > 2) { - fillRectAboveScrollBar(g, startX, startY, scrollBar.getWidth(), height, thumb); + g.fillRect(startX, startY, scrollbarWidth, height); Color framingColor = DiffUtil.getFramingColor(color); - if (outsideBounds(startY, thumb)) { - UIUtil.drawLine(g, startX, startY, endX, startY, null, framingColor); - } - if (outsideBounds(endY, thumb)) { - UIUtil.drawLine(g, startX, endY, endX, endY, null, framingColor); - } + UIUtil.drawLine(g, startX, startY, endX, startY, null, framingColor); + UIUtil.drawLine(g, startX, endY, endX, endY, null, framingColor); } else { - if (outsideBounds(startY, thumb)) { - DiffUtil.drawDoubleShadowedLine(g, startX, endX, startY, color); - } + DiffUtil.drawDoubleShadowedLine(g, startX, endX, startY, color); } } else { - if (outsideBounds(startY, thumb)) { - UIUtil.drawBoldDottedLine(g, startX, endX, startY, null, color, false); - } - if (outsideBounds(endY, thumb)) { - UIUtil.drawBoldDottedLine(g, startX, endX, endY, null, color, false); - } + UIUtil.drawBoldDottedLine(g, startX, endX, startY, null, color, false); + UIUtil.drawBoldDottedLine(g, startX, endX, endY, null, color, false); } } - private static void fillRectAboveScrollBar(Graphics2D g, int startX, int startY, int width, int height, Rectangle thumb) { - int endY = startY + height; - int thumbEndY = thumb == null ? 0 : thumb.y + thumb.height; // it's for further readability (could have a 2-level ifs for the variable) - if (thumb == null) { - g.fillRect(startX, startY, width, height); - } - else if (outsideBounds(startY, thumb) && !outsideBounds(endY, thumb)) { - g.fillRect(startX, startY, width, thumb.y - startY); - } - else if (!outsideBounds(startY, thumb) && outsideBounds(endY, thumb)) { - g.fillRect(startX, thumbEndY, width, endY - thumbEndY); - } - else if (startY < thumb.y && endY > thumbEndY) { // surrounding the thumb - g.fillRect(startX, startY, width, thumb.y - startY); - g.fillRect(startX, thumbEndY, width, endY - thumbEndY); - } - else if (outsideBounds(startY, thumb) && outsideBounds(endY, thumb)) { // outside without intersection - g.fillRect(startX, startY, width, height); - } - } - - private static boolean outsideBounds(int y, @Nullable Rectangle rectangle) { - if (rectangle == null) { - return true; - } - return y < rectangle.y || y > rectangle.y + rectangle.height; - } - - @Nullable - private static Rectangle calcThumbBounds(JScrollBar scrollBar) { - ScrollBarUI scrollBarUI = scrollBar.getUI(); - if (scrollBarUI instanceof ButtonlessScrollBarUI) { - return ((ButtonlessScrollBarUI)scrollBarUI).getThumbBounds(); - } - return null; - } - public void addNotify() { if (myEditor != null) { super.addNotify(); @@ -249,6 +184,7 @@ public class EditorPlace extends JComponent implements Disposable, EditorEx.Repa public interface EditorListener { void onEditorCreated(EditorPlace place); + void onEditorReleased(Editor releasedEditor); } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DiffDivider.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DiffDivider.java index e9c3168e401c..010aa8d7c6bd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DiffDivider.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DiffDivider.java @@ -29,6 +29,7 @@ import java.awt.*; public class DiffDivider extends JComponent { public static final int MERGE_DIVIDER_POLYGONS_OFFSET = 1; + public static final int MERGE_SCROLL_DIVIDER_POLYGONS_OFFSET = 2; private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.util.DiffDivider"); private final Editor[] myEditors = new Editor[2]; private final FragmentSide myLeftSide; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java index 62064a0b1a49..8752e13681b8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java @@ -32,6 +32,7 @@ import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ui.ButtonlessScrollBarUI; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -262,10 +263,5 @@ public interface EditorEx extends Editor { * @param callback callback which will be called from the {@link javax.swing.JComponent#paint(java.awt.Graphics)} method of * the editor vertical scrollbar. */ - void registerScrollBarRepaintCallback(@Nullable RepaintCallback callback); - - interface RepaintCallback { - void call(Graphics g); - } - + void registerScrollBarRepaintCallback(@Nullable ButtonlessScrollBarUI.ScrollbarRepaintCallback callback); } 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 ed2bcd3be7fb..7e803c59438c 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 @@ -597,7 +597,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } @Override - public void registerScrollBarRepaintCallback(@Nullable RepaintCallback callback) { + public void registerScrollBarRepaintCallback(@Nullable ButtonlessScrollBarUI.ScrollbarRepaintCallback callback) { myVerticalScrollBar.registerRepaintCallback(callback); } @@ -2724,12 +2724,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int visibleLine = clip.y / lineHeight; - // The main idea is that there is a possible case that we need to perform painting starting from soft-wrapped logical line. - // We may want to skip necessary number of visual lines then. Hence, we remember logical position that corresponds to the starting - // visual line in order to use it for further processing. As soon as necessary number of visual lines is skipped, logical - // position is expected to be set to null as an indication that no soft wrap-introduced visual lines should be skipped on - // current painting iteration. - Ref logicalPosition = new Ref(clipStartPosition); int startLine = clipStartPosition.line; int start = clipStartOffset; @@ -2737,7 +2731,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (startLine == 0 && myPrefixText != null) { position.x = drawStringWithSoftWraps(g, new CharArrayCharSequence(myPrefixText), 0, myPrefixText.length, position, clip, myPrefixAttributes.getEffectColor(), myPrefixAttributes.getEffectType(), - myPrefixAttributes.getFontType(), myPrefixAttributes.getForegroundColor(), logicalPosition, + myPrefixAttributes.getFontType(), myPrefixAttributes.getForegroundColor(), -1, PAINT_NO_WHITESPACE); } if (startLine >= myDocument.getLineCount() || startLine < 0) { @@ -2773,7 +2767,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start); if (collapsedFolderAt == null) { drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor, - effectType, fontType, currentColor, logicalPosition, context); + effectType, fontType, currentColor, clipStartOffset, context); final VirtualFile file = getVirtualFile(); if (myProject != null && file != null && !isOneLineMode()) { int offset = position.x; @@ -2789,7 +2783,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi info.getEffectType() == null ? effectType : info.getEffectType(), info.getFontType(), info.getColor() == null ? currentColor : info.getColor(), - logicalPosition, context); + clipStartOffset, context); } } } @@ -2820,7 +2814,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (softWrap != null) { position.x = drawStringWithSoftWraps( g, chars, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, clip, effectColor, effectType, - fontType, currentColor, logicalPosition, context + fontType, currentColor, clipStartOffset, context ); } int foldingXStart = position.x; @@ -2833,7 +2827,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } else { position.x = drawStringWithSoftWraps(g, chars, start, Math.min(hEnd, lEnd - lIterator.getSeparatorLength()), position, clip, - effectColor, effectType, fontType, currentColor, logicalPosition, context); + effectColor, effectType, fontType, currentColor, clipStartOffset, context); } iterationState.advance(); @@ -2856,7 +2850,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (collapsedFolderAt != null) { int foldingXStart = position.x; int foldingXEnd = drawStringWithSoftWraps( - g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, fontType, currentColor, logicalPosition, + g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, fontType, currentColor, clipStartOffset, PAINT_NO_WHITESPACE); BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, foldingXEnd, getLineHeight(), effectColor, effectType); // myBorderEffect.collapsedFolderReached(g, this); @@ -3084,15 +3078,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi EffectType effectType, @JdkConstants.FontStyle int fontType, Color fontColor, - @NotNull Ref startDrawingLogicalPosition, + int startDrawingOffset, WhitespacePaintingStrategy context) { return drawStringWithSoftWraps(g, text, 0, text.length(), position, clip, effectColor, effectType, - fontType, fontColor, startDrawingLogicalPosition, context); + fontType, fontColor, startDrawingOffset, context); } private int drawStringWithSoftWraps(@NotNull Graphics g, final CharSequence text, - final int start, + int start, final int end, @NotNull Point position, @NotNull Rectangle clip, @@ -3100,49 +3094,26 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi EffectType effectType, @JdkConstants.FontStyle int fontType, Color fontColor, - @NotNull Ref startDrawingLogicalPosition, + int startDrawingOffset, WhitespacePaintingStrategy context) { - int startToUse = start; - - // 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 need to skip necessary number of visual lines then. - int softWrapLinesToSkip = 0; - if (startDrawingLogicalPosition.get() != null) { - softWrapLinesToSkip = startDrawingLogicalPosition.get().softWrapLinesOnCurrentLogicalLine; - } - SoftWrap lastSkippedSoftWrap = null; - if (softWrapLinesToSkip > 0) { - List softWraps = getSoftWrapModel().getSoftWrapsForLine(startDrawingLogicalPosition.get().line); - for (SoftWrap softWrap : softWraps) { - softWrapLinesToSkip--; // Assuming that soft wrap has a single line feed all the time - if (softWrapLinesToSkip <= 0) { - lastSkippedSoftWrap = softWrap; - startToUse = softWrap.getStart(); - break; - } - } - } - startToUse = Math.max(startToUse, start); - - if (startToUse >= end && getSoftWrapModel().getSoftWrap(startToUse) == null) { + if (start >= end && getSoftWrapModel().getSoftWrap(start) == null) { return position.x; } - startDrawingLogicalPosition.set(null); // Given 'end' offset is exclusive though SoftWrapModel.getSoftWrapsForRange() uses inclusive end offset. // Hence, we decrement it if necessary. Please note that we don't do that if start is equal to end. That is the case, // for example, for soft-wrapped collapsed fold region - we need to draw soft wrap before it. int softWrapRetrievalEndOffset = end; - if (startToUse < end) { + if (start < end) { softWrapRetrievalEndOffset--; } outer: - for (SoftWrap softWrap : getSoftWrapModel().getSoftWrapsForRange(startToUse, softWrapRetrievalEndOffset)) { + for (SoftWrap softWrap : getSoftWrapModel().getSoftWrapsForRange(start, softWrapRetrievalEndOffset)) { char[] softWrapChars = softWrap.getChars(); CharArrayCharSequence softWrapSeq = new CharArrayCharSequence(softWrapChars); - if (softWrap.equals(lastSkippedSoftWrap)) { + if (softWrap.getStart() == startDrawingOffset) { // If we are here that means that we are located on soft wrap-introduced visual line just after soft wrap. Hence, we need // to draw soft wrap indent if any and 'after soft wrap' sign. int i = CharArrayUtil.lastIndexOf(softWrapChars, '\n', 0, softWrapChars.length); @@ -3157,13 +3128,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } // Draw token text before the wrap. - if (softWrap.getStart() > startToUse) { + if (softWrap.getStart() > start) { position.x = drawString( - g, text, startToUse, softWrap.getStart(), position, clip, null, null, fontType, fontColor, context + g, text, start, softWrap.getStart(), position, clip, null, null, fontType, fontColor, context ); } - startToUse = softWrap.getStart(); + start = softWrap.getStart(); // We don't draw every soft wrap symbol one-by-one but whole visual line. Current variable holds index that points // to the first soft wrap symbol that is not drawn yet. @@ -3201,7 +3172,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } position.x += mySoftWrapModel.paint(g, SoftWrapDrawingType.AFTER_SOFT_WRAP, position.x, position.y, getLineHeight()); } - return position.x = drawString(g, text, startToUse, end, position, clip, effectColor, effectType, fontType, fontColor, context); + return position.x = drawString(g, text, start, end, position, clip, effectColor, effectType, fontType, fontColor, context); } private int drawString(@NotNull Graphics g, @@ -4808,7 +4779,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi class MyScrollBar extends JBScrollBar implements IdeGlassPane.TopComponent { @NonNls private static final String APPLE_LAF_AQUA_SCROLL_BAR_UI_CLASS = "apple.laf.AquaScrollBarUI"; private ScrollBarUI myPersistentUI; - @Nullable private RepaintCallback myRepaintCallback; private MyScrollBar(@JdkConstants.AdjustableOrientation int orientation) { super(orientation); @@ -4833,9 +4803,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi @Override public void paint(@NotNull Graphics g) { super.paint(g); - if (myRepaintCallback != null) { - myRepaintCallback.call(g); - } } /** @@ -4906,8 +4873,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return myEditorComponent.getScrollableBlockIncrement(vr, SwingConstants.VERTICAL, direction); } - public void registerRepaintCallback(@Nullable RepaintCallback callback) { - myRepaintCallback = callback; + public void registerRepaintCallback(@Nullable ButtonlessScrollBarUI.ScrollbarRepaintCallback callback) { + if (myPersistentUI instanceof ButtonlessScrollBarUI) { + ((ButtonlessScrollBarUI)myPersistentUI).registerRepaintCallback(callback); + } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java index 8a9031986ef8..d4b7b96e5006 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java @@ -117,7 +117,7 @@ public class ModifierKeyDoubleClickHandler { resetState(); return false; } - if (ourOtherKeyWasPressed.get() && Clock.getTime() - ourLastTimePressed.get() < 500) { + if (myActionKeyCode == -1 && ourOtherKeyWasPressed.get() && Clock.getTime() - ourLastTimePressed.get() < 500) { resetState(); return false; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java index 17883b2493fe..6a326f1a70d4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java @@ -612,7 +612,12 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom } frame.addWindowListener(myActivationListener); - + frame.addComponentListener(new ComponentAdapter() { + @Override + public void componentMoved(@NotNull ComponentEvent e) { + updateFrameBounds(frame); + } + }); myEventDispatcher.getMulticaster().frameCreated(frame); return frame; @@ -778,7 +783,21 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom return null; } + int extendedState = updateFrameBounds(frame); + Rectangle rectangle = myFrameBounds; final Element frameElement = new Element(FRAME_ELEMENT); + frameElement.setAttribute(X_ATTR, Integer.toString(rectangle.x)); + frameElement.setAttribute(Y_ATTR, Integer.toString(rectangle.y)); + frameElement.setAttribute(WIDTH_ATTR, Integer.toString(rectangle.width)); + frameElement.setAttribute(HEIGHT_ATTR, Integer.toString(rectangle.height)); + + if (!(frame.isInFullScreen() && SystemInfo.isAppleJvm)) { + frameElement.setAttribute(EXTENDED_STATE_ATTR, Integer.toString(extendedState)); + } + return frameElement; + } + + private int updateFrameBounds(IdeFrameImpl frame) { int extendedState = frame.getExtendedState(); if (SystemInfo.isMacOSLion) { @SuppressWarnings("deprecation") ComponentPeer peer = frame.getPeer(); @@ -792,16 +811,10 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom boolean usePreviousBounds = isMaximized && myFrameBounds != null && frame.getBounds().contains(new Point((int)myFrameBounds.getCenterX(), (int)myFrameBounds.getCenterY())); - Rectangle rectangle = usePreviousBounds ? myFrameBounds : frame.getBounds(); - frameElement.setAttribute(X_ATTR, Integer.toString(rectangle.x)); - frameElement.setAttribute(Y_ATTR, Integer.toString(rectangle.y)); - frameElement.setAttribute(WIDTH_ATTR, Integer.toString(rectangle.width)); - frameElement.setAttribute(HEIGHT_ATTR, Integer.toString(rectangle.height)); - - if (!(frame.isInFullScreen() && SystemInfo.isAppleJvm)) { - frameElement.setAttribute(EXTENDED_STATE_ATTR, Integer.toString(extendedState)); + if (!usePreviousBounds) { + myFrameBounds = frame.getBounds(); } - return frameElement; + return extendedState; } @Override diff --git a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java index fe041c5ea02b..cfea2dfb0d8e 100644 --- a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java @@ -65,11 +65,11 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants { maxOffset++; g2d.setPaint(UIUtil.getPanelBackground()); if (getFirstTabOffset() > 0) { - g2d.fillRect(clip.x, clip.y, clip.x + getFirstTabOffset() - 1, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT); + g2d.fillRect(clip.x, clip.y, clip.x + getFirstTabOffset() - 1, clip.y + maxLength - getActiveTabUnderlineHeight()); } - g2d.fillRect(clip.x + maxOffset, clip.y, clip.width - maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT); + g2d.fillRect(clip.x + maxOffset, clip.y, clip.width - maxOffset, clip.y + maxLength - getActiveTabUnderlineHeight()); g2d.setPaint(new JBColor(Gray._181, UIUtil.getPanelBackground())); - g2d.drawLine(clip.x + maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT, clip.x + clip.width, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT); + g2d.drawLine(clip.x + maxOffset, clip.y + maxLength - getActiveTabUnderlineHeight(), clip.x + clip.width, clip.y + maxLength - getActiveTabUnderlineHeight()); g2d.setPaint(UIUtil.getPanelBackground()); g2d.drawLine(clip.x, clip.y + maxLength, clip.width, clip.y + maxLength); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUiProperties.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUiProperties.java index 1db1181dfb3b..933ae718b05e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUiProperties.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUiProperties.java @@ -43,6 +43,7 @@ public class VcsLogUiProperties implements PersistentStateComponent RECENTLY_FILTERED_USER_GROUPS = new ArrayDeque(); public Deque RECENTLY_FILTERED_BRANCH_GROUPS = new ArrayDeque(); } @@ -126,6 +127,14 @@ public class VcsLogUiProperties implements PersistentStateComponent users = new ArrayList(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 8f7b10b33363..9f7153427509 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -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() { @Override diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 85bc266dc3c9..55d4d6a900ff 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -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(""); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index f1d1eba2bc35..0a69398735ee 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -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 "" + ((VirtualFile)at).getPresentableUrl() + "
Click to " + (myUI.isShowRootNames() ? "collapse" : "expand") + ""; } } 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 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; } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index a97679b164d3..813d3b8cc165 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -42,6 +42,7 @@ import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowId; @@ -381,13 +382,21 @@ public class XDebugSessionImpl implements XDebugSession { private > void handleBreakpoint(final XBreakpointHandler handler, final B b, final boolean register, final boolean temporary) { - if (register && isBreakpointActive(b)) { - synchronized (myRegisteredBreakpoints) { - myRegisteredBreakpoints.put(b, new CustomizedBreakpointPresentation()); + if (register) { + boolean active = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + return isBreakpointActive(b); + } + }); + if (active) { + synchronized (myRegisteredBreakpoints) { + myRegisteredBreakpoints.put(b, new CustomizedBreakpointPresentation()); + } + handler.registerBreakpoint(b); } - handler.registerBreakpoint(b); } - if (!register) { + else { boolean removed; synchronized (myRegisteredBreakpoints) { removed = myRegisteredBreakpoints.remove(b) != null; diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index d579be95e6cb..7b7bfabf73c8 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -61,7 +61,7 @@ import static org.jetbrains.plugins.github.util.GithubUtil.setVisibleEnabled; */ public class GithubRebaseAction extends DumbAwareAction { private static final Logger LOG = GithubUtil.LOG; - private static final String CANNOT_PERFORM_GITHUB_REBASE = "Can't perform github rebase"; + private static final String CANNOT_PERFORM_GITHUB_REBASE = "Can't perform GitHub rebase"; public GithubRebaseAction() { super("Rebase my GitHub fork", "Rebase your GitHub forked repository relative to the origin", GithubIcons.Github_icon); @@ -165,7 +165,7 @@ public class GithubRebaseAction extends DumbAwareAction { if (!repositoryInfo.isFork() || repositoryInfo.getParent() == null) { GithubNotifications.showWarningURL(project, CANNOT_PERFORM_GITHUB_REBASE, "GitHub repository ", "'" + repositoryInfo.getName() + "'", - " is not a forked one", repositoryInfo.getHtmlUrl()); + " is not a fork", repositoryInfo.getHtmlUrl()); return null; } @@ -188,7 +188,7 @@ public class GithubRebaseAction extends DumbAwareAction { @NotNull ProgressIndicator indicator) { final String remoteUrl = GithubUtil.findGithubRemoteUrl(gitRepository); if (remoteUrl == null) { - GithubNotifications.showError(project, CANNOT_PERFORM_GITHUB_REBASE, "Can't find github remote"); + GithubNotifications.showError(project, CANNOT_PERFORM_GITHUB_REBASE, "Can't find GitHub remote"); return null; } final GithubFullPath userAndRepo = GithubUrlUtil.getUserAndRepositoryFromRemoteUrl(remoteUrl);