1919
2020import org .eclipse .jface .fieldassist .ControlDecoration ;
2121import org .eclipse .jface .fieldassist .FieldDecorationRegistry ;
22+ import org .eclipse .swt .graphics .GC ;
2223import org .eclipse .swt .graphics .Image ;
24+ import org .eclipse .swt .widgets .Control ;
2325
2426/**
2527 * This class contains methods to validate and decorate search fields.
@@ -41,11 +43,10 @@ private SearchDecoration() {
4143 * the validation.
4244 */
4345 public static boolean validateRegex (String regex , ControlDecoration targetDecoration ) {
44- String errorMessage = getValidationError (regex );
46+ String errorMessage = getValidationError (regex , targetDecoration . getControl () );
4547 if (errorMessage .isEmpty ()) {
4648 targetDecoration .hide ();
4749 return true ;
48-
4950 }
5051
5152 Image decorationImage = FieldDecorationRegistry .getDefault ()
@@ -62,21 +63,57 @@ public static boolean validateRegex(String regex, ControlDecoration targetDecora
6263 * @return The appropriate error message if the regex is invalid or an empty
6364 * string if the regex is valid.
6465 */
65- private static String getValidationError (String regex ) {
66+ private static String getValidationError (String regex , Control targetControl ) {
67+
6668 try {
6769 Pattern .compile (regex );
6870 return "" ; //$NON-NLS-1$
6971 } catch (PatternSyntaxException e ) {
70- String message = e .getLocalizedMessage ();
72+ return buildValidationErrorString (e , targetControl );
73+ }
74+ }
75+
76+ private static String buildValidationErrorString (PatternSyntaxException e , Control targetControl ) {
7177
72- // Only preserve the first line of the original error message.
73- int i = 0 ;
74- while (i < message .length () && "\n \r " .indexOf (message .charAt (i )) == -1 ) { //$NON-NLS-1$
75- i ++;
76- }
78+ String description = e .getDescription ();
79+ int errorIndex = e .getIndex ();
7780
78- return message .substring (0 , i );
81+ if (errorIndex == -1 ) {
82+ return description ;
7983 }
84+
85+ GC gc = new GC (targetControl );
86+ String pattern = e .getPattern ();
87+
88+ StringBuilder validationErrorMessage = new StringBuilder ();
89+
90+ validationErrorMessage .append (description );
91+ validationErrorMessage .append (" at index " ).append (errorIndex ).append (System .lineSeparator ()); //$NON-NLS-1$
92+ validationErrorMessage .append (pattern ).append (System .lineSeparator ());
93+
94+ String stringToIndexString = pattern .substring (0 , errorIndex + 1 );
95+ String hairSpace = "\u200A " ; //$NON-NLS-1$
96+ int hairSpaceWidth = gc .stringExtent (hairSpace ).x ;
97+
98+ int stringToIndex = gc .stringExtent (stringToIndexString ).x ;
99+ String lastCharacter = stringToIndexString .substring (stringToIndexString .length () - 1 );
100+
101+ int widthLastChar = gc .stringExtent (lastCharacter ).x ;
102+ int upWidth = gc .stringExtent ("^" ).x ; //$NON-NLS-1$
103+
104+ double howFar = stringToIndex - widthLastChar / 2 - upWidth / 2 ;
105+ int currentWidth = 0 ;
106+
107+ while (currentWidth < howFar ) {
108+ currentWidth += hairSpaceWidth ;
109+ validationErrorMessage .append (hairSpace );
110+ }
111+
112+ validationErrorMessage .append ("^" ); //$NON-NLS-1$
113+ gc .dispose ();
114+
115+ return validationErrorMessage .toString ();
80116 }
81117
118+
82119}
0 commit comments