--- /dev/null
+/**\r
+* Copyright (C) 2007 EDIT\r
+* European Distributed Institute of Taxonomy \r
+* http://www.e-taxonomy.eu\r
+* \r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/\r
+\r
+package eu.etaxonomy.taxeditor.editor;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.eclipse.jface.text.source.Annotation;\r
+import org.eclipse.jface.text.source.AnnotationPainter.SquigglesStrategy;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.StyledText;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Point;\r
+\r
+/**\r
+ * Adds ability to draw multiline squiggles when a <code>StyledText</code>\r
+ * contains line-wrapping.\r
+ * \r
+ * @author p.ciardelli\r
+ * @created 21.11.2008\r
+ * @version 1.0\r
+ */\r
+public class LineWrapSquigglesStrategy extends SquigglesStrategy {\r
+ private static final Logger logger = Logger\r
+ .getLogger(LineWrapSquigglesStrategy.class);\r
+ \r
+ public static final String ID = "linewrap_squigglesstrategy";\r
+\r
+ private GC gc;\r
+\r
+ private Color color;\r
+\r
+ private int lineHeight;\r
+\r
+ private int baseline;\r
+ \r
+ public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {\r
+ \r
+ this.gc = gc;\r
+ this.color = color;\r
+ \r
+ if (gc != null) {\r
+\r
+ if (length < 1)\r
+ return;\r
+ \r
+ baseline = textWidget.getBaseline(offset);\r
+ lineHeight = textWidget.getLineHeight(offset);\r
+ \r
+ Point right = null;\r
+ int newLineOffset = 0;\r
+ \r
+ for (int i = 1; i <= length; i++) {\r
+ \r
+ // If the y of the current offset is different from that of the last offset,\r
+ // we are on a new line\r
+ if (right != null && textWidget.getLocationAtOffset(i).y > right.y) {\r
+ \r
+ // Save last new line offset to draw squigglies under last line\r
+ newLineOffset = i;\r
+ \r
+ Point left = textWidget.getLocationAtOffset(offset);\r
+ \r
+ drawPolyline(left, right);\r
+ \r
+ offset += i;\r
+ }\r
+ \r
+ right = textWidget.getLocationAtOffset(i); \r
+ }\r
+ \r
+ drawPolyline(textWidget.getLocationAtOffset(newLineOffset), right);\r
+\r
+ } else {\r
+ textWidget.redrawRange(offset, length, true);\r
+ }\r
+ }\r
+ \r
+ private void drawPolyline(Point left, Point right) {\r
+ \r
+ int[] polyline= computePolyline(left, right, baseline, lineHeight);\r
+\r
+ gc.setLineWidth(0); // NOTE: 0 means width is 1 but with optimized performance\r
+ gc.setLineStyle(SWT.LINE_SOLID);\r
+ gc.setForeground(color);\r
+ gc.drawPolyline(polyline);\r
+ }\r
+\r
+ private int[] computePolyline(Point left, Point right, int baseline, int lineHeight) {\r
+\r
+ final int WIDTH= 4; // must be even\r
+ final int HEIGHT= 2; // can be any number\r
+\r
+ int peaks= (right.x - left.x) / WIDTH;\r
+ if (peaks == 0 && right.x - left.x > 2)\r
+ peaks= 1;\r
+\r
+ int leftX= left.x;\r
+\r
+ // compute (number of point) * 2\r
+ int length= ((2 * peaks) + 1) * 2;\r
+ if (length < 0)\r
+ return new int[0];\r
+\r
+ int[] coordinates= new int[length];\r
+\r
+ // cache peeks' y-coordinates\r
+ int top= left.y + Math.min(baseline + 1, lineHeight - HEIGHT - 1);\r
+ int bottom= top + HEIGHT;\r
+\r
+ // populate array with peek coordinates\r
+ for (int i= 0; i < peaks; i++) {\r
+ int index= 4 * i;\r
+ coordinates[index]= leftX + (WIDTH * i);\r
+ coordinates[index+1]= bottom;\r
+ coordinates[index+2]= coordinates[index] + WIDTH/2;\r
+ coordinates[index+3]= top;\r
+ }\r
+\r
+ // the last down flank is missing\r
+ coordinates[length-2]= Math.min(Math.max(0, right.x - 1), left.x + (WIDTH * peaks));\r
+ coordinates[length-1]= bottom;\r
+\r
+ return coordinates;\r
+ }\r
+}\r