--- /dev/null
+package org.simantics.spreadsheet.ui;\r
+\r
+import java.awt.Graphics;\r
+import java.awt.Insets;\r
+import java.awt.Component;\r
+import java.awt.Color;\r
+\r
+import javax.swing.Icon;\r
+import javax.swing.border.EmptyBorder;\r
+\r
+import org.simantics.ui.colors.Colors;\r
+\r
+public class SheetBorder extends EmptyBorder\r
+{\r
+ private static final long serialVersionUID = 1L;\r
+ protected boolean bottomColor;\r
+ protected boolean rightColor;\r
+ \r
+ final Color NONE = Colors.awt(Colors.rgb(0.9,0.9,0.9));\r
+ \r
+\r
+\r
+ /**\r
+ * Creates a matte border with the specified insets and color.\r
+ * @param top the top inset of the border\r
+ * @param left the left inset of the border\r
+ * @param bottom the bottom inset of the border\r
+ * @param right the right inset of the border\r
+ * @param matteColor the color rendered for the border\r
+ */\r
+ public SheetBorder(int top, int left, int bottom, int right, boolean bottomColor, boolean rightColor) {\r
+ super(top, left, bottom, right);\r
+ this.bottomColor = bottomColor;\r
+ this.rightColor = rightColor;\r
+ }\r
+\r
+ /**\r
+ * Paints the matte border.\r
+ */\r
+ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {\r
+ \r
+ Insets insets = getBorderInsets(c);\r
+ Color oldColor = g.getColor();\r
+ g.translate(x, y);\r
+\r
+ boolean same = bottomColor == rightColor;\r
+ \r
+ if(same) {\r
+ \r
+ g.setColor(bottomColor ? Color.BLACK : NONE);\r
+ g.fillRect(0, height - insets.bottom, 2 + width - insets.left, insets.bottom);\r
+ g.fillRect(width - insets.right, 0, insets.right, height - insets.bottom + 2);\r
+ \r
+ } else {\r
+ \r
+ // Not the same color - paint black on top\r
+\r
+ if(bottomColor) {\r
+ // Black bottom - no right\r
+ g.setColor(NONE);\r
+ g.fillRect(width - insets.right, 0, insets.right, height - insets.bottom + 2);\r
+ g.setColor(Color.BLACK);\r
+ g.fillRect(0, height - insets.bottom, 2 + width - insets.left, insets.bottom);\r
+ } else {\r
+ // Black right - no bottom\r
+ g.setColor(NONE);\r
+ g.fillRect(0, height - insets.bottom, 2 + width - insets.left, insets.bottom);\r
+ g.setColor(Color.BLACK);\r
+ g.fillRect(width - insets.right, 0, insets.right, height - insets.bottom + 2);\r
+ }\r
+ \r
+ }\r
+ \r
+ g.translate(-x, -y);\r
+ g.setColor(oldColor);\r
+\r
+ }\r
+\r
+ /**\r
+ * Reinitialize the insets parameter with this Border's current Insets.\r
+ * @param c the component for which this border insets value applies\r
+ * @param insets the object to be reinitialized\r
+ * @since 1.3\r
+ */\r
+ public Insets getBorderInsets(Component c, Insets insets) {\r
+ return computeInsets(insets);\r
+ }\r
+\r
+ /**\r
+ * Returns the insets of the border.\r
+ * @since 1.3\r
+ */\r
+ public Insets getBorderInsets() {\r
+ return computeInsets(new Insets(0,0,0,0));\r
+ }\r
+\r
+ /* should be protected once api changes area allowed */\r
+ private Insets computeInsets(Insets insets) {\r
+ insets.left = left;\r
+ insets.top = top;\r
+ insets.right = right;\r
+ insets.bottom = bottom;\r
+ return insets;\r
+ }\r
+\r
+ /**\r
+ * Returns the color used for tiling the border or null\r
+ * if a tile icon is being used.\r
+ * @since 1.3\r
+ */\r
+ public Color getMatteColor() {\r
+ return NONE;\r
+ }\r
+\r
+ /**\r
+ * Returns the icon used for tiling the border or null\r
+ * if a solid color is being used.\r
+ * @since 1.3\r
+ */\r
+ public Icon getTileIcon() {\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Returns whether or not the border is opaque.\r
+ */\r
+ public boolean isBorderOpaque() {\r
+ // If a tileIcon is set, then it may contain transparent bits\r
+ return true;\r
+ }\r
+\r
+}\r