Merge remote-tracking branch 'origin/svn' 80/80/1
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Mon, 19 Sep 2016 09:15:51 +0000 (12:15 +0300)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Mon, 19 Sep 2016 09:17:21 +0000 (12:17 +0300)
Change-Id: I6de2fe5c0e54e45498ef01e5ee398325dee1a2a7

bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLPostLexer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/Types.java
bundles/org.simantics.scl.compiler/tests/org/simantics/scl/compiler/tests/ActiveTests.java
bundles/org.simantics.scl.compiler/tests/org/simantics/scl/compiler/tests/scl/EmptyLet.scl [new file with mode: 0644]
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorAlphaGradient.java [new file with mode: 0644]
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorGradient.java

index 6821da83e7014a6d027869b8f111ed87fe103f15..500cf3b20d5a148ed92ad0775ce0d0f487c54c7f 100644 (file)
@@ -187,7 +187,7 @@ stringLiteral
     ;
 
 statements
-    = LBRACE statement (SEMICOLON statement)* RBRACE         # Statements
+    = LBRACE (statement (SEMICOLON statement)*)? RBRACE      # Statements
     ;
 
 statement
index e23a9a17c720c3704745d31b32aca11391f42c26..e3111279029743dda253292caf2b37508c5440fc 100644 (file)
@@ -1,12 +1,12 @@
 /* The following code was generated by JFlex 1.6.1 */\r
 \r
-package org.simantics.scl.compiler.internal.parsing.parser;
-
-import org.simantics.scl.compiler.internal.parsing.Token;
-import org.simantics.scl.compiler.errors.Locations;
-import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
-import gnu.trove.list.array.TIntArrayList;
-
+package org.simantics.scl.compiler.internal.parsing.parser;\r
+\r
+import org.simantics.scl.compiler.internal.parsing.Token;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;\r
+import gnu.trove.list.array.TIntArrayList;\r
+\r
 \r
 /**\r
  * This class is a scanner generated by \r
@@ -562,20 +562,20 @@ public class SCLLexer {
   private int zzFinalHighSurrogate = 0;\r
 \r
   /* user code: */\r
