1 22 23 24 package net.sourceforge.chart2d; 25 26 27 import java.awt.*; 28 import java.awt.geom.*; 29 import java.util.*; 30 31 32 37 class GraphArea extends Area { 38 39 40 43 static float[] CONTINUOUS = {10.0f, 0.0f}; 44 47 static float[] DASHED = {7.0f, 3.0f}; 48 51 static float[] DOTTED = {3.0f, 3.0f}; 52 55 static int POS = 1; 56 59 static int MIX = 0; 60 63 static int NEG = -1; 64 65 66 static final int COMPONENT = 0; 67 static final int GRAPH = 1; 68 69 70 private int type; 71 private boolean allowComponentAlignment; 72 73 private Rectangle[] xTicks; 74 private Rectangle[] yTicks; 75 private int ticksAlignment; 76 private int[][] graphValues; 77 private int[][] barLowValues; 78 79 private boolean linesThicknessAssociation; 80 private boolean verticalLinesExistence; 81 private Line2D.Double[] verticalLines; 82 private int verticalLinesThicknessModel; 83 private int verticalLinesThickness; 84 private Color verticalLinesColor; 85 private float[] verticalLinesStyle; 86 private BasicStroke verticalLinesStroke; 87 88 private boolean horizontalLinesExistence; 89 private Line2D.Double[] horizontalLines; 90 private int horizontalLinesThicknessModel; 91 private int horizontalLinesThickness; 92 private Color horizontalLinesColor; 93 private float[] horizontalLinesStyle; 94 private BasicStroke horizontalLinesStroke; 95 96 private boolean barsExistence; 97 private int barsThicknessModel; 98 private Color[] barColors; 99 private float barsExcessSpaceFeedbackRatio; 100 private float barsWithinCategoryOverlapRatio; 101 102 private boolean dotsExistence; 103 private int dotsThicknessModel; 104 private Color[] dotColors; 105 private float dotsExcessSpaceFeedbackRatio; 106 private float dotsWithinCategoryOverlapRatio; 107 108 private boolean linesExistence; 109 private int linesThicknessModel; 110 private Color[] lineColors; 111 private boolean linesFillInterior; 112 private int linesFillInteriorBaseValue; 113 private float linesExcessSpaceFeedbackRatio; 114 private float linesWithinCategoryOverlapRatio; 115 116 private boolean outlineComponents; 117 private Color outlineComponentsColor; 118 119 private boolean betweenComponentsGapExistence; 120 private int betweenComponentsGapThicknessModel; 121 122 private float barRoundingRatio; 123 private int roundSide; 124 private int lightSource; 125 private int lightType; 126 private Vector warningRegions; 127 private boolean clip; 128 private boolean componentsColoringByCat; 129 private Color[] componentsColorsByCat; 130 131 private int dataSign; 132 133 private AlphaComposite componentsAlphaComposite; 134 135 private boolean needsUpdate; 136 137 138 142 GraphArea() { 143 144 setType (LABELSBOTTOM); 145 setGraphValues (new int[0][0]); 146 setBarLowValues (new int[0][0]); 147 setAllowComponentAlignment (false); 148 149 setAutoSizes (false, false); 150 setAutoJustifys (false, false); 151 setBackgroundColor (Color.lightGray); 152 setBorderAssociations (false, false, true, true, false, false); 153 setBorderCornerAssociations (LEFT, LEFT, RIGHT, RIGHT); 154 setBorderColors (Color.black, Color.gray, Color.gray, Color.black); 155 156 setXTicks (new Rectangle[0]); 157 setYTicks (new Rectangle[0]); 158 159 setLinesThicknessAssociation (true); 160 setHorizontalLinesExistence (true); 161 setHorizontalLinesThicknessModel (2); 162 setHorizontalLinesStyle (CONTINUOUS); 163 setHorizontalLinesColor (Color.gray); 164 setVerticalLinesExistence (false); 165 setVerticalLinesThicknessModel (2); 166 setVerticalLinesStyle (CONTINUOUS); 167 setVerticalLinesColor (Color.gray); 168 169 setBarsExistence (true); 170 setBarsThicknessModel (10); 171 setBarColors (new Color[0]); 172 setBarsExcessSpaceFeedbackRatio (.75f); 173 setBarsWithinCategoryOverlapRatio (.5f); 174 175 setDotsExistence (false); 176 setDotsThicknessModel (8); 177 setDotColors (new Color[0]); 178 setDotsExcessSpaceFeedbackRatio (0f); 179 setDotsWithinCategoryOverlapRatio (.5f); 180 181 setLinesExistence (false); 182 setLinesThicknessModel (4); 183 setLineColors (new Color[0]); 184 setLinesFillInterior (false); 185 setLinesFillInteriorBaseValue (0); 186 setLinesExcessSpaceFeedbackRatio (0f); 187 setLinesWithinCategoryOverlapRatio (.5f); 188 189 setBetweenComponentsGapExistence (true); 190 setBetweenComponentsGapThicknessModel (2); 191 setLabelsAxisTicksAlignment (BETWEEN); 192 193 setGapExistence (false); 194 setOutlineComponents (true); 195 setOutlineComponentsColor (Color.black); 196 197 setBarRoundingRatio (.25f); 198 setComponentsLightSource (FancyShape.LEFT); 199 setComponentsLightType (COMPONENT); 200 201 setClip (true); 202 setComponentsColoringByCat (false); 203 setComponentsColorsByCat (new Color[0]); 204 205 resetGraphAreaModel (true); 206 needsUpdate = true; 207 } 208 209 210 219 public final void setComponentsAlphaComposite (AlphaComposite a) { 220 221 componentsAlphaComposite = a; 222 needsUpdate = true; 223 } 224 225 226 235 public final AlphaComposite getComponentsAlphaComposite() { 236 return componentsAlphaComposite; 237 } 238 239 240 247 final void setDataSign (int sign) { 248 249 dataSign = sign; 250 needsUpdate = true; 251 } 252 253 254 261 final int getDataSign() { 262 263 return dataSign; 264 } 265 266 267 271 final void setComponentsColoringByCat (boolean b) { 272 needsUpdate = true; 273 componentsColoringByCat = b; 274 } 275 276 277 281 final void setComponentsColorsByCat (Color[] c) { 282 needsUpdate = true; 283 componentsColorsByCat = c; 284 } 285 286 287 291 final void setClip (boolean c) { 292 needsUpdate = true; 293 clip = c; 294 } 295 296 297 301 final void setWarningRegions (Vector v) { 302 warningRegions = v; 303 needsUpdate = true; 304 } 305 306 307 312 final void setBarRoundingRatio (float r) { 313 barRoundingRatio = r; 314 needsUpdate = true; 315 } 316 317 318 326 final void setComponentsLightSource (int s) { 327 lightSource = s; 328 needsUpdate = true; 329 } 330 331 332 340 final void setComponentsLightType (int t) { 341 lightType = t; 342 needsUpdate = true; 343 } 344 345 346 351 final void setOutlineComponents (boolean outline) { 352 353 needsUpdate = true; 354 outlineComponents = outline; 355 } 356 357 358 362 final void setOutlineComponentsColor (Color color) { 363 364 needsUpdate = true; 365 outlineComponentsColor = color; 366 } 367 368 369 376 final void setLabelsAxisTicksAlignment (int alignment) { 377 needsUpdate = true; 378 ticksAlignment = alignment; 379 } 380 381 382 388 final void setType (int type) { 389 390 needsUpdate = true; 391 this.type = type; 392 } 393 394 395 401 final void setAllowComponentAlignment (boolean allow) { 402 403 needsUpdate = true; 404 allowComponentAlignment = allow; 405 } 406 407 408 416 final void setGraphValues (int[][] values) { 417 418 needsUpdate = true; 419 graphValues = values; 420 } 421 422 423 431 final void setBarLowValues (int[][] values) { 432 433 needsUpdate = true; 434 barLowValues = values; 435 } 436 437 438 444 final void setXTicks (Rectangle[] ticks) { 445 446 needsUpdate = true; 447 this.xTicks = ticks; 448 } 449 450 451 457 final void setYTicks (Rectangle[] ticks) { 458 459 needsUpdate = true; 460 this.yTicks = ticks; 461 } 462 463 464 471 final void setLinesThicknessAssociation (boolean association) { 472 473 needsUpdate = true; 474 linesThicknessAssociation = association; 475 } 476 477 478 482 final void setHorizontalLinesExistence (boolean existence) { 483 484 needsUpdate = true; 485 horizontalLinesExistence = existence; 486 } 487 488 489 499 final void setHorizontalLinesThicknessModel (int thickness) { 500 501 needsUpdate = true; 502 horizontalLinesThicknessModel = thickness; 503 } 504 505 506 511 final void setHorizontalLinesStyle (float[] style) { 512 513 needsUpdate = true; 514 horizontalLinesStyle = style; 515 } 516 517 518 522 final void setHorizontalLinesColor (Color color) { 523 524 needsUpdate = true; 525 horizontalLinesColor = color; 526 } 527 528 529 533 final void setVerticalLinesExistence (boolean existence) { 534 535 needsUpdate = true; 536 verticalLinesExistence = existence; 537 } 538 539 540 550 final void setVerticalLinesThicknessModel (int thickness) { 551 552 needsUpdate = true; 553 verticalLinesThicknessModel = thickness; 554 } 555 556 557 562 final void setVerticalLinesStyle (float[] style) { 563 564 needsUpdate = true; 565 verticalLinesStyle = style; 566 } 567 568 569 573 final void setVerticalLinesColor (Color color) { 574 575 needsUpdate = true; 576 verticalLinesColor = color; 577 } 578 579 580 585 final void setBarsExistence (boolean existence) { 586 587 needsUpdate = true; 588 barsExistence = existence; 589 } 590 591 592 602 final void setBarsThicknessModel (int thickness) { 603 604 needsUpdate = true; 605 barsThicknessModel = thickness; 606 } 607 608 609 615 final void setBarColors (Color[] colors) { 616 617 needsUpdate = true; 618 barColors = colors; 619 } 620 621 622 629 final void setBarsExcessSpaceFeedbackRatio (float ratio) { 630 631 needsUpdate = true; 632 barsExcessSpaceFeedbackRatio = ratio; 633 } 634 635 636 641 final void setBarsWithinCategoryOverlapRatio (float ratio) { 642 needsUpdate = true; 643 barsWithinCategoryOverlapRatio = ratio; 644 } 645 646 647 652 final void setDotsExistence (boolean existence) { 653 654 needsUpdate = true; 655 dotsExistence = existence; 656 } 657 658 659 669 final void setDotsThicknessModel (int thickness) { 670 671 needsUpdate = true; 672 dotsThicknessModel = thickness; 673 } 674 675 676 681 final void setDotsWithinCategoryOverlapRatio (float ratio) { 682 needsUpdate = true; 683 dotsWithinCategoryOverlapRatio = ratio; 684 } 685 686 687 693 final void setDotColors (Color[] colors) { 694 695 needsUpdate = true; 696 dotColors = colors; 697 } 698 699 700 707 final void setDotsExcessSpaceFeedbackRatio (float ratio) { 708 709 needsUpdate = true; 710 dotsExcessSpaceFeedbackRatio = ratio; 711 } 712 713 714 719 final void setLinesExistence (boolean existence) { 720 721 needsUpdate = true; 722 linesExistence = existence; 723 } 724 725 726 736 final void setLinesThicknessModel (int thickness) { 737 738 needsUpdate = true; 739 linesThicknessModel = thickness; 740 } 741 742 743 748 final void setLinesFillInterior (boolean fill) { 749 750 needsUpdate = true; 751 linesFillInterior = fill; 752 } 753 754 755 760 final void setLinesFillInteriorBaseValue (int value) { 761 762 needsUpdate = true; 763 linesFillInteriorBaseValue = value; 764 } 765 766 767 773 final void setLineColors (Color[] colors) { 774 775 needsUpdate = true; 776 lineColors = colors; 777 } 778 779 780 787 final void setLinesExcessSpaceFeedbackRatio (float ratio) { 788 789 needsUpdate = true; 790 linesExcessSpaceFeedbackRatio = ratio; 791 } 792 793 794 799 final void setLinesWithinCategoryOverlapRatio (float ratio) { 800 needsUpdate = true; 801 linesWithinCategoryOverlapRatio = ratio; 802 } 803 804 805 811 final void setBetweenComponentsGapExistence (boolean existence) { 812 813 needsUpdate = true; 814 betweenComponentsGapExistence = existence; 815 } 816 817 818 828 final void setBetweenComponentsGapThicknessModel (int thickness) { 829 830 needsUpdate = true; 831 betweenComponentsGapThicknessModel = thickness; 832 } 833 834 835 840 final float getBarRoundingRatio() { 841 return barRoundingRatio; 842 } 843 844 845 851 final int getComponentsLightSource() { 852 return lightSource; 853 } 854 855 856 864 final int getComponentsLightType() { 865 return lightType; 866 } 867 868 869 873 final Vector getWarningRegions() { 874 return warningRegions; 875 } 876 877 878 882 final boolean getClip() { 883 return clip; 884 } 885 886 887 891 final Color[] getComponentsColorsByCat() { 892 return componentsColorsByCat; 893 } 894 895 896 900 final boolean getComponentsColoringByCat() { 901 return componentsColoringByCat; 902 } 903 904 905 910 final boolean getOutlineComponents() { 911 912 return outlineComponents; 913 } 914 915 916 920 final Color getOutlineComponentsColor() { 921 922 return outlineComponentsColor; 923 } 924 925 926 930 final int getType() { 931 932 return type; 933 } 934 935 936 940 final boolean getAllowComponentAlignment() { 941 942 return allowComponentAlignment; 943 } 944 945 946 951 final int[][] getGraphValues() { 952 953 return graphValues; 954 } 955 956 957 961 final int[][] getBarLowValues() { 962 963 return barLowValues; 964 } 965 966 967 972 final Rectangle[] getXTicks() { 973 974 return xTicks; 975 } 976 977 978 983 final Rectangle[] getYTicks() { 984 985 return yTicks; 986 } 987 988 989 994 final int getLabelsAxisTicksAlignment() { 995 996 return ticksAlignment; 997 } 998 999 1000 1004 final boolean getBarsExistence() { 1005 1006 return barsExistence; 1007 } 1008 1009 1010 1014 final int getBarsThicknessModel() { 1015 1016 return barsThicknessModel; 1017 } 1018 1019 1020 1024 final Color[] getBarColors() { 1025 1026 return barColors; 1027 } 1028 1029 1030 1034 final float getBarsExcessSpaceFeedbackRatio() { 1035 return barsExcessSpaceFeedbackRatio; 1036 } 1037 1038 1039 1044 final float getBarsWithinCategoryOverlapRatio() { 1045 return barsWithinCategoryOverlapRatio; 1046 } 1047 1048 1049 1053 final boolean getDotsExistence() { 1054 1055 return dotsExistence; 1056 } 1057 1058 1059 1063 final int getDotsThicknessModel() { 1064 1065 return dotsThicknessModel; 1066 } 1067 1068 1069 1073 final Color[] getDotColors() { 1074 1075 return dotColors; 1076 } 1077 1078 1079 1083 final float getDotsExcessSpaceFeedbackRatio() { 1084 return dotsExcessSpaceFeedbackRatio; 1085 } 1086 1087 1088 1093 final float getDotsWithinCategoryOverlapRatio() { 1094 return dotsWithinCategoryOverlapRatio; 1095 } 1096 1097 1098 1102 final boolean getLinesExistence() { 1103 1104 return linesExistence; 1105 } 1106 1107 1108 1112 final int getLinesThicknessModel() { 1113 1114 return linesThicknessModel; 1115 } 1116 1117 1118 1124 final boolean getLinesFillInterior() { 1125 1126 return linesFillInterior; 1127 } 1128 1129 1130 1135 final int getLinesFillInteriorBaseValue() { 1136 1137 return linesFillInteriorBaseValue; 1138 } 1139 1140 1141 1145 final Color[] getLineColors() { 1146 1147 return lineColors; 1148 } 1149 1150 1151 1155 final float getLinesExcessSpaceFeedbackRatio() { 1156 return linesExcessSpaceFeedbackRatio; 1157 } 1158 1159 1160 1165 final float getLinesWithinCategoryOverlapRatio() { 1166 return linesWithinCategoryOverlapRatio; 1167 } 1168 1169 1170 1174 final boolean getBetweenComponentsGapExistence() { 1175 1176 return betweenComponentsGapExistence; 1177 } 1178 1179 1180 1184 final int getBetweenComponentsGapThicknessModel() { 1185 1186 return betweenComponentsGapThicknessModel; 1187 } 1188 1189 1190 1194 final boolean getVerticalLinesExistence() { 1195 1196 return verticalLinesExistence; 1197 } 1198 1199 1200 1204 final int getVerticalLinesThicknessModel() { 1205 1206 return verticalLinesThicknessModel; 1207 } 1208 1209 1210 1214 final int getVerticalLinesThickness() { 1215 1216 updateGraphArea(); 1217 return verticalLinesThickness; 1218 } 1219 1220 1221 1225 final Color getVerticalLinesColor() { 1226 1227 return verticalLinesColor; 1228 } 1229 1230 1231 1236 final float[] getVerticalLinesStyle() { 1237 1238 return verticalLinesStyle; 1239 } 1240 1241 1242 1246 final boolean getHorizontalLinesExistence() { 1247 1248 return horizontalLinesExistence; 1249 } 1250 1251 1252 1256 final int getHorizontalLinesThicknessModel() { 1257 1258 return horizontalLinesThicknessModel; 1259 } 1260 1261 1262 1266 final int getHorizontalLinesThickness() { 1267 1268 updateGraphArea(); 1269 return horizontalLinesThickness; 1270 } 1271 1272 1273 1277 final Color getHorizontalLinesColor() { 1278 1279 return horizontalLinesColor; 1280 } 1281 1282 1283 1288 final float[] getHorizontalLinesStyle() { 1289 1290 return horizontalLinesStyle; 1291 } 1292 1293 1294 1302 int[] stackedBarSort (int[][] graphValues, int barIndex) { 1303 1304 boolean[] used = new boolean[graphValues.length]; 1305 for (int i = 0; i < graphValues.length; ++i) { 1306 used[i] = false; 1307 } 1308 1309 int[] sorted = new int[graphValues.length]; 1310 for (int doing = 0; doing < graphValues.length; ++doing) { 1311 1312 int lowestValue = Integer.MIN_VALUE; 1313 int lowestIndex = -1; 1314 for (int i = graphValues.length - 1; i >= 0 ; --i) { 1315 if (!used[i] && (graphValues[i][barIndex] > lowestValue)) { 1316 lowestIndex = i; 1317 lowestValue = graphValues[i][barIndex]; 1318 } 1319 } 1320 sorted[doing] = lowestIndex; 1321 used[lowestIndex] = true; 1322 } 1323 return sorted; 1324 } 1325 1326 1327 1334 int[][] stackedBarConvert (int[][] graphValues, int[][] lowBarValues) { 1335 1336 int[][] convertedValues = 1337 new int[graphValues.length][graphValues[0].length]; 1338 for (int i = 0; i < graphValues.length; ++i) { 1339 for (int j = 0; j < graphValues[0].length; ++j) { 1340 convertedValues[i][j] = graphValues[i][j] < lowBarValues[i][j] ? 1341 -graphValues[i][j] :graphValues[i][j]; 1342 } 1343 } 1344 return convertedValues; 1345 } 1346 1347 1348 1360 final void resetGraphAreaModel (boolean reset) { 1361 1362 needsUpdate = true; 1363 resetAreaModel (reset); 1364 } 1365 1366 1367 1371 final boolean getGraphAreaNeedsUpdate() { 1372 return (needsUpdate || getAreaNeedsUpdate()); 1373 } 1374 1375 1376 1380 final void updateGraphArea() { 1381 1382 if (getGraphAreaNeedsUpdate()) { 1383 1384 updateArea(); 1385 update(); 1386 } 1387 needsUpdate = false; 1388 } 1389 1390 1391 1395 void paintComponent (Graphics2D g2D) { 1396 1397 updateGraphArea(); 1398 super.paintComponent (g2D); 1399 1400 Color oldColor = g2D.getColor(); 1401 Stroke oldStroke = g2D.getStroke(); 1402 1403 if (horizontalLinesThickness > 0 && horizontalLinesExistence && horizontalLines.length > 0) { 1404 g2D.setColor (horizontalLinesColor); 1405 g2D.setStroke (horizontalLinesStroke); 1406 for (int i = 0; i < horizontalLines.length; ++i) g2D.draw (horizontalLines[i]); 1407 } 1408 1409 if (verticalLinesThickness > 0 && verticalLinesExistence && verticalLines.length > 0) { 1410 g2D.setColor (verticalLinesColor); 1411 g2D.setStroke (verticalLinesStroke); 1412 for (int i = 0; i < verticalLines.length; ++i) g2D.draw (verticalLines[i]); 1413 } 1414 1415 g2D.setColor (oldColor); 1416 g2D.setStroke (oldStroke); 1417 } 1418 1419 1420 private void update() { 1421 1422 horizontalLinesThickness = 0; 1423 int numHorizontalLines = type == LABELSBOTTOM ? 1424 yTicks.length - 2 : yTicks.length; 1425 int availableHeight = getSpaceSize (MIN).height; 1426 if (horizontalLinesExistence && numHorizontalLines > 0) { 1427 horizontalLinesThickness = 1428 applyRatio (horizontalLinesThicknessModel, getRatio (HEIGHT)); 1429 horizontalLinesThickness = 1430 numHorizontalLines * horizontalLinesThickness <= availableHeight ? 1431 horizontalLinesThickness : availableHeight / numHorizontalLines; 1432 } 1433 else numHorizontalLines = 0; 1434 1435 verticalLinesThickness = 0; 1436 int numVerticalLines = type == LABELSBOTTOM ? 1437 xTicks.length : xTicks.length - 2; 1438 int availableWidth = getSpaceSize (MIN).width; 1439 if (verticalLinesExistence && numVerticalLines > 0) { 1440 verticalLinesThickness = 1441 applyRatio (verticalLinesThicknessModel, getRatio (WIDTH)); 1442 verticalLinesThickness = 1443 numVerticalLines * verticalLinesThickness <= availableWidth ? 1444 verticalLinesThickness : availableWidth / numVerticalLines; 1445 } 1446 else numVerticalLines = 0; 1447 1448 if (linesThicknessAssociation) { 1449 verticalLinesThickness = 1450 horizontalLinesThickness < verticalLinesThickness && 1451 horizontalLinesExistence ? 1452 horizontalLinesThickness : verticalLinesThickness; 1453 horizontalLinesThickness = 1454 verticalLinesThickness < horizontalLinesThickness && 1455 verticalLinesExistence ? 1456 verticalLinesThickness : horizontalLinesThickness; 1457 } 1458 1459 horizontalLinesStroke = 1460 new BasicStroke ((float)horizontalLinesThickness, 1461 BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, 1462 horizontalLinesStyle, 0.0f); 1463 verticalLinesStroke = 1464 new BasicStroke ((float)verticalLinesThickness, 1465 BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, 1466 verticalLinesStyle, 0.0f); 1467 1468 int x1,x2,y1,y2; 1469 1470 horizontalLines = new Line2D.Double[numHorizontalLines]; 1471 int horizontalLinesOffset = 0; 1472 if (horizontalLinesExistence && yTicks.length > 0) { 1473 horizontalLinesOffset = +yTicks[0].height / 2; 1474 } 1475 x1 = getSpaceSizeLocation (MIN).x; 1476 x2 = x1 + getSpaceSize (MIN).width; 1477 int offsetI = type == LABELSBOTTOM ? 1 : 0; 1478 for (int i = 0; i < numHorizontalLines; ++i) { 1479 y1 = yTicks[i + offsetI].y + horizontalLinesOffset; 1480 y2 = y1; 1481 horizontalLines[i] = 1482 new Line2D.Double ((double)x1, (double)y1, (double)x2, (double)y2); 1483 } 1484 1485 verticalLines = new Line2D.Double[numVerticalLines]; 1486 int verticalLinesOffset = 0; 1487 if (verticalLinesExistence && xTicks.length > 0) { 1488 verticalLinesOffset = xTicks[0].width / 2; 1489 } 1490 1491 y1 = getSpaceSizeLocation (MIN).y; 1492 y2 = y1 + getSpaceSize (MIN).height; 1493 offsetI = type == LABELSBOTTOM ? 0 : 1; 1494 for (int i = 0; i < numVerticalLines; ++i) { 1495 x1 = xTicks[i + offsetI].x + verticalLinesOffset; 1496 x2 = x1; 1497 verticalLines[i] = new Line2D.Double ((double)x1, (double)y1, (double)x2, (double)y2); 1498 } 1499 } 1500} | Popular Tags |