Parcourir la source

fix: G4NodeProperties
new: CustomBevelBorder

Ranides Atterwim il y a 2 ans
Parent
commit
38cbf3331e

+ 12 - 6
assira.commons/src/main/java/net/ranides/assira/grammar/properties/G4NodeProperties.java

@@ -6,6 +6,7 @@ import net.ranides.assira.grammar.G4Node;
 import java.util.Collections;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.WeakHashMap;
 import java.util.WeakHashMap;
 
 
 /**
 /**
@@ -33,7 +34,8 @@ public class G4NodeProperties {
     }
     }
 
 
     public static Map<Object, Object> getAll(G4Node node) {
     public static Map<Object, Object> getAll(G4Node node) {
-        return Collections.unmodifiableMap(getReadableScope(node));
+        Object unwrapped = node.unwrap();
+        return Collections.unmodifiableMap(getReadableScope(unwrapped));
     }
     }
 
 
     public static boolean has(G4Node node, String name) {
     public static boolean has(G4Node node, String name) {
@@ -73,15 +75,18 @@ public class G4NodeProperties {
     }
     }
 
 
     public static void put(G4Node tree, String name, Object value) {
     public static void put(G4Node tree, String name, Object value) {
-        getWritableScope(tree).put(name, value);
+        Object unwrapped = tree.unwrap();
+        getWritableScope(unwrapped).put(name, value);
     }
     }
 
 
     public static <V> void put(G4Node tree, G4NodeProperty<V> key, V value) {
     public static <V> void put(G4Node tree, G4NodeProperty<V> key, V value) {
-        getWritableScope(tree).put(key, value);
+        Object unwrapped = tree.unwrap();
+        getWritableScope(unwrapped).put(key, value);
     }
     }
 
 
     public static void put(G4Node tree, G4NodeProperties values) {
     public static void put(G4Node tree, G4NodeProperties values) {
-        getWritableScope(tree).data.putAll(values.data);
+        Object unwrapped = tree.unwrap();
+        getWritableScope(unwrapped).data.putAll(values.data);
     }
     }
 
 
     public void put(String name, Object value) {
     public void put(String name, Object value) {
@@ -96,10 +101,11 @@ public class G4NodeProperties {
         Object output = null;
         Object output = null;
         G4Node current = node;
         G4Node current = node;
         while (current != null && output == null) {
         while (current != null && output == null) {
-            output = getReadableScope(current).get(key);
+            Object unwrapped = current.unwrap();
+            output = getReadableScope(unwrapped).get(key);
             current = current.parent().orElse(null);
             current = current.parent().orElse(null);
         }
         }
-        return Ref.ofNullable(output);
+        return Ref.ofNullable(output, () -> new NoSuchElementException("Node " + node + " has no property " + key));
     }
     }
 
 
     private static <T> G4NodeProperties getWritableScope(T reference) {
     private static <T> G4NodeProperties getWritableScope(T reference) {

+ 1 - 1
assira.ui/src/main/antlr4/net/ranides/grammars/generated/CssGrammar.g4

@@ -21,7 +21,7 @@ border
 
 
 borderCSS
 borderCSS
     : borderCSS_Style WS color WS borderSize
     : borderCSS_Style WS color WS borderSize
-    | borderCSS_Style (WS  borderSize)? (WS color)?
+    | borderCSS_Style (WS borderSize)? (WS color)?
     | color WS borderCSS_Style WS borderSize
     | color WS borderCSS_Style WS borderSize
     | color (WS borderSize)? (WS borderCSS_Style)?
     | color (WS borderSize)? (WS borderCSS_Style)?
     | borderSize WS borderCSS_Style WS color
     | borderSize WS borderCSS_Style WS color

+ 9 - 112
assira.ui/src/main/java/net/ranides/assira/ui/primitives/BorderParser.java

@@ -1,9 +1,9 @@
 package net.ranides.assira.ui.primitives;
 package net.ranides.assira.ui.primitives;
 
 
+import net.ranides.assira.generic.Ref;
 import net.ranides.assira.generic.ValueUtils;
 import net.ranides.assira.generic.ValueUtils;
 
 
 import javax.swing.*;
 import javax.swing.*;
-import javax.swing.border.AbstractBorder;
 import javax.swing.border.Border;
 import javax.swing.border.Border;
 import java.awt.*;
 import java.awt.*;
 import java.util.Optional;
 import java.util.Optional;
@@ -39,18 +39,18 @@ public class BorderParser {
                         BorderFactory.createLineBorder(color, size1)
                         BorderFactory.createLineBorder(color, size1)
                     );
                     );
                 case "outset":
                 case "outset":
-                    return createBevelBorder(size, color, BevelBorderV2.RAISED);
+                    return createBevelBorder(size, color, CustomBevelBorder.RAISED);
                 case "inset":
                 case "inset":
-                    return createBevelBorder(size, color, BevelBorderV2.LOWERED);
+                    return createBevelBorder(size, color, CustomBevelBorder.LOWERED);
                 case "groove":
                 case "groove":
                     return BorderFactory.createCompoundBorder(
                     return BorderFactory.createCompoundBorder(
-                        createBevelBorder(size, color, BevelBorderV2.LOWERED),
-                        createBevelBorder(size, color, BevelBorderV2.RAISED)
+                        createBevelBorder(size, color, CustomBevelBorder.LOWERED),
+                        createBevelBorder(size, color, CustomBevelBorder.RAISED)
                     );
                     );
                 case "ridge":
                 case "ridge":
                     return BorderFactory.createCompoundBorder(
                     return BorderFactory.createCompoundBorder(
-                        createBevelBorder(size, color, BevelBorderV2.RAISED),
-                        createBevelBorder(size, color, BevelBorderV2.LOWERED)
+                        createBevelBorder(size, color, CustomBevelBorder.RAISED),
+                        createBevelBorder(size, color, CustomBevelBorder.LOWERED)
                     );
                     );
             }
             }
         }
         }
@@ -58,111 +58,8 @@ public class BorderParser {
         throw new IllegalArgumentException("Unsupported border style: " + expression);
         throw new IllegalArgumentException("Unsupported border style: " + expression);
     }
     }
 
 
-    private static Border createBevelBorder(Integer size, Color color, int lowered) {
-        if(size == null && color ==null) {
-            return BorderFactory.createBevelBorder(lowered);
-        }
-        if(color ==null) {
-            return new BevelBorderV2(lowered, size);
-        } else {
-            return new BevelBorderV2(lowered, ValueUtils.or(size, 1), color.brighter(), color.darker());
-        }
-    }
-
-    @SuppressWarnings("serial")
-    public static class BevelBorderV2 extends AbstractBorder
-    {
-        public static final int RAISED  = 0;
-        public static final int LOWERED = 1;
-
-        protected int etchType;
-
-        protected int size;
-        protected Color highlight;
-        protected Color shadow;
-
-        public BevelBorderV2(int etchType)    {
-            this(etchType, 1, null, null);
-        }
-
-        public BevelBorderV2(int etchType, int size)    {
-            this(etchType, size, null, null);
-        }
-
-        public BevelBorderV2(int etchType, int size, Color highlight, Color shadow)    {
-            this.etchType = etchType;
-            this.size = size;
-            this.highlight = highlight;
-            this.shadow = shadow;
-        }
-
-        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
-            super.paintBorder(c, g, x, y, width, height);
-
-            int h = height;
-            int w = width;
-            int bw = size;
-
-            Graphics2D g2 = (Graphics2D) g.create();
-            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-            g2.translate(x, y);
-
-            Polygon topPolygon = createPolygon(pt(0, 0), pt(w, 0), pt(w - bw, bw), pt(bw, bw), pt(0, 0));
-            g2.setColor(getLTColor(c));
-            g2.fill(topPolygon);
-
-            Polygon rightPolygon = createPolygon(pt(w , 0), pt(w, h), pt(w - bw , h - bw), pt(w - bw, bw), pt(w, 0));
-            g2.setColor(getRBColor(c));
-            g2.fill(rightPolygon);
-
-            Polygon bottomPolygon = createPolygon(pt(0, h), pt(w, h), pt(w - bw, h - bw), pt(bw, h - bw), pt(0, h));
-            g2.setColor(getRBColor(c));
-            g2.fill(bottomPolygon);
-
-            Polygon leftPolygon = createPolygon(pt(0, 0), pt(0, h), pt(bw, h - bw), pt(bw, bw), pt(0, 0));
-            g2.setColor(getLTColor(c));
-            g2.fill(leftPolygon);
-
-            g2.dispose();
-        }
-
-        private Point pt(int bw, int h) {
-            return new Point(bw, h);
-        }
-
-        private Polygon createPolygon(Point... points) {
-            Polygon polygon = new Polygon();
-            for (Point point : points) {
-                polygon.addPoint(point.x, point.y);
-            }
-            return polygon;
-        }
-
-        @Override
-        public Insets getBorderInsets(Component c, Insets insets) {
-            insets.set(size, size, size, size);
-            return insets;
-        }
-
-        @Override
-        public boolean isBorderOpaque() { return true; }
-
-        private Color getLTColor(Component c)   {
-            return etchType==RAISED ? getHighlightColor(c) : getShadowColor(c);
-        }
-
-        private Color getRBColor(Component c)   {
-            return etchType==RAISED ? getShadowColor(c) : getHighlightColor(c);
-        }
-
-        private Color getHighlightColor(Component c)   {
-            return highlight != null? highlight : c.getBackground().brighter();
-        }
-
-        private Color getShadowColor(Component c)   {
-            return shadow != null? shadow : c.getBackground().darker();
-        }
-
+    private static Border createBevelBorder(Integer size, Color color, int type) {
+        return CustomBevelBorder.newInstance(Ref.ofNullable(size), Ref.ofNullable(color), type);
     }
     }
 
 
 }
 }

+ 30 - 7
assira.ui/src/main/java/net/ranides/assira/ui/primitives/CssParser.java

@@ -3,6 +3,7 @@ package net.ranides.assira.ui.primitives;
 import lombok.Data;
 import lombok.Data;
 import net.ranides.assira.generic.Ref;
 import net.ranides.assira.generic.Ref;
 import net.ranides.assira.grammar.G4Node;
 import net.ranides.assira.grammar.G4Node;
+import net.ranides.assira.grammar.properties.G4NodeProperties;
 import net.ranides.assira.grammar.properties.G4NodeProperty;
 import net.ranides.assira.grammar.properties.G4NodeProperty;
 import net.ranides.assira.ui.helpers.ColorUtils;
 import net.ranides.assira.ui.helpers.ColorUtils;
 import net.ranides.assira.collection.query.CQuery;
 import net.ranides.assira.collection.query.CQuery;
@@ -222,16 +223,21 @@ public class CssParser {
             CssBorderStyle style = node.children("borderCSS_Style").single()
             CssBorderStyle style = node.children("borderCSS_Style").single()
                 .map(v -> BORDER_STYLE.single(v))
                 .map(v -> BORDER_STYLE.single(v))
                 .orElse(CssBorderStyle.SOLID);
                 .orElse(CssBorderStyle.SOLID);
-            Color color = node.children("color").single()
-                .map(v -> COLOR.single(v))
-                .orElseGet(() -> node.get(COMPONENT).get().getForeground());
-            CssBorderSize size = node.children("size").single()
-                .map(v -> BORDER_SIZE.single(v))
-                .orElseGet(() -> new CssBorderSize(1,1,1,1));
+            Ref<Color> color = node.children("color").single()
+                .map(v -> COLOR.single(v));
+            Ref<CssBorderSize> size = node.children("borderSize").single()
+                .map(v -> BORDER_SIZE.single(v));
 
 
             switch (style) {
             switch (style) {
                 case SOLID:
                 case SOLID:
-                    return BorderFactory.createLineBorder(color, size.left);
+                    return BorderFactory.createLineBorder(
+                        color.orElseGet(() -> node.get(COMPONENT).get().getBackground()),
+                        size.orElse(CssBorderSize.SINGLE).left
+                    );
+                case OUTSET:
+                    return CustomBevelBorder.newInstance(size.map(CssBorderSize::getLeft), color, CustomBevelBorder.RAISED);
+                case INSET:
+                    return CustomBevelBorder.newInstance(size.map(CssBorderSize::getLeft), color, CustomBevelBorder.LOWERED);
                 default:
                 default:
                     throw new UnsupportedOperationException("Unsupported border style: " + style);
                     throw new UnsupportedOperationException("Unsupported border style: " + style);
             }
             }
@@ -275,8 +281,25 @@ public class CssParser {
         }
         }
     }
     }
 
 
+    public static Border border(JComponent component, String value) {
+        try {
+            G4Node node = PARSER.parse("root_border", value);
+            G4NodeProperties.put(node, COMPONENT, component);
+            return BORDER.single(node);
+        } catch (NoSuchElementException | G4Exception e) {
+            throw new IllegalArgumentException("Invalid border: " + value, e);
+        }
+    }
+
     @Data
     @Data
     public static class CssBorderSize {
     public static class CssBorderSize {
+
+        public static final CssBorderSize NONE = new CssBorderSize(1,1,1,1);
+
+        public static final CssBorderSize SINGLE = new CssBorderSize(1,1,1,1);
+
+        public static final CssBorderSize DOUBLE = new CssBorderSize(2,2,2,2);
+
         private final int top;
         private final int top;
         private final int left;
         private final int left;
         private final int bottom;
         private final int bottom;

+ 104 - 0
assira.ui/src/main/java/net/ranides/assira/ui/primitives/CustomBevelBorder.java

@@ -0,0 +1,104 @@
+package net.ranides.assira.ui.primitives;
+
+import net.ranides.assira.generic.Ref;
+
+import javax.swing.*;
+import javax.swing.border.AbstractBorder;
+import javax.swing.border.Border;
+import java.awt.*;
+
+class CustomBevelBorder extends AbstractBorder {
+    public static final int RAISED = 0;
+    public static final int LOWERED = 1;
+
+    private final int etchType;
+    private final int size;
+    private final Color highlight;
+    private final Color shadow;
+
+    protected CustomBevelBorder(int etchType, int size, Color highlight, Color shadow) {
+        this.etchType = etchType;
+        this.size = size;
+        this.highlight = highlight;
+        this.shadow = shadow;
+    }
+
+    public static Border newInstance(Ref<Integer> size, Ref<Color> color, int type) {
+        if(size.isAbsent() && color.isAbsent()) {
+            return BorderFactory.createBevelBorder(type);
+        }
+        if(color.isAbsent()) {
+            return new CustomBevelBorder(type, size.orElse(1), null, null);
+        } else {
+            return new CustomBevelBorder(type, size.orElse(1), color.get().brighter(), color.get().darker());
+        }
+    }
+
+    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+        super.paintBorder(c, g, x, y, width, height);
+
+        int h = height;
+        int w = width;
+        int bw = size;
+
+        Graphics2D g2 = (Graphics2D) g.create();
+        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        g2.translate(x, y);
+
+        Polygon topPolygon = createPolygon(pt(0, 0), pt(w, 0), pt(w - bw, bw), pt(bw, bw), pt(0, 0));
+        g2.setColor(getLTColor(c));
+        g2.fill(topPolygon);
+
+        Polygon rightPolygon = createPolygon(pt(w, 0), pt(w, h), pt(w - bw, h - bw), pt(w - bw, bw), pt(w, 0));
+        g2.setColor(getRBColor(c));
+        g2.fill(rightPolygon);
+
+        Polygon bottomPolygon = createPolygon(pt(0, h), pt(w, h), pt(w - bw, h - bw), pt(bw, h - bw), pt(0, h));
+        g2.setColor(getRBColor(c));
+        g2.fill(bottomPolygon);
+
+        Polygon leftPolygon = createPolygon(pt(0, 0), pt(0, h), pt(bw, h - bw), pt(bw, bw), pt(0, 0));
+        g2.setColor(getLTColor(c));
+        g2.fill(leftPolygon);
+
+        g2.dispose();
+    }
+
+    private static Point pt(int bw, int h) {
+        return new Point(bw, h);
+    }
+
+    private static Polygon createPolygon(Point... points) {
+        Polygon polygon = new Polygon();
+        for (Point point : points) {
+            polygon.addPoint(point.x, point.y);
+        }
+        return polygon;
+    }
+
+    @Override
+    public Insets getBorderInsets(Component c, Insets insets) {
+        insets.set(size, size, size, size);
+        return insets;
+    }
+
+    @Override
+    public boolean isBorderOpaque() {return true;}
+
+    private Color getLTColor(Component c) {
+        return etchType == RAISED ? getHighlightColor(c) : getShadowColor(c);
+    }
+
+    private Color getRBColor(Component c) {
+        return etchType == RAISED ? getShadowColor(c) : getHighlightColor(c);
+    }
+
+    private Color getHighlightColor(Component c) {
+        return highlight != null ? highlight : c.getBackground().brighter();
+    }
+
+    private Color getShadowColor(Component c) {
+        return shadow != null ? shadow : c.getBackground().darker();
+    }
+
+}