From 472ba62bbace45421436620aaf315470e0f3eccf Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Mon, 6 Aug 2012 10:34:26 +0200 Subject: [PATCH] PropertyTable: displaying categories, JBTable: fixed renderer with striped tables UIUtil: drawHeader method --- .../intellij/ui/SimpleColoredComponent.java | 10 +- .../src/com/intellij/ui/table/JBTable.java | 2 +- .../com/intellij/designer/model/Property.java | 2 +- .../designer/propertyTable/PropertyTable.java | 171 ++++++++++++++---- .../openapi/wm/impl/ToolWindowHeader.java | 25 +-- .../util/src/com/intellij/util/ui/UIUtil.java | 34 +++- 6 files changed, 176 insertions(+), 68 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index 7fb68fdfd301..a3c59359ebd1 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -456,13 +456,17 @@ public class SimpleColoredComponent extends JComponent implements Accessible { } - protected void doPaintTextBackground(Graphics2D g, int offset) { + private void doPaintTextBackground(Graphics2D g, int offset) { if (isOpaque() || shouldDrawBackground()) { - g.setColor(getBackground()); - g.fillRect(offset, 0, getWidth() - offset, getHeight()); + paintBackground(g, offset, getWidth() - offset, getHeight()); } } + protected void paintBackground(Graphics2D g, int x, int width, int height) { + g.setColor(getBackground()); + g.fillRect(x, 0, width, height); + } + protected void doPaintIcon(Graphics2D g, Icon icon, int offset) { final Container parent = getParent(); Color iconBackgroundColor = null; diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java index 59461c9ad68b..27b6a640bbed 100644 --- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java +++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java @@ -479,7 +479,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component final Color bg = row % 2 == 1 ? getBackground() : UIUtil.getDecoratedRowColor(); final JComponent c = (JComponent)result; final boolean cellSelected = isCellSelected(row, column); - if (!cellSelected || (!hasFocus() && !getSelectionBackground().equals(c.getBackground()))) { + if (!cellSelected) { c.setOpaque(true); c.setBackground(bg); for (Component child : c.getComponents()) { diff --git a/platform/platform-impl/src/com/intellij/designer/model/Property.java b/platform/platform-impl/src/com/intellij/designer/model/Property.java index fb39f7f264e3..f15ecff33e07 100644 --- a/platform/platform-impl/src/com/intellij/designer/model/Property.java +++ b/platform/platform-impl/src/com/intellij/designer/model/Property.java @@ -56,7 +56,7 @@ public abstract class Property { ////////////////////////////////////////////////////////////////////////////////////////// @Nullable - public String getCategory() { + public String getGroup() { return null; } diff --git a/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java b/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java index bec2abd37e1d..3176b6d1007e 100644 --- a/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java +++ b/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java @@ -19,6 +19,7 @@ import com.intellij.designer.model.ErrorInfo; import com.intellij.designer.model.PropertiesContainer; import com.intellij.designer.model.Property; import com.intellij.designer.model.PropertyContext; +import com.intellij.designer.propertyTable.renderers.LabelPropertyRenderer; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -60,9 +61,21 @@ import java.util.List; */ public abstract class PropertyTable extends JBTable { private static final Logger LOG = Logger.getInstance("#com.intellij.designer.propertyTable.PropertyTable"); + private static final Comparator GROUP_COMPARATOR = new Comparator() { + @Override + public int compare(String o1, String o2) { + return StringUtil.compare(o1, o2, true); + } + }; + private static final Comparator PROPERTY_COMPARATOR = new Comparator() { + @Override + public int compare(Property o1, Property o2) { + return StringUtil.compare(o1.getName(), o2.getName(), true); + } + }; private boolean mySorted; - private boolean myShowCategories; + private boolean myShowGroups; private boolean myShowExpertProperties; private final AbstractTableModel myModel = new PropertyTableModel(); @@ -111,13 +124,13 @@ public abstract class PropertyTable extends JBTable { return mySorted; } - public boolean isShowCategories() { - return myShowCategories; + public void setShowGroups(boolean showGroups) { + myShowGroups = showGroups; + update(); } - public void setShowCategories(boolean showCategories) { - myShowCategories = showCategories; - update(); + public boolean isShowGroups() { + return myShowGroups; } public void showExpert(boolean showExpert) { @@ -270,7 +283,7 @@ public abstract class PropertyTable extends JBTable { Property selection = initialSelection != null ? initialSelection : getSelectionProperty(); myContainers = new ArrayList(containers); fillProperties(); - sortProperties(); + sortPropertiesAndCreateGroups(); myModel.fireTableDataChanged(); restoreSelection(selection); @@ -280,25 +293,46 @@ public abstract class PropertyTable extends JBTable { } } - private void sortProperties() { - if (!mySorted && !myShowCategories) return; + private void sortPropertiesAndCreateGroups() { + if (!mySorted && !myShowGroups) return; Collections.sort(myProperties, new Comparator() { @Override public int compare(Property o1, Property o2) { - if (myShowCategories) { - String c1 = o1.getCategory(); - String c2 = o2.getCategory(); - int result = StringUtil.compare(c1, c2, true); - if (result != 0) { - if (c1 == null) return 1; - if (c2 == null) return -1; - return result; - } + if (myShowGroups) { + int result = getGroupComparator().compare(o1.getGroup(), o2.getGroup()); + if (result != 0) return result; } - return mySorted ? StringUtil.compare(o1.getName(), o2.getName(), true) : 0; + return mySorted ? getPropertyComparator().compare(o1, o2) : 0; } }); + + if (myShowGroups) { + for (int i = 0; i < myProperties.size() - 1; i++) { + Property prev = i == 0 ? null : myProperties.get(i - 1); + Property each = myProperties.get(i); + + String eachGroup = each.getGroup(); + String prevGroup = prev == null ? null : prev.getGroup(); + + if (prevGroup != null || eachGroup != null) { + if (!StringUtil.equalsIgnoreCase(eachGroup, prevGroup)) { + myProperties.add(i, new GroupProperty(each.getGroup())); + i++; + } + } + } + } + } + + @NotNull + protected Comparator getGroupComparator() { + return GROUP_COMPARATOR; + } + + @NotNull + protected Comparator getPropertyComparator() { + return PROPERTY_COMPARATOR; } private void restoreSelection(Property selection) { @@ -327,7 +361,14 @@ public abstract class PropertyTable extends JBTable { getSelectionModel().setSelectionInterval(indexToSelect, indexToSelect); } else if (getRowCount() > 0) { - getSelectionModel().setSelectionInterval(0, 0); + indexToSelect = 0; + for (int i = 0; i < myProperties.size(); i++) { + if (!(myProperties.get(i) instanceof GroupProperty)) { + indexToSelect = i; + break; + } + } + getSelectionModel().setSelectionInterval(indexToSelect, indexToSelect); } TableUtil.scrollSelectionToVisible(this); } @@ -1036,13 +1077,31 @@ public abstract class PropertyTable extends JBTable { protected abstract TextAttributesKey getErrorAttributes(@NotNull HighlightSeverity severity); private class PropertyCellRenderer implements TableCellRenderer { - private final ColoredTableCellRenderer myRenderer; + private final ColoredTableCellRenderer myCellRenderer; + private final ColoredTableCellRenderer myGroupRenderer; private PropertyCellRenderer() { - myRenderer = new ColoredTableCellRenderer() { + myCellRenderer = new MyCellRenderer(); + myGroupRenderer = new MyCellRenderer() { + private boolean mySelected; + public boolean myDrawTopLine; + + + @Override protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) { - setPaintFocusBorder(false); - setFocusBorderAroundIcon(true); + super.customizeCellRenderer(table, value, selected, hasFocus, row, column); + mySelected = selected; + myDrawTopLine = row > 0; + } + + @Override + protected void paintBackground(Graphics2D g, int x, int width, int height) { + if (mySelected) { + super.paintBackground(g, x, width, height); + } + else { + UIUtil.drawHeader(g, x, width, height, true, myDrawTopLine); + } } }; } @@ -1057,11 +1116,24 @@ public abstract class PropertyTable extends JBTable { column = table.convertColumnIndexToModel(column); Property property = (Property)value; Color background = table.getBackground(); - boolean isDefault = true; Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); boolean tableHasFocus = focusOwner != null && SwingUtilities.isDescendingFrom(focusOwner, table); + ColoredTableCellRenderer renderer = property instanceof GroupProperty ? myGroupRenderer : myCellRenderer; + + renderer.getTableCellRendererComponent(table, value, selected, cellHasFocus, row, column); + renderer.setBackground(selected ? UIUtil.getTreeSelectionBackground(tableHasFocus) : background); + + if (property instanceof GroupProperty) { + renderer.setIpad(new Insets(0, 5, 0, 0)); + if (column == 0) { + renderer.append(property.getName()); + } + return renderer; + } + + boolean isDefault = true; try { isDefault = isDefault(property); } @@ -1069,13 +1141,9 @@ public abstract class PropertyTable extends JBTable { LOG.debug(e); } - myRenderer.clear(); + renderer.clear(); if (column == 0) { - myRenderer.getTableCellRendererComponent(table, value, selected, cellHasFocus, row, column); - - myRenderer.setBackground(selected ? UIUtil.getTreeSelectionBackground(tableHasFocus) : background); - SimpleTextAttributes attr = SimpleTextAttributes.REGULAR_ATTRIBUTES; if (!selected && !isDefault) { @@ -1101,31 +1169,31 @@ public abstract class PropertyTable extends JBTable { attr = attr.derive(attr.getStyle() | style, template.getFgColor(), template.getBgColor(), template.getWaveColor()); } - myRenderer.append(property.getName(), attr); + renderer.append(property.getName(), attr); Icon icon = UIUtil.getTreeNodeIcon(isExpanded(property), selected, tableHasFocus); boolean hasChildren = !getChildren(property).isEmpty(); - myRenderer.setIcon(hasChildren ? icon : null); + renderer.setIcon(hasChildren ? icon : null); Pair indents = getBeforeIconAndAfterIndents(property, icon); int indent = indents.first; if (hasChildren) { - myRenderer.setIconTextGap(indents.second); + renderer.setIconTextGap(indents.second); } else { indent += icon.getIconWidth() + indents.second; } - myRenderer.setIpad(new Insets(0, indent, 0, 0)); + renderer.setIpad(new Insets(0, indent, 0, 0)); - return myRenderer; + return renderer; } else { try { - PropertyRenderer renderer = property.getRenderer(); + PropertyRenderer valueRenderer = property.getRenderer(); JComponent component = - renderer.getComponent(getCurrentComponent(), getPropertyContext(), getValue(property), selected, tableHasFocus); + valueRenderer.getComponent(getCurrentComponent(), getPropertyContext(), getValue(property), selected, tableHasFocus); component.setBackground(selected ? UIUtil.getTreeSelectionBackground(tableHasFocus) : background); component.setFont(table.getFont()); @@ -1138,11 +1206,34 @@ public abstract class PropertyTable extends JBTable { } catch (Exception e) { LOG.debug(e); - myRenderer.getTableCellRendererComponent(table, value, selected, cellHasFocus, row, column); - myRenderer.append(formatErrorGettingValueMesage(e.getMessage()), SimpleTextAttributes.ERROR_ATTRIBUTES); - return myRenderer; + renderer.append(formatErrorGettingValueMesage(e.getMessage()), SimpleTextAttributes.ERROR_ATTRIBUTES); + return renderer; } } } + + private class MyCellRenderer extends ColoredTableCellRenderer { + protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) { + setPaintFocusBorder(false); + setFocusBorderAroundIcon(true); + } + } + } + + private static class GroupProperty extends Property { + public GroupProperty(@Nullable String name) { + super(null, StringUtil.notNullize(name)); + } + + @NotNull + @Override + public PropertyRenderer getRenderer() { + return new LabelPropertyRenderer(null); + } + + @Override + public PropertyEditor getEditor() { + return null; + } } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java index cfaeeb6d0b9c..4731278a240b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java @@ -333,28 +333,11 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable { private static BufferedImage drawToBuffer(boolean active, int height, boolean floating) { final int width = 150; - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D _g = image.createGraphics(); + BufferedImage image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + UIUtil.drawHeader(g, 0, width, height, active, true, !floating); + g.dispose(); - _g.setColor(UIUtil.getPanelBackground()); - _g.fillRect(0, 0, width, height); - - _g.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 5), 0, height, new Color(0, 0, 0, 20))); - _g.fillRect(0, 0, width, height); - - _g.setColor(new Color(0, 0, 0, 90)); - if (!floating) _g.drawLine(0, 0, width, 0); - _g.drawLine(0, height - 1, width, height - 1); - - _g.setColor(new Color(255, 255, 255, 100)); - _g.drawLine(0, 1, width, 1); - - if (active) { - _g.setColor(new Color(100, 150, 230, 50)); - _g.fillRect(0, 0, width, height); - } - - _g.dispose(); return image; } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index feec83018d91..3a4bdab93ebb 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1177,8 +1177,8 @@ public class UIUtil { public static void drawRectPickedOut(Graphics2D g, int x, int y, int w, int h) { g.drawLine(x+1, y, x+w-1, y); g.drawLine(x+w, y+1, x+w, y+h-1); - g.drawLine(x+w-1, y+h, x+1, y+h); - g.drawLine(x, y+1, x, y+h-1); + g.drawLine(x + w - 1, y + h, x + 1, y + h); + g.drawLine(x, y + 1, x, y + h - 1); } private static void drawBoringDottedLine(final Graphics2D g, @@ -1226,6 +1226,36 @@ public class UIUtil { g2d.fillRect(0, 0, width, height); } + public static void drawHeader(Graphics g, int x, int width, int height, boolean active, boolean drawTopLine) { + drawHeader(g, x, width, height, active, false, drawTopLine); + } + + public static void drawHeader(Graphics g, + int x, + int width, + int height, + boolean active, + boolean toolWindow, + boolean drawTopLine) { + g.setColor(getPanelBackground()); + g.fillRect(x, 0, width, height); + + ((Graphics2D)g).setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 5), 0, height, new Color(0, 0, 0, 20))); + g.fillRect(x, 0, width, height); + + g.setColor(new Color(0, 0, 0, toolWindow ? 90 : 50)); + if (drawTopLine) g.drawLine(x, 0, width, 0); + g.drawLine(x, height - 1, width, height - 1); + + g.setColor(new Color(255, 255, 255, 100)); + g.drawLine(x, drawTopLine ? 1 : 0, width, drawTopLine ? 1 : 0); + + if (active) { + g.setColor(new Color(100, 150, 230, toolWindow? 50 : 30)); + g.fillRect(x, 0, width, height); + } + } + public static void drawDoubleSpaceDottedLine(final Graphics2D g, final int start, final int end,