19
19
20
20
import org .eclipse .jface .fieldassist .ControlDecoration ;
21
21
import org .eclipse .jface .fieldassist .FieldDecorationRegistry ;
22
+ import org .eclipse .swt .graphics .GC ;
22
23
import org .eclipse .swt .graphics .Image ;
24
+ import org .eclipse .swt .widgets .Control ;
23
25
24
26
/**
25
27
* This class contains methods to validate and decorate search fields.
@@ -41,11 +43,10 @@ private SearchDecoration() {
41
43
* the validation.
42
44
*/
43
45
public static boolean validateRegex (String regex , ControlDecoration targetDecoration ) {
44
- String errorMessage = getValidationError (regex );
46
+ String errorMessage = getValidationError (regex , targetDecoration . getControl () );
45
47
if (errorMessage .isEmpty ()) {
46
48
targetDecoration .hide ();
47
49
return true ;
48
-
49
50
}
50
51
51
52
Image decorationImage = FieldDecorationRegistry .getDefault ()
@@ -62,21 +63,54 @@ public static boolean validateRegex(String regex, ControlDecoration targetDecora
62
63
* @return The appropriate error message if the regex is invalid or an empty
63
64
* string if the regex is valid.
64
65
*/
65
- private static String getValidationError (String regex ) {
66
+ private static String getValidationError (String regex , Control targetControl ) {
66
67
try {
67
68
Pattern .compile (regex );
68
69
return "" ; //$NON-NLS-1$
69
70
} catch (PatternSyntaxException e ) {
70
- String message = e .getLocalizedMessage ();
71
+ return buildValidationErrorString (e , targetControl );
72
+ }
73
+ }
74
+
75
+ private static String buildValidationErrorString (PatternSyntaxException e , Control targetControl ) {
76
+ String description = e .getDescription ();
77
+ int errorIndex = e .getIndex ();
78
+
79
+ if (errorIndex == -1 ) {
80
+ return description ;
81
+ }
82
+
83
+ GC gc = new GC (targetControl );
84
+ String pattern = e .getPattern ();
71
85
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
- }
86
+ StringBuilder validationErrorMessage = new StringBuilder ();
77
87
78
- return message .substring (0 , i );
88
+ validationErrorMessage .append (description );
89
+ validationErrorMessage .append (" at index " ).append (errorIndex ).append (System .lineSeparator ()); //$NON-NLS-1$
90
+ validationErrorMessage .append (pattern ).append (System .lineSeparator ());
91
+
92
+ String stringToIndexString = pattern .substring (0 , errorIndex + 1 );
93
+ String hairSpace = "\u200A " ; //$NON-NLS-1$
94
+ int hairSpaceWidth = gc .stringExtent (hairSpace ).x ;
95
+
96
+ int stringToIndex = gc .stringExtent (stringToIndexString ).x ;
97
+ String lastCharacter = stringToIndexString .substring (stringToIndexString .length () - 1 );
98
+
99
+ int widthLastChar = gc .stringExtent (lastCharacter ).x ;
100
+ int upWidth = gc .stringExtent ("^" ).x ; //$NON-NLS-1$
101
+
102
+ double howFar = stringToIndex - widthLastChar / 2 - upWidth / 2 ;
103
+ int currentWidth = 0 ;
104
+
105
+ while (currentWidth < howFar ) {
106
+ currentWidth += hairSpaceWidth ;
107
+ validationErrorMessage .append (hairSpace );
79
108
}
109
+
110
+ validationErrorMessage .append ("^" ); //$NON-NLS-1$
111
+ gc .dispose ();
112
+
113
+ return validationErrorMessage .toString ();
80
114
}
81
115
82
116
}
0 commit comments