-
-
Notifications
You must be signed in to change notification settings - Fork 257
Expand file tree
/
Copy pathUserDefinedLayoutReader.java
More file actions
393 lines (348 loc) · 12.9 KB
/
UserDefinedLayoutReader.java
File metadata and controls
393 lines (348 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
package net.osmtracker.util;
import java.io.IOException;
import java.util.HashMap;
import net.osmtracker.OSMTracker;
import net.osmtracker.R;
import net.osmtracker.activity.TrackLogger;
import net.osmtracker.layout.DisablableTableLayout;
import net.osmtracker.layout.UserDefinedLayout;
import net.osmtracker.listener.IncrementalWaypointOnclickListener;
import net.osmtracker.listener.PageButtonOnClickListener;
import net.osmtracker.listener.StillImageOnClickListener;
import net.osmtracker.listener.TagButtonOnClickListener;
import net.osmtracker.listener.TextNoteOnClickListener;
import net.osmtracker.listener.VoiceRecOnClickListener;
import net.osmtracker.service.resources.IconResolver;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
/**
* Reads an user defined layout, using a pull parser,
* and instantiate corresponding objects (Layouts, Buttons)
*
* @author Nicolas Guillaumin
*
*/
public class UserDefinedLayoutReader {
@SuppressWarnings("unused")
private static final String TAG = UserDefinedLayoutReader.class.getSimpleName();
/**
* Map containing parsed layouts
*/
private HashMap<String, ViewGroup> layouts = new HashMap<String, ViewGroup>();
/**
* Source parser
*/
private XmlPullParser parser;
/**
* Context for accessing resources
*/
private Context context;
/**
* The user defined Layout
*/
private UserDefinedLayout userDefinedLayout;
/**
* {@link IconResolver} to retrieve button icons.
*/
private IconResolver iconResolver;
/**
* Listener bound to text note buttons
*/
private TextNoteOnClickListener textNoteOnClickListener;
/**
* Listener bound to voice record buttons
*/
private VoiceRecOnClickListener voiceRecordOnClickListener;
/**
* Lister bound to picture buttons
*/
private StillImageOnClickListener stillImageOnClickListener;
/**
* {@link Resources} to retrieve String resources
*/
private Resources resources;
/**
* representing ScreenOrientation
* see {@link Configuration.orientation}
*/
private int orientation;
private static final int ICON_POS_AUTO = 0;
private static final int ICON_POS_TOP = 1;
private static final int ICON_POS_RIGHT = 2;
private static final int ICON_POS_BOTTOM = 3;
private static final int ICON_POS_LEFT = 4;
/**
* the icon position for the current layout
*/
private int currentLayoutIconPos = UserDefinedLayoutReader.ICON_POS_AUTO;
/**
* Current track id
*/
private long currentTrackId;
/**
* Constructor
*
* @param udl
* User defined layout
* @param c
* Context for accessing resources
* @param tl
* TrackLogger activity
* @param trackId
* Current track id
* @param input
* Parser for reading layout
* @param ir
* Icon resolver to use to fetch icons
*/
public UserDefinedLayoutReader(UserDefinedLayout udl, Context c, TrackLogger tl, long trackId, XmlPullParser input, IconResolver ir) {
parser = input;
context = c;
resources = context.getResources();
userDefinedLayout = udl;
iconResolver = ir;
currentTrackId = trackId;
orientation = resources.getConfiguration().orientation;
// Initialize listeners which will be bound to buttons
textNoteOnClickListener = new TextNoteOnClickListener(tl);
voiceRecordOnClickListener = new VoiceRecOnClickListener(tl);
stillImageOnClickListener = new StillImageOnClickListener(tl);
}
/**
* Parses an XML layout
*
* @return An HashMap of {@link ViewGroup} with layout name as key.
* @throws XmlPullParserException
* @throws IOException
*/
public HashMap<String, ViewGroup> parseLayout() throws XmlPullParserException, IOException {
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG:
String tagName = parser.getName();
if (XmlSchema.TAG_LAYOUT.equals(tagName)) {
// <layout> tag has been encountered. Inflate this layout
inflateLayout();
}
break;
case XmlPullParser.END_TAG:
break;
}
eventType = parser.next();
}
return layouts;
}
/**
* Inflates a <layout> into a {@link TableLayout}
*
* @throws IOException
* @throws XmlPullParserException
*/
private void inflateLayout() throws IOException, XmlPullParserException {
String layoutName = parser.getAttributeValue(null, XmlSchema.ATTR_NAME);
String layoutIconPosValue = parser.getAttributeValue(null, XmlSchema.ATTR_ICONPOS);
// find out the correct icon position for this layout
if(XmlSchema.ATTR_VAL_ICONPOS_TOP.equals(layoutIconPosValue)){
// TOP position
this.currentLayoutIconPos = UserDefinedLayoutReader.ICON_POS_TOP;
} else if (XmlSchema.ATTR_VAL_ICONPOS_RIGHT.equals(layoutIconPosValue)){
// RIGHT position
this.currentLayoutIconPos = UserDefinedLayoutReader.ICON_POS_RIGHT;
} else if (XmlSchema.ATTR_VAL_ICONPOS_BOTTOM.equals(layoutIconPosValue)){
// BOTTOM position
this.currentLayoutIconPos = UserDefinedLayoutReader.ICON_POS_BOTTOM;
} else if (XmlSchema.ATTR_VAL_ICONPOS_LEFT.equals(layoutIconPosValue)){
// LEFT position
this.currentLayoutIconPos = UserDefinedLayoutReader.ICON_POS_LEFT;
} else {
// if no or an undefined value is given for the current layout
// AUTO position depending on screen orientation
this.currentLayoutIconPos = UserDefinedLayoutReader.ICON_POS_AUTO;
}
// Create a new table layout and set default parameters
DisablableTableLayout tblLayout = new DisablableTableLayout(context);
tblLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT, 1));
String currentTagName = null;
while (!XmlSchema.TAG_LAYOUT.equals(currentTagName)) {
int eventType = parser.next();
switch (eventType) {
case XmlPullParser.START_TAG:
String name = parser.getName();
if (XmlSchema.TAG_ROW.equals(name)) {
// <row> tag has been encountered, inflates it
inflateRow(tblLayout);
}
break;
case XmlPullParser.END_TAG:
currentTagName = parser.getName();
break;
}
}
// Add the new inflated layout to the list
layouts.put(layoutName, tblLayout);
}
/**
* Inflates a <row> into a {@link TableRow}
*
* @param layout
* {@link TableLayout} to rattach the row to
* @throws XmlPullParserException
* @throws IOException
*/
private void inflateRow(TableLayout layout) throws XmlPullParserException, IOException {
TableRow tblRow = new TableRow(layout.getContext());
tblRow.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT,
TableLayout.LayoutParams.FILL_PARENT, 1));
String currentTagName = null;
// int eventType = parser.next();
while (!XmlSchema.TAG_ROW.equals(currentTagName)) {
int eventType = parser.next();
switch (eventType) {
case XmlPullParser.START_TAG:
String name = parser.getName();
if (XmlSchema.TAG_BUTTON.equals(name)) {
// <button> tag has been encountered, inflates it.
inflateButton(tblRow);
}
break;
case XmlPullParser.END_TAG:
currentTagName = parser.getName();
break;
}
}
// Add the inflated table row to the current layout
layout.addView(tblRow);
}
/**
* Inflates a <button>
*
* @param row
* The table row to attach the button to
*/
public void inflateButton(TableRow row) {
Button button = new Button(row.getContext());
button.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT,
TableRow.LayoutParams.FILL_PARENT, 1));
// TODO Use kind of ButtonFactory here
String buttonType = parser.getAttributeValue(null, XmlSchema.ATTR_TYPE);
Drawable buttonIcon = null;
if (XmlSchema.ATTR_VAL_PAGE.equals(buttonType)) {
// Page button
button.setText(findLabel(parser.getAttributeValue(null, XmlSchema.ATTR_LABEL), resources));
buttonIcon = iconResolver.getIcon(parser.getAttributeValue(null, XmlSchema.ATTR_ICON));
button.setOnClickListener(new PageButtonOnClickListener(userDefinedLayout, parser.getAttributeValue(null,
XmlSchema.ATTR_TARGETLAYOUT)));
} else if (XmlSchema.ATTR_VAL_TAG.equals(buttonType)) {
// Standard tag button
button.setText(findLabel(parser.getAttributeValue(null, XmlSchema.ATTR_LABEL), resources));
buttonIcon = iconResolver.getIcon(parser.getAttributeValue(null, XmlSchema.ATTR_ICON));
button.setOnClickListener(new TagButtonOnClickListener(currentTrackId));
} else if (XmlSchema.ATTR_VAL_INCREMENTAL_WAYPOINT.equals(buttonType)) {
button.setText(resources.getString(R.string.gpsstatus_record_incremental_waypoint));
buttonIcon = iconResolver.getIcon(parser.getAttributeValue(null, XmlSchema.ATTR_ICON));
String incremental_waypoint_format = parser.getAttributeValue(null,XmlSchema.ATTR_FORMAT);
button.setOnClickListener(new IncrementalWaypointOnclickListener(currentTrackId, incremental_waypoint_format, context));
} else if ((XmlSchema.ATTR_VAL_VOICEREC.equals(buttonType))) {
// Voice record button
button.setText(resources.getString(R.string.gpsstatus_record_voicerec));
buttonIcon = resources.getDrawable(R.drawable.voice_32x32);
button.setOnClickListener(voiceRecordOnClickListener);
} else if (XmlSchema.ATTR_VAL_TEXTNOTE.equals(buttonType)) {
// Text note button
button.setText(resources.getString(R.string.gpsstatus_record_textnote));
buttonIcon = resources.getDrawable(R.drawable.text_32x32);
button.setOnClickListener(textNoteOnClickListener);
} else if (XmlSchema.ATTR_VAL_PICTURE.equals(buttonType)) {
// Picture button
button.setText(resources.getString(R.string.gpsstatus_record_stillimage));
buttonIcon = resources.getDrawable(R.drawable.camera_32x32);
button.setOnClickListener(stillImageOnClickListener);
}
// Where to draw the button's icon (depending on the current layout)
switch(this.currentLayoutIconPos){
case UserDefinedLayoutReader.ICON_POS_TOP:
// TOP position
button.setCompoundDrawablesWithIntrinsicBounds(null, buttonIcon, null, null);
break;
case UserDefinedLayoutReader.ICON_POS_RIGHT:
// RIGHT position
button.setCompoundDrawablesWithIntrinsicBounds(null, null, buttonIcon, null);
break;
case UserDefinedLayoutReader.ICON_POS_BOTTOM:
// BOTTOM position
button.setCompoundDrawablesWithIntrinsicBounds(null, null, null, buttonIcon);
break;
case UserDefinedLayoutReader.ICON_POS_LEFT:
// LEFT position
button.setCompoundDrawablesWithIntrinsicBounds(buttonIcon, null, null, null);
break;
case UserDefinedLayoutReader.ICON_POS_AUTO:
default:
// if no or an undefined value is given for the current layout
// AUTO position depending on screen orientation
if(orientation == Configuration.ORIENTATION_LANDSCAPE){
// in landscape mode draw icon to the LEFT
button.setCompoundDrawablesWithIntrinsicBounds(buttonIcon, null, null,null);
}else{
// in portrait mode draw icon to the TOP
button.setCompoundDrawablesWithIntrinsicBounds(null, buttonIcon, null, null);
}
break;
}
row.addView(button);
}
/**
* Finds a label if it's a reference to an internal resource (@string/label)
* @param text Resource reference or plain label
* @param r {@link Resources} to lookup from
* @return Plain label, or corresponding text extracted from {@link Resources}
*/
private String findLabel(String text, Resources r) {
if (text != null) {
if (text.startsWith("@")) {
// Check if it's a resource identifier
int resId = resources.getIdentifier(text.replace("@", ""), null, OSMTracker.PACKAGE_NAME);
if (resId != 0) {
return resources.getString(resId);
}
}
}
return text;
}
/**
* XML Schema
*/
private static final class XmlSchema {
public static final String TAG_LAYOUT = "layout";
public static final String TAG_ROW = "row";
public static final String TAG_BUTTON = "button";
public static final String ATTR_NAME = "name";
public static final String ATTR_TYPE = "type";
public static final String ATTR_LABEL = "label";
public static final String ATTR_TARGETLAYOUT = "targetlayout";
public static final String ATTR_ICON = "icon";
public static final String ATTR_ICONPOS = "iconpos";
public static final String ATTR_FORMAT = "format";
public static final String ATTR_VAL_TAG = "tag";
public static final String ATTR_VAL_PAGE = "page";
public static final String ATTR_VAL_VOICEREC = "voicerec";
public static final String ATTR_VAL_TEXTNOTE = "textnote";
public static final String ATTR_VAL_PICTURE = "picture";
public static final String ATTR_VAL_INCREMENTAL_WAYPOINT = "incwp";
public static final String ATTR_VAL_ICONPOS_TOP = "top";
public static final String ATTR_VAL_ICONPOS_RIGHT = "right";
public static final String ATTR_VAL_ICONPOS_BOTTOM = "bottom";
public static final String ATTR_VAL_ICONPOS_LEFT = "left";
}
}