Skip to content

Commit dad1e3d

Browse files
committed
Merge pull request androidannotations#830 from yDelouis/494_EditorAction
New annotation @EditorAction
2 parents 6014cf3 + 1e6a298 commit dad1e3d

9 files changed

Lines changed: 378 additions & 5 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* Copyright (C) 2010-2013 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.annotations;
17+
18+
import java.lang.annotation.ElementType;
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
import java.lang.annotation.Target;
22+
23+
/**
24+
* Should be used on editor action listener methods in enhanced classes with view support
25+
*
26+
* The method may have some parameters amoung :
27+
* - a TextView
28+
* - an int : the actionId
29+
* - a KeyEvent
30+
*
31+
* The annotation value should be one of R.id.* fields. If not set, the method
32+
* name will be used as the R.id.* field name.
33+
*
34+
*/
35+
36+
/**
37+
* This annotation is intended to be used on methods to receive events defined
38+
* by
39+
* {@link android.widget.TextView.OnEditorActionListener#onEditorAction(android.widget.TextView, int, android.view.KeyEvent)}
40+
* when an action is performed on the editor.
41+
* <p/>
42+
* The annotation value should be one or several R.id.* fields that refers to
43+
* TextView or subclasses of TextView. If not set, the method name will be used
44+
* as the R.id.* field name.
45+
* <p/>
46+
* The method MAY have multiple parameter :
47+
* <ul>
48+
* <li>A {@link android.widget.TextView} parameter to know which view has
49+
* targeted this event
50+
* <li>An int parameter to get the actionId
51+
* <li>A {@link android.view.KeyEvent} parameter
52+
* </ul>
53+
* <p/>
54+
* <blockquote>
55+
*
56+
* Examples :
57+
*
58+
* <pre>
59+
* &#064;EditorAction(<b>R.id.helloTextView</b>)
60+
* void onEditorActionsOnHelloTextView(TextView hello, int actionId, KeyEvent keyEvent) {
61+
* // Something Here
62+
* }
63+
*
64+
* &#064;EditorAction
65+
* void <b>helloTextView</b>EditorAction(TextView hello) {
66+
* // Something Here
67+
* }
68+
*
69+
* &#064;EditorAction(<b>{R.id.editText, R.id.helloTextView}</b>)
70+
* void onEditorActionsOnSomeTextViews(TextView tv, int actionId) {
71+
* // Something Here
72+
* }
73+
*
74+
* &#064;EditorAction(<b>R.id.helloTextView</b>)
75+
* void onEditorActionsOnHelloTextView() {
76+
* // Something Here
77+
* }
78+
* </pre>
79+
*
80+
* </blockquote>
81+
*/
82+
@Retention(RetentionPolicy.CLASS)
83+
@Target(ElementType.METHOD)
84+
public @interface EditorAction {
85+
86+
int[] value() default ResId.DEFAULT_VALUE;
87+
88+
String[] resName() default "";
89+
90+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/AnnotationHandlers.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public AnnotationHandlers(ProcessingEnvironment processingEnvironment) {
7676
add(new ItemClickHandler(processingEnvironment));
7777
add(new ItemSelectHandler(processingEnvironment));
7878
add(new ItemLongClickHandler(processingEnvironment));
79+
add(new EditorActionHandler(processingEnvironment));
7980
for (AndroidRes androidRes : AndroidRes.values()) {
8081
add(new ResHandler(androidRes, processingEnvironment));
8182
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* Copyright (C) 2010-2013 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.handler;
17+
18+
import com.sun.codemodel.*;
19+
import org.androidannotations.annotations.EditorAction;
20+
import org.androidannotations.helper.CanonicalNameConstants;
21+
import org.androidannotations.model.AnnotationElements;
22+
import org.androidannotations.process.IsValid;
23+
24+
import javax.annotation.processing.ProcessingEnvironment;
25+
import javax.lang.model.element.Element;
26+
import javax.lang.model.element.ExecutableElement;
27+
import javax.lang.model.element.VariableElement;
28+
import javax.lang.model.type.TypeKind;
29+
import javax.lang.model.type.TypeMirror;
30+
import java.util.List;
31+
32+
public class EditorActionHandler extends AbstractListenerHandler {
33+
34+
public EditorActionHandler(ProcessingEnvironment processingEnvironment) {
35+
super(EditorAction.class, processingEnvironment);
36+
}
37+
38+
@Override
39+
public void validate(Element element, AnnotationElements validatedElements, IsValid valid) {
40+
super.validate(element, validatedElements, valid);
41+
42+
ExecutableElement executableElement = (ExecutableElement) element;
43+
44+
validatorHelper.returnTypeIsVoidOrBoolean(executableElement, valid);
45+
46+
validatorHelper.param.hasAtMostOneTextViewParameter(executableElement, valid);
47+
48+
validatorHelper.param.hasAtMostOneIntegerParameter(executableElement, valid);
49+
50+
validatorHelper.param.hasAtMostOneKeyEventParameter(executableElement, valid);
51+
52+
validatorHelper.param.hasNoOtherParameterFromATextViewAnIntegerAndAKeyEvent(executableElement, valid);
53+
}
54+
55+
@Override
56+
protected void makeCall(JBlock listenerMethodBody, JInvocation call, TypeMirror returnType) {
57+
boolean returnMethodResult = returnType.getKind() != TypeKind.VOID;
58+
59+
if (returnMethodResult) {
60+
listenerMethodBody._return(call);
61+
} else {
62+
listenerMethodBody.add(call);
63+
listenerMethodBody._return(JExpr.TRUE);
64+
}
65+
}
66+
67+
@Override
68+
protected void processParameters(JMethod listenerMethod, JInvocation call, List<? extends VariableElement> userParameters) {
69+
JVar textView = listenerMethod.param(classes().TEXT_VIEW, "textView");
70+
JVar actionId = listenerMethod.param(codeModel().INT, "actionId");
71+
JVar event = listenerMethod.param(classes().KEY_EVENT, "event");
72+
73+
for (VariableElement param : userParameters) {
74+
String paramClassQualifiedName = param.asType().toString();
75+
if (paramClassQualifiedName.equals(CanonicalNameConstants.TEXT_VIEW)) {
76+
call.arg(textView);
77+
} else if (paramClassQualifiedName.equals(CanonicalNameConstants.INTEGER) || paramClassQualifiedName.equals(codeModel().INT.fullName())) {
78+
call.arg(actionId);
79+
} else if(paramClassQualifiedName.equals(CanonicalNameConstants.KEY_EVENT)) {
80+
call.arg(event);
81+
}
82+
}
83+
}
84+
85+
@Override
86+
protected JMethod createListenerMethod(JDefinedClass listenerAnonymousClass) {
87+
return listenerAnonymousClass.method(JMod.PUBLIC, codeModel().BOOLEAN, "onEditorAction");
88+
}
89+
90+
@Override
91+
protected String getSetterName() {
92+
return "setOnEditorActionListener";
93+
}
94+
95+
@Override
96+
protected JClass getListenerClass() {
97+
return classes().TEXT_VIEW_ON_EDITOR_ACTION_LISTENER;
98+
}
99+
100+
@Override
101+
protected JClass getViewClass() {
102+
return classes().TEXT_VIEW;
103+
}
104+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public final class CanonicalNameConstants {
6262
public static final String SEEKBAR = "android.widget.SeekBar";
6363
public static final String ON_SEEKBAR_CHANGE_LISTENER = "android.widget.SeekBar.OnSeekBarChangeListener";
6464
public static final String TEXT_VIEW = "android.widget.TextView";
65+
public static final String TEXT_VIEW_ON_EDITOR_ACTION_LISTENER = "android.widget.TextView.OnEditorActionListener";
6566
public static final String COMPOUND_BUTTON = "android.widget.CompoundButton";
6667
public static final String COMPOUND_BUTTON_ON_CHECKED_CHANGE_LISTENER = "android.widget.CompoundButton.OnCheckedChangeListener";
6768
public static final String VIEW = "android.view.View";

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/ValidatorParameterHelper.java‎

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,22 @@
1515
*/
1616
package org.androidannotations.helper;
1717

18-
import static java.util.Arrays.asList;
19-
20-
import java.util.Arrays;
21-
import java.util.List;
18+
import org.androidannotations.process.IsValid;
2219

2320
import javax.lang.model.element.ExecutableElement;
2421
import javax.lang.model.element.VariableElement;
2522
import javax.lang.model.type.TypeKind;
2623
import javax.lang.model.type.TypeMirror;
24+
import java.util.Arrays;
25+
import java.util.List;
2726

28-
import org.androidannotations.process.IsValid;
27+
import static java.util.Arrays.asList;
2928

3029
public class ValidatorParameterHelper {
3130

3231
private static final List<String> ANDROID_SHERLOCK_MENU_ITEM_QUALIFIED_NAMES = asList(CanonicalNameConstants.MENU_ITEM, CanonicalNameConstants.SHERLOCK_MENU_ITEM);
32+
private static final List<String> EDITOR_ACTION_ALLOWED_PARAMETER_TYPES = asList(CanonicalNameConstants.TEXT_VIEW,
33+
CanonicalNameConstants.INTEGER, "int", CanonicalNameConstants.KEY_EVENT);
3334

3435
protected final TargetAnnotationHelper annotationHelper;
3536

@@ -213,4 +214,45 @@ public void hasExactlyOneParameter(ExecutableElement executableElement, IsValid
213214
}
214215
}
215216

217+
public void hasAtMostOneTextViewParameter(ExecutableElement executableElement, IsValid valid) {
218+
hasAtMostOneSpecificParameter(executableElement, CanonicalNameConstants.TEXT_VIEW, valid);
219+
}
220+
221+
public void hasAtMostOneIntegerParameter(ExecutableElement executableElement, IsValid valid) {
222+
List<String> integers = Arrays.asList(CanonicalNameConstants.INTEGER, "integer");
223+
hasAtMostOneSpecificParameter(executableElement, integers, valid);
224+
}
225+
226+
public void hasAtMostOneKeyEventParameter(ExecutableElement executableElement, IsValid valid) {
227+
hasAtMostOneSpecificParameter(executableElement, CanonicalNameConstants.KEY_EVENT, valid);
228+
229+
}
230+
231+
public void hasAtMostOneSpecificParameter(ExecutableElement executableElement, String qualifiedName, IsValid valid) {
232+
hasAtMostOneSpecificParameter(executableElement, Arrays.asList(qualifiedName), valid);
233+
}
234+
235+
public void hasAtMostOneSpecificParameter(ExecutableElement executableElement, List<String> qualifiedNames, IsValid valid) {
236+
boolean hasOneMatchingParameter = false;
237+
for (VariableElement parameter : executableElement.getParameters()) {
238+
if (qualifiedNames.contains(parameter.asType().toString())) {
239+
if (hasOneMatchingParameter) {
240+
valid.invalidate();
241+
annotationHelper.printAnnotationError(executableElement, "%s can't have more than one parameter of type "+parameter.asType().toString());
242+
} else {
243+
hasOneMatchingParameter = true;
244+
}
245+
}
246+
}
247+
}
248+
249+
public void hasNoOtherParameterFromATextViewAnIntegerAndAKeyEvent(ExecutableElement executableElement, IsValid valid) {
250+
for (VariableElement parameter : executableElement.getParameters()) {
251+
String parameterType = parameter.asType().toString();
252+
if (!EDITOR_ACTION_ALLOWED_PARAMETER_TYPES.contains(parameterType)) {
253+
valid.invalidate();
254+
annotationHelper.printAnnotationError(executableElement, "%s can only have TextView, int and/or KeyEvent parameters");
255+
}
256+
}
257+
}
216258
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ProcessHolder.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public class Classes {
7373
public final JClass SEEKBAR = refClass(CanonicalNameConstants.SEEKBAR);
7474
public final JClass ON_SEEKBAR_CHANGE_LISTENER = refClass(CanonicalNameConstants.ON_SEEKBAR_CHANGE_LISTENER);
7575
public final JClass TEXT_VIEW = refClass(CanonicalNameConstants.TEXT_VIEW);
76+
public final JClass TEXT_VIEW_ON_EDITOR_ACTION_LISTENER = refClass(CanonicalNameConstants.TEXT_VIEW_ON_EDITOR_ACTION_LISTENER);
7677
public final JClass COMPOUND_BUTTON = refClass(CanonicalNameConstants.COMPOUND_BUTTON);
7778
public final JClass COMPOUND_BUTTON_ON_CHECKED_CHANGE_LISTENER = refClass(CanonicalNameConstants.COMPOUND_BUTTON_ON_CHECKED_CHANGE_LISTENER);
7879
public final JClass VIEW = refClass(CanonicalNameConstants.VIEW);

‎AndroidAnnotations/functional-test-1-5/AndroidManifest.xml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<activity android:name=".CheckedChangeHandledActivity_" />
4848
<activity android:name=".LongClicksHandledActivity_" />
4949
<activity android:name=".TouchesHandledActivity_" />
50+
<activity android:name=".EditorActionsHandledActivity_" />
5051
<activity android:name=".ItemClicksHandledActivity_" />
5152
<activity android:name=".ActivityWithServices_" />
5253
<activity android:name=".ExtraInjectedActivity_" />
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
4+
Copyright (C) 2010-2013 eBusiness Information, Excilys Group
5+
6+
Licensed under the Apache License, Version 2.0 (the "License"); you may not
7+
use this file except in compliance with the License. You may obtain a copy of
8+
the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed To in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15+
License for the specific language governing permissions and limitations under
16+
the License.
17+
18+
-->
19+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
20+
android:orientation="vertical"
21+
android:layout_width="fill_parent"
22+
android:layout_height="fill_parent">
23+
24+
<TextView
25+
android:id="@+id/textView1"
26+
android:layout_width="wrap_content"
27+
android:layout_height="wrap_content"
28+
/>
29+
30+
<EditText
31+
android:id="@+id/editText1"
32+
android:layout_width="wrap_content"
33+
android:layout_height="wrap_content"
34+
android:inputType="text"
35+
/>
36+
37+
<TextView
38+
android:id="@+id/textView2"
39+
android:layout_width="fill_parent"
40+
android:layout_height="wrap_content"
41+
/>
42+
43+
<TextView
44+
android:id="@+id/textView3"
45+
android:layout_width="fill_parent"
46+
android:layout_height="wrap_content"
47+
/>
48+
49+
<TextView
50+
android:id="@+id/textView4"
51+
android:layout_width="fill_parent"
52+
android:layout_height="wrap_content"
53+
/>
54+
55+
<EditText
56+
android:id="@+id/editText2"
57+
android:layout_width="fill_parent"
58+
android:layout_height="wrap_content"
59+
android:inputType="text"
60+
/>
61+
62+
<EditText
63+
android:id="@+id/editText3"
64+
android:layout_width="fill_parent"
65+
android:layout_height="wrap_content"
66+
android:inputType="text"
67+
/>
68+
69+
</LinearLayout>

0 commit comments

Comments
 (0)