1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of 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,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "java_lang_builder.h"
18
19 #include "android-base/stringprintf.h"
20
21 using android::base::StringPrintf;
22 using std::string;
23
Start() const24 void JavaLangViewBuilder::Start() const {
25 out_ << StringPrintf("package %s;\n", package_.c_str())
26 << "import android.content.Context;\n"
27 "import android.content.res.Resources;\n"
28 "import android.content.res.XmlResourceParser;\n"
29 "import android.util.AttributeSet;\n"
30 "import android.util.Xml;\n"
31 "import android.view.*;\n"
32 "import android.widget.*;\n"
33 "\n"
34 "public final class CompiledView {\n"
35 "\n"
36 "static <T extends View> T createView(Context context, AttributeSet attrs, View parent, "
37 "String name, LayoutInflater.Factory factory, LayoutInflater.Factory2 factory2) {"
38 "\n"
39 " if (factory2 != null) {\n"
40 " return (T)factory2.onCreateView(parent, name, context, attrs);\n"
41 " } else if (factory != null) {\n"
42 " return (T)factory.onCreateView(name, context, attrs);\n"
43 " }\n"
44 // TODO: find a way to call the private factory
45 " return null;\n"
46 "}\n"
47 "\n"
48 " public static View inflate(Context context) {\n"
49 " try {\n"
50 " LayoutInflater inflater = LayoutInflater.from(context);\n"
51 " LayoutInflater.Factory factory = inflater.getFactory();\n"
52 " LayoutInflater.Factory2 factory2 = inflater.getFactory2();\n"
53 " Resources res = context.getResources();\n"
54 << StringPrintf(" XmlResourceParser xml = res.getLayout(%s.R.layout.%s);\n",
55 package_.c_str(),
56 layout_name_.c_str())
57 << " AttributeSet attrs = Xml.asAttributeSet(xml);\n"
58 // The Java-language XmlPullParser needs a call to next to find the start document tag.
59 " xml.next(); // start document\n";
60 }
61
Finish() const62 void JavaLangViewBuilder::Finish() const {
63 out_ << " } catch (Exception e) {\n"
64 " return null;\n"
65 " }\n" // end try
66 " }\n" // end inflate
67 "}\n"; // end CompiledView
68 }
69
StartView(const string & class_name,bool)70 void JavaLangViewBuilder::StartView(const string& class_name, bool /*is_viewgroup*/) {
71 const string view_var = MakeVar("view");
72 const string layout_var = MakeVar("layout");
73 std::string parent = "null";
74 if (!view_stack_.empty()) {
75 const StackEntry& parent_entry = view_stack_.back();
76 parent = parent_entry.view_var;
77 }
78 out_ << " xml.next(); // <" << class_name << ">\n"
79 << StringPrintf(" %s %s = createView(context, attrs, %s, \"%s\", factory, factory2);\n",
80 class_name.c_str(),
81 view_var.c_str(),
82 parent.c_str(),
83 class_name.c_str())
84 << StringPrintf(" if (%s == null) %s = new %s(context, attrs);\n",
85 view_var.c_str(),
86 view_var.c_str(),
87 class_name.c_str());
88 if (!view_stack_.empty()) {
89 out_ << StringPrintf(" ViewGroup.LayoutParams %s = %s.generateLayoutParams(attrs);\n",
90 layout_var.c_str(),
91 parent.c_str());
92 }
93 view_stack_.push_back({class_name, view_var, layout_var});
94 }
95
FinishView()96 void JavaLangViewBuilder::FinishView() {
97 const StackEntry var = view_stack_.back();
98 view_stack_.pop_back();
99 if (!view_stack_.empty()) {
100 const string& parent = view_stack_.back().view_var;
101 out_ << StringPrintf(" xml.next(); // </%s>\n", var.class_name.c_str())
102 << StringPrintf(" %s.addView(%s, %s);\n",
103 parent.c_str(),
104 var.view_var.c_str(),
105 var.layout_params_var.c_str());
106 } else {
107 out_ << StringPrintf(" return %s;\n", var.view_var.c_str());
108 }
109 }
110
MakeVar(std::string prefix)111 const std::string JavaLangViewBuilder::MakeVar(std::string prefix) {
112 std::stringstream v;
113 v << prefix << view_id_++;
114 return v.str();
115 }
116