-    public SCLParserOptions options = SCLParserOptions.DEFAULT;
-    int stringStart;
-    TIntArrayList parenCountStack = new TIntArrayList(2);
-    int parenCount = 0;
-    TIntArrayList stateStack = new TIntArrayList(2);
-
-    StringBuffer string = new StringBuffer();
-    
-    private Token sym(int id) {
-        return new Token(id, yychar, yychar+yylength(), yytext());
-    }
-    private Token sym(int id, String text) {
-        return new Token(id, yychar, yychar+yylength(), text);
-    }
+    public SCLParserOptions options = SCLParserOptions.DEFAULT;\r
+    int stringStart;\r
+    TIntArrayList parenCountStack = new TIntArrayList(2);\r
+    int parenCount = 0;\r
+    TIntArrayList stateStack = new TIntArrayList(2);\r
+\r
+    StringBuffer string = new StringBuffer();\r
+    \r
+    private Token sym(int id) {\r
+        return new Token(id, yychar, yychar+yylength(), yytext());\r
+    }\r
+    private Token sym(int id, String text) {\r
+        return new Token(id, yychar, yychar+yylength(), text);\r
+    }\r
 \r
 \r
   /**\r
@@ -900,7 +900,7 @@ public class SCLLexer {
             }\r
             case 278: break;\r
             default:\r
-          {     return sym(SCLTerminals.EOF);
+          {     return sym(SCLTerminals.EOF);\r
  }\r
         }\r
       }\r
@@ -943,15 +943,15 @@ public class SCLLexer {
             }\r
           case 101: break;\r
           case 10: \r
-            { --parenCount;
-                    if(parenCount == 0 && !parenCountStack.isEmpty()) { 
-                       parenCount = parenCountStack.removeAt(parenCountStack.size()-1);
-                       string.setLength(0);
-                       stringStart=yychar;
-                       yybegin(stateStack.removeAt(stateStack.size()-1));
-                       return sym(SCLTerminals.CONTINUE_STRING);
-                    }
-                    else
+            { --parenCount;\r
+                    if(parenCount == 0 && !parenCountStack.isEmpty()) { \r
+                       parenCount = parenCountStack.removeAt(parenCountStack.size()-1);\r
+                       string.setLength(0);\r
+                       stringStart=yychar;\r
+                       yybegin(stateStack.removeAt(stateStack.size()-1));\r
+                       return sym(SCLTerminals.CONTINUE_STRING);\r
+                    }\r
+                    else\r
                        return sym(SCLTerminals.RPAREN);\r
             }\r
           case 102: break;\r
@@ -1036,7 +1036,7 @@ public class SCLLexer {
             }\r
           case 122: break;\r
           case 31: \r
-            { yybegin(YYINITIAL); 
+            { yybegin(YYINITIAL); \r
                     return new Token(SCLTerminals.END_STRING, stringStart, yychar+1, string.toString());\r
             }\r
           case 123: break;\r
@@ -1113,10 +1113,10 @@ public class SCLLexer {
             }\r
           case 141: break;\r
           case 50: \r
-            { parenCountStack.add(parenCount);
-                    parenCount = 1;
-                    stateStack.add(STRING);
-                    yybegin(YYINITIAL); 
+            { parenCountStack.add(parenCount);\r
+                    parenCount = 1;\r
+                    stateStack.add(STRING);\r
+                    yybegin(YYINITIAL); \r
                     return new Token(SCLTerminals.SUSPEND_STRING, stringStart, yychar+1, string.toString());\r
             }\r
           case 142: break;\r
@@ -1129,10 +1129,10 @@ public class SCLLexer {
             }\r
           case 144: break;\r
           case 53: \r
-            { parenCountStack.add(parenCount);
-                    parenCount = 1;
-                    stateStack.add(LONG_STRING);
-                    yybegin(YYINITIAL); 
+            { parenCountStack.add(parenCount);\r
+                    parenCount = 1;\r
+                    stateStack.add(LONG_STRING);\r
+                    yybegin(YYINITIAL); \r
                     return new Token(SCLTerminals.SUSPEND_STRING, stringStart, yychar+1, string.toString());\r
             }\r
           case 145: break;\r
@@ -1145,12 +1145,12 @@ public class SCLLexer {
             }\r
           case 147: break;\r
           case 56: \r
-            { String text = yytext();
+            { String text = yytext();\r
                      return sym(SCLTerminals.ID, text.substring(1, text.length()-1));\r
             }\r
           case 148: break;\r
           case 57: \r
-            { String text = yytext();
+            { String text = yytext();\r
                      return sym(SCLTerminals.SYMBOL, text.substring(1, text.length()-1));\r
             }\r
           case 149: break;\r
@@ -1171,7 +1171,7 @@ public class SCLLexer {
             }\r
           case 153: break;\r
           case 62: \r
-            { yybegin(YYINITIAL); 
+            { yybegin(YYINITIAL); \r
                       return new Token(SCLTerminals.END_STRING, stringStart, yychar+3, string.toString());\r
             }\r
           case 154: break;\r
index f17807cb50b5a65ac8b4185c1df3870340716c06..fe5dac3c46f78e291d2ee254261596d2fdb25b19 100644 (file)
Binary files a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat and b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat differ
index bde7f10b4a46dc525b035823c454f124ad8433f2..ac61c901002bf20854505ed3f45419576468210e 100644 (file)
@@ -13,7 +13,7 @@ public abstract class SCLParser {
     public static final boolean TRACE = false;\r
 \r
     private static final int INITIAL_CAPACITY = 16;\r
-    private static final int STATE_COUNT = 323;\r
+    private static final int STATE_COUNT = 324;\r
     private static final int TERMINAL_COUNT = 79;\r
     private static final int NONTERMINAL_COUNT = 49;\r
     private static final int PRODUCT_COUNT = 126;\r
@@ -21,7 +21,7 @@ public abstract class SCLParser {
     private static final int[] ACTION_ROW_ID = new int[STATE_COUNT];\r
     private static final int[] ACTION_COLUMN_ID = new int[TERMINAL_COUNT];\r
     private static final short[] ACTION_TABLE = new short[5508];\r
-    private static final int[] ERROR_TABLE = new int[798];\r
+    private static final int[] ERROR_TABLE = new int[800];\r
     private static final int[] GOTO_ROW_ID = new int[STATE_COUNT];\r
     private static final int[] GOTO_COLUMN_ID = new int[NONTERMINAL_COUNT];\r
     private static final short[] GOTO_TABLE = new short[1620];\r
@@ -362,19 +362,19 @@ public abstract class SCLParser {
         return parse(0);\r
     }\r
     public Object parseCommands() {\r
-        return parse(308);\r
+        return parse(309);\r
     }\r
     public Object parseImport() {\r
-        return parse(315);\r
+        return parse(316);\r
     }\r
     public Object parseType() {\r
-        return parse(317);\r
+        return parse(318);\r
     }\r
     public Object parseExp() {\r
-        return parse(319);\r
+        return parse(320);\r
     }\r
     public Object parseEquationBlock() {\r
-        return parse(321);\r
+        return parse(322);\r
     }\r
 \r
 \r
@@ -945,7 +945,7 @@ public abstract class SCLParser {
      */\r
     protected abstract Object reduceFieldDescription();\r
     /**\r
-     * statements ::= LBRACE statement (SEMICOLON statement)&#42; RBRACE\r
+     * statements ::= LBRACE (statement (SEMICOLON (statement SEMICOLON)&#42; statement)?)? RBRACE\r
      */\r
     protected abstract Object reduceStatements();\r
     /**\r
index 680be5e35dbd7478ba13e94d20d52eaecd997546..bbf944f1e28b8c84cf78b00895fbca516158e8e4 100644 (file)
@@ -480,8 +480,9 @@ public class SCLParserImpl extends SCLParser {
     @Override
     protected Object reduceStatements() {
         EBlock block = new EBlock();
-        for(int i=1;i<length();i+=2)
-            block.addStatement((Statement)get(i));
+        if(length() > 2)
+            for(int i=1;i<length();i+=2)
+                block.addStatement((Statement)get(i));
         return block;
     }
 
index 4a446e6e2f2027af55c80c9fbd06da7cd30f8200..866fb8c985c4126b6e368746b83c767953c66cda 100644 (file)
@@ -79,6 +79,10 @@ public class SCLPostLexer {
     }
     
     private void push(Token symbol) {
+        /*System.out.println("TOKEN " + symbol.text + " (" + SCLParser.TERMINAL_NAMES[symbol.id] + ")" +
+                " [" 
+                + Locations.beginOf(symbol.location) + ".." 
+                + Locations.endOf(symbol.location) + "]");*/
         if(queueSize == queue.length)
             queue = Arrays.copyOf(queue, queueSize*2);
         queue[queueSize++] = symbol;
@@ -117,8 +121,6 @@ public class SCLPostLexer {
         int symbolEnd = Locations.endOf(symbol.location);
         
         if(INDENTABLE.contains(prevTokenId) && symbolId != SCLTerminals.LBRACE) {
-            if(prevTokenId == SCLTerminals.LET)
-                indentations.add(-1);
             push(new Token(SCLTerminals.LBRACE, symbolStart, symbolStart, "implicit {"));
             int symbolIndentation = symbolStart-lineStart;
             //System.out.println("symbolIndentation = " + symbolIndentation);
@@ -149,6 +151,7 @@ public class SCLPostLexer {
         case SCLTerminals.LPAREN:
         case SCLTerminals.LBRACKET:
         case SCLTerminals.IF:
+        case SCLTerminals.LET:
             indentations.add(-1);
             push(symbol);
             return;
index 5e332742ab29debd7f8c3674c4b2ac38f993448f..5e8c548878e4b10e010cb6fc8f0f7cddc8da18ef 100644 (file)
@@ -154,11 +154,13 @@ public class Types {
      * Get the concrete type pointed to by a chain of type meta-variables.
      */
     public static Type canonical(Type type) {
-        while(type instanceof TMetaVar) {
+        if(type instanceof TMetaVar) {
             TMetaVar metaVar = (TMetaVar)type;
             type = metaVar.ref;
             if(type == null)
                 return metaVar;
+            else
+                return metaVar.ref = canonical(type);
         }
         return type;
     }
index 0b7b52e2938a58cd0926ad8b1c0a50bab5151d17..f9533efeee64222052a7e27ecc8a6c318d66a8f3 100644 (file)
@@ -6,7 +6,7 @@ import org.junit.Test;
 public class ActiveTests extends TestBase {
     
     public ActiveTests() { super("scl"); }
-
+/*
     @Test public void Equations1() { test(); }
     @Test public void MarketModel2() { test(); }
     @Test public void Overloading2() { test(); }
@@ -17,5 +17,8 @@ public class ActiveTests extends TestBase {
     @Ignore
     @Test public void TypeClass2() { test(); }
     @Test public void TypeClassBug2() { test(); }
+  */  
     
+    //@Test public void CityoptSetup() { test(); }
+    @Test public void EmptyLet() { test(); }
 }
diff --git a/bundles/org.simantics.scl.compiler/tests/org/simantics/scl/compiler/tests/scl/EmptyLet.scl b/bundles/org.simantics.scl.compiler/tests/org/simantics/scl/compiler/tests/scl/EmptyLet.scl
new file mode 100644 (file)
index 0000000..68c6623
--- /dev/null
@@ -0,0 +1,9 @@
+import "Prelude"\r
+\r
+ex1 = let in 1\r
+ex2 = let {} in 2\r
+ex3 = let {a=3} in a \r
+\r
+main = ex1 + ex2 + ex3\r
+--\r
+6
\ No newline at end of file
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorAlphaGradient.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorAlphaGradient.java
new file mode 100644 (file)
index 0000000..05635df
--- /dev/null
@@ -0,0 +1,256 @@
+package org.simantics.utils.ui.color;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.widgets.Display;\r
+\r
+public class ColorAlphaGradient extends ColorGradient {\r
+       \r
+       List<Integer> alphaValues;\r
+       \r
+       \r
+       public ColorAlphaGradient() {\r
+               super();\r
+               this.alphaValues = new ArrayList<>();\r
+       }\r
+       \r
+       public ColorAlphaGradient(ColorAlphaGradient copyFrom) {\r
+               super(copyFrom);\r
+               this.alphaValues = copyFrom.alphaValues;\r
+    }\r
+       \r
+       public ColorAlphaGradient(ColorValue array[], int alphaArray[]) {\r
+               super(array);\r
+               if (array.length != alphaArray.length)\r
+                       throw new IllegalArgumentException("Array lenghts do not match.");\r
+               this.alphaValues = new ArrayList<>(alphaArray.length);\r
+               for (int a : alphaArray) {\r
+            alphaValues.add(a);\r
+        }\r
+       }\r
+       \r
+       public ColorAlphaGradient(ColorValue array[], int alphaArray[], int type) {\r
+               super(array, type);\r
+               if (array.length != alphaArray.length)\r
+                       throw new IllegalArgumentException("Array lenghts do not match.");\r
+               this.alphaValues = new ArrayList<>(alphaArray.length);\r
+               for (int a : alphaArray) {\r
+            alphaValues.add(a);\r
+        }\r
+       }\r
+       \r
+       public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues) {\r
+               super(values);\r
+               if (values.size() != alphaValues.size())\r
+                       throw new IllegalArgumentException("Array lenghts do not match.");\r
+               this.alphaValues = new ArrayList<>(alphaValues);\r
+       }\r
+       \r
+       public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues, int type) {\r
+               super(values, type);\r
+               if (values.size() != alphaValues.size())\r
+                       throw new IllegalArgumentException("Array lenghts do not match.");\r
+               this.alphaValues = new ArrayList<>(alphaValues);\r
+       }\r
+       \r
+        /**\r
+     * Interpolates color in RGB space\r
+     * \r
+     * @param value\r
+     * @return\r
+     */\r
+    private byte[] getRGBColor(double value) {\r
+        int index = 1;\r
+        while (values.get(index).getValue() <= value && index < values.size()-1)\r
+            index++;\r
+\r
+        value -= values.get(index - 1).getValue();\r
+        value /= (values.get(index).getValue() - values.get(index - 1).getValue());\r
+        double valuei = 1.0 - value;\r
+        byte color[] = new byte[] {\r
+                (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getR() + valuei * values.get(index - 1).getColor().getR())),\r
+                (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getG() + valuei * values.get(index - 1).getColor().getG())),\r
+                (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getB() + valuei * values.get(index - 1).getColor().getB())),\r
+                (byte) Math.min(255.0, Math.floor(value * alphaValues.get(index)              + valuei * alphaValues.get(index - 1)))};\r
+        return color;\r
+\r
+    }\r
+\r
+    /**\r
+     * Interpolates color in HSV space\r
+     * \r
+     * @param value\r
+     * @return\r
+     */\r
+    private byte[] getHSVColor(double value) {\r
+        int index = 1;\r
+        while (values.get(index).getValue() <= value && index < values.size()-1)\r
+            index++;\r
+\r
+        value -= values.get(index - 1).getValue();\r
+        value /= (values.get(index).getValue() - values.get(index - 1).getValue());\r
+        double valuei = 1.0 - value;\r
+        double h;\r
+        if (Float.isNaN(values.get(index).getColor().getH())) {\r
+            h = values.get(index-1).getColor().getH();\r
+        } else if (Float.isNaN(values.get(index-1).getColor().getH())) {\r
+            h = values.get(index).getColor().getH();\r
+        } else {\r
+            // selecting shortest direction between hues\r
+            float angle = values.get(index).getColor().getH() - values.get(index - 1).getColor().getH();\r
+            if (angle > 180.f)\r
+                angle -= 360.f;\r
+            else if (angle < -180.f)\r
+                angle += 360.f;\r
+            h = values.get(index - 1).getColor().getH() + value * angle;\r
+            if (h > 360.f)\r
+                h -= 360.f;\r
+            else if (h < 0.f)\r
+                h+= 360.f;\r
+        }\r
+        org.simantics.utils.ui.color.Color interpolated = new org.simantics.utils.ui.color.Color(h, value * values.get(index).getColor().getS() + valuei * values.get(index - 1).getColor().getS(),\r
+                value * values.get(index).getColor().getV() + valuei * values.get(index - 1).getColor().getV());\r
+        byte color[] = new byte[] { (byte) interpolated.getR(), (byte) interpolated.getG(), (byte) interpolated.getB(), (byte) Math.min(255.0, Math.floor(value * alphaValues.get(index)              + valuei * alphaValues.get(index - 1)))};\r
+\r
+        return color;\r
+\r
+    }\r
+\r
+    /**\r
+     * <p>\r
+     * Returns gradient in array of bytes. Array is RGB order and int contains 3 * requested size of bytes.\r
+     * </p>\r
+     * <p>\r
+     * If gradient contains only one color array is filled with that color\r
+     * </p>\r
+     * <p>\r
+     * if gradient has no colors array is filled with white\r
+     * </p>\r
+     * @param size number of pixels\r
+     * @return gradient in array of bytes\r
+     */\r
+    public byte[] getGradientArray(int size) {\r
+        byte array[] = new byte[size * 4];\r
+        if (values.size() > 1) {\r
+            for (int i = 0; i < size; i++) {\r
+                int index = i * 4;\r
+                double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) i / (double) size;\r
+                byte color[];\r
+                if (type == RGB)\r
+                    color = getRGBColor(value);\r
+                else\r
+                    color = getHSVColor(value);\r
+                array[index] = color[0];\r
+                array[index + 1] = color[1];\r
+                array[index + 2] = color[2];\r
+                array[index + 3] = color[3];\r
+            }\r
+        } else if (values.size() == 1) {\r
+            byte color[] = new byte[3];\r
+            color[0] = (byte)values.get(0).getColor().getR();\r
+            color[1] = (byte)values.get(0).getColor().getG();\r
+            color[2] = (byte)values.get(0).getColor().getB();\r
+            color[3] = (byte)(int)alphaValues.get(0);\r
+            for (int i = 0; i < size; i++) {\r
+                int index = i * 3;\r
+                array[index] = color[0];\r
+                array[index + 1] = color[1];\r
+                array[index + 2] = color[2];\r
+                array[index + 3] = color[3];\r
+            }\r
+        } else {\r
+            for (int i = 0; i < size; i++) {\r
+                int index = i * 4;\r
+                array[index] = (byte)255;\r
+                array[index + 1] = (byte)255;\r
+                array[index + 2] = (byte)255;\r
+                array[index + 3] = (byte)255;\r
+            }\r
+        }\r
+        return array;\r
+    }\r
+\r
+    /**\r
+     * <p>\r
+     * Returns gradient in image.\r
+     * </p>\r
+     * <p>\r
+     * If gradient contains only one color image is filled with that color\r
+     * </p>\r
+     * <p>\r
+     * if gradient has no colors image is filled with white\r
+     * </p>\r
+     * <p>\r
+     * Style must be set to  <code>SWT.HORIZONTAL</code> or <code>SWT.VERTICAL</code>\r
+     * </p>\r
+     * @param size number of pixels\r
+     * @return gradient in array of bytes\r
+     */\r
+    \r
+    public Image getGradientImage(int width, int height, int style) {\r
+        Image image = new Image(Display.getCurrent(), width, height);\r
+        GC gc = new GC(image);\r
+        gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));\r
+        gc.fillRectangle(0, 0, width, height);\r
+        if (values.size() > 1) {\r
+            if (SWT.HORIZONTAL == (style | SWT.HORIZONTAL)) {\r
+                for (int x = 0; x < width; x++) {\r
+                    double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) x / (double) (width - 1);\r
+                    byte byteColor[];\r
+                    if (type == RGB)\r
+                        byteColor = getRGBColor(value);\r
+                    else\r
+                        byteColor = getHSVColor(value);\r
+                    Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);\r
+                    gc.setForeground(color);\r
+                    gc.drawLine(x, 0, x, height);\r
+                    color.dispose();\r
+                }\r
+            } else if (SWT.VERTICAL == (style | SWT.VERTICAL)){\r
+                for (int y = 0; y < height; y++) {\r
+                    double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) y\r
+                            / (double) (height - 1);\r
+                    byte byteColor[];\r
+                    if (type == RGB)\r
+                        byteColor = getRGBColor(value);\r
+                    else\r
+                        byteColor = getHSVColor(value);\r
+                    Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);\r
+                    gc.setForeground(color);\r
+                    gc.drawLine(0, y, width, y);\r
+                    color.dispose();\r
+                }\r
+            } else {\r
+                gc.dispose();\r
+                image.dispose();\r
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);\r
+            }\r
+        } else if (values.size() == 1) {\r
+            Color color = new Color(Display.getCurrent(), values.get(0).getColor().getR(), values.get(0).getColor().getG(), values.get(0).getColor().getB(), alphaValues.get(0));      \r
+            gc.setBackground(color);\r
+            gc.fillRectangle(0, 0, width, height);\r
+            color.dispose();\r
+        } else {\r
+            gc.fillRectangle(0, 0, width, height);\r
+        }\r
+        gc.dispose();\r
+        return image;\r
+    }\r
+    \r
+    @Override\r
+    public boolean equals(Object obj) {\r
+       if (super.equals(obj)) {\r
+               ColorAlphaGradient cg = (ColorAlphaGradient)obj;\r
+               return alphaValues.containsAll(cg.alphaValues);\r
+       } else {\r
+               return false;\r
+       }\r
+    }\r
+\r
+}\r
index a08010f20076294e0917b15b0ba3822ad4c5bcf3..56195ce0c4cd5c643d89d513e25a59d761e76226 100644 (file)
@@ -38,9 +38,9 @@ public class ColorGradient {
 \r
     public static final int HSV = 1;\r
 \r
-    private ArrayList<ColorValue> values;\r
+    protected ArrayList<ColorValue> values;\r
 \r
-    private int type;\r
+    protected int type;\r
     \r
     public ColorGradient() {\r
         this.values = new ArrayList<ColorValue>();\r
@@ -59,7 +59,7 @@ public class ColorGradient {
     }\r
 \r
     public ColorGradient(ColorValue array[]) {\r
-        this.values = new ArrayList<ColorValue>();\r
+        this.values = new ArrayList<ColorValue>(array.length);\r
         for (ColorValue c : array) {\r
             values.add(c);\r
         }\r
@@ -295,7 +295,10 @@ public class ColorGradient {
     \r
     @Override\r
     public boolean equals(Object obj) {\r
-        if (!(obj instanceof ColorGradient)) return false;\r
+       if (obj == null)\r
+               return false;\r
+       if (obj.getClass() != getClass())\r
+               return false;\r
         ColorGradient cg = (ColorGradient) obj;\r
         if (cg.type != type) return false;\r
         if (values.size()!=cg.values.size()) return false;\r