22
22
import android .os .Bundle ;
23
23
import android .os .Handler ;
24
24
import android .support .v4 .app .Fragment ;
25
+ import android .text .Html ;
26
+ import android .text .Spanned ;
27
+ import android .text .TextUtils ;
28
+ import android .util .Log ;
25
29
import android .view .LayoutInflater ;
26
30
import android .view .View ;
27
31
import android .view .ViewGroup ;
47
51
import com .imgtec .hobbyist .flow .DevicePresenceListener ;
48
52
import com .imgtec .hobbyist .flow .FlowEntities ;
49
53
import com .imgtec .hobbyist .flow .FlowHelper ;
54
+ import com .imgtec .hobbyist .fragments .menu .setupguide .SpannedAdapter ;
50
55
import com .imgtec .hobbyist .fragments .navigationdrawer .NDListeningFragment ;
51
56
import com .imgtec .hobbyist .fragments .navigationdrawer .NDMenuItem ;
52
57
import com .imgtec .hobbyist .utils .BackgroundExecutor ;
60
65
import com .imgtec .hobbyist .utils .WifiUtil ;
61
66
import com .imgtec .hobbyist .views .InstantAutoCompleteTextView ;
62
67
68
+ import java .io .StringReader ;
69
+ import java .io .StringWriter ;
63
70
import java .util .ArrayList ;
64
71
import java .util .Calendar ;
65
72
import java .util .Date ;
68
75
import java .util .Locale ;
69
76
import java .util .concurrent .CopyOnWriteArrayList ;
70
77
78
+ import javax .xml .transform .OutputKeys ;
79
+ import javax .xml .transform .Transformer ;
80
+ import javax .xml .transform .TransformerException ;
81
+ import javax .xml .transform .TransformerFactory ;
82
+ import javax .xml .transform .stream .StreamResult ;
83
+ import javax .xml .transform .stream .StreamSource ;
84
+
71
85
/**
72
86
* Fragment used to interact with Board through Flow.
73
87
* There are two modes: Commands and Messages.
@@ -80,9 +94,9 @@ public class InteractiveModeFragment extends NDListeningFragment implements Asyn
80
94
81
95
public static final String TAG = "InteractiveModeFragment" ;
82
96
83
- public static final String TX_MESSAGE = "TX message:\n " ;
84
- public static final String RX_MESSAGE = "RX message:\n " ;
85
- public static final String CMD_MESSAGE = "Received message:\n " ;
97
+ public static final String TX_MESSAGE = "<b> TX message:</b> " ;
98
+ public static final String RX_MESSAGE = "<b> RX message:</b> " ;
99
+ public static final String CMD_MESSAGE = "<b> Received message:</b> " ;
86
100
private RadioGroup interactiveModeChoice ;
87
101
private TextView deviceName ;
88
102
private EditText messageText ;
@@ -91,8 +105,8 @@ public class InteractiveModeFragment extends NDListeningFragment implements Asyn
91
105
private Button clearButton ;
92
106
private Button searchUsersButton ;
93
107
private ListView messagesListView ;
94
- private List <String > messageList = new CopyOnWriteArrayList <>();
95
- private ArrayAdapter < String > messageListAdapter ;
108
+ private List <Spanned > messageList = new CopyOnWriteArrayList <>();
109
+ private SpannedAdapter messageListAdapter ;
96
110
private ConnectivityReceiver connectionReceiver ;
97
111
98
112
private boolean isCommandMode = true ;
@@ -158,7 +172,7 @@ private void initFlowHelper() {
158
172
}
159
173
160
174
private void initListAdapter () {
161
- messageListAdapter = new ArrayAdapter <> (getActivity (), android .R .layout .simple_list_item_1 , messageList );
175
+ messageListAdapter = new SpannedAdapter (getActivity (), android .R .layout .simple_list_item_1 , messageList );
162
176
messagesListView .setAdapter (messageListAdapter );
163
177
}
164
178
@@ -319,8 +333,8 @@ public void execute() {
319
333
} catch (FlowException e ) {
320
334
DebugLogger .log (getClass ().getSimpleName (), e );
321
335
ActivitiesAndFragmentsHelper .showToast (appContext ,
322
- ErrorHtmlLogger .log (FlowEntities .getInstance (appContext ).getLastError ()),
323
- handler );
336
+ ErrorHtmlLogger .log (FlowEntities .getInstance (appContext ).getLastError ()),
337
+ handler );
324
338
}
325
339
}
326
340
});
@@ -332,7 +346,9 @@ public void execute() {
332
346
* @param commandString previously sent command text.
333
347
*/
334
348
private void showCommandTXMessage (String commandString ) {
335
- messageList .add (0 , TX_MESSAGE + DateFormatter .now (appContext ) + "\n " + commandString + "\n " );
349
+ messageList .add (0 , Html .fromHtml ("<font color='#006400'>" + TX_MESSAGE + "<br/>" +
350
+ DateFormatter .now (appContext ) + "<br/>" +
351
+ TextUtils .htmlEncode (commandString ) + "<br/></font>" ));
336
352
removeMessageIfListIsTooLong ();
337
353
notifyMessageListAdapter ();
338
354
}
@@ -373,7 +389,7 @@ public void onAsyncMessageResponse(MessagingEvent.AsyncMessageResponse response)
373
389
responseText = "" ;
374
390
break ;
375
391
}
376
- messageList .add (0 , "Command " + responseText );
392
+ messageList .add (0 , Html . fromHtml ( "<font color='fuchsia'><b>Response:</b> " + TextUtils . htmlEncode ( responseText ) + "</font>" ) );
377
393
removeMessageIfListIsTooLong ();
378
394
notifyMessageListAdapter ();
379
395
setCommandUIEnabled (true );
@@ -395,7 +411,7 @@ public void onCommandRXMessageReceived(final AsyncMessage msg) {
395
411
public void run () {
396
412
if (isCommandMode ) {
397
413
String commandText = commandEditText .getText ().toString ();
398
- if (commandText .equalsIgnoreCase (Command .REBOOT .getCommand ()) || commandText .equalsIgnoreCase (Command .REBOOT_SOFTAP .getCommand ())) {
414
+ if (commandText .equalsIgnoreCase (Command .REBOOT .getCommand ()) || commandText .equalsIgnoreCase (Command .GET_STATUS .getCommand ())) {
399
415
reactOnRebootCommand ();
400
416
}
401
417
}
@@ -426,14 +442,58 @@ public void onCommandMessageReceived(AsyncMessage msg) {
426
442
* @param msg AsyncMessage object which can be parsed to get additional data.
427
443
*/
428
444
private void showCommandRXMessage (AsyncMessage msg ) {
429
- messageList .add (0 , RX_MESSAGE + DateFormatter .now (appContext ) + "\n " + commandEditText .getText ().toString ()
430
- + " " + msg .getNode (AsyncMessageNodeKeys .RESPONSE_CODE ) + msg .getNode (AsyncMessageNodeKeys .RESPONSE_PARAMS ));
445
+ String html = RX_MESSAGE + "<br/>" +
446
+ DateFormatter .now (appContext ) + "<br/>" +
447
+ Html .fromHtml (commandEditText .getText ().toString ()).toString () + " → " +
448
+ Html .fromHtml (msg .getNode (AsyncMessageNodeKeys .RESPONSE_CODE )).toString () + "<br/>" ;
449
+ String params = msg .getNode (AsyncMessageNodeKeys .RESPONSE_PARAMS );
450
+ if (params != null && !params .equals ("" )) {
451
+ try {
452
+ html += "</font><font color='#4169E1'>" + formatXML (params ) + "</font>" ;
453
+ } catch (TransformerException e ) {
454
+ e .printStackTrace ();
455
+ Log .e ("InteractiveModeFragment.showCommandRXMessage" , "Failed to format response parameters from command" , e );
456
+ html += "</font><font color='red'>Error formatting response \" " + params + "\" </font>" ;
457
+ }
458
+ } else {
459
+ html += "</font><font color='black'>No response parameters</font>" ;
460
+ }
461
+ messageList .add (0 , Html .fromHtml ("<font color='blue'>" + html + "</font>" ));
431
462
removeMessageIfListIsTooLong ();
432
463
notifyMessageListAdapter ();
433
464
}
434
465
435
- private void showCommandMessage (AsyncMessage msg ) {
436
- messageList .add (0 , CMD_MESSAGE + DateFormatter .now (appContext ) + "\n " + msg .getNode (AsyncMessageNodeKeys .DETAILS ));
466
+ private String formatXML (String input ) throws TransformerException {
467
+ // adapted from http://stackoverflow.com/a/139096
468
+
469
+ // add on temporary tags to ensure correct parsing
470
+ // this is necessary as we are pretty-printing <i>part</i>
471
+ // of a XML document, so we allow a simple string (content)
472
+ // and allow multiple children at the "root" level
473
+ input = "<t>" + input + "</t>" ;
474
+
475
+ Transformer transformer = TransformerFactory .newInstance ().newTransformer ();
476
+ transformer .setOutputProperty (OutputKeys .INDENT , "yes" );
477
+ transformer .setOutputProperty (OutputKeys .OMIT_XML_DECLARATION , "yes" );
478
+ transformer .setOutputProperty ("{http://xml.apache.org/xslt}indent-amount" , "4" );
479
+ StreamResult result = new StreamResult (new StringWriter ());
480
+ StreamSource source = new StreamSource (new StringReader (input ));
481
+ transformer .transform (source , result );
482
+ String xmlString = result .getWriter ().toString ();
483
+
484
+ // remove temporary tags and newlines at beginning and end
485
+ xmlString = xmlString .substring (3 , xmlString .length ()-5 ).replaceAll ("(?m)^\\ s*\r ?\n " , "" );
486
+ if (xmlString .endsWith ("\n " )) xmlString = xmlString .substring (0 , xmlString .length ()-2 );
487
+
488
+ // if this is a one-line string then add a tab to the beginning
489
+ if (!xmlString .contains ("\n " )) xmlString = "\t " + xmlString ;
490
+
491
+ return TextUtils .htmlEncode (xmlString ).replace ("\n " , "<br>" ).replace ("\t " , " " ).replace (" " , " " );
492
+ }
493
+
494
+ private void showCommandMessage (AsyncMessage msg ) {
495
+ messageList .add (0 , Html .fromHtml ( CMD_MESSAGE + DateFormatter .now (appContext ) + "<br/>" +
496
+ Html .fromHtml (msg .getNode (AsyncMessageNodeKeys .DETAILS )).toString ()));
437
497
removeMessageIfListIsTooLong ();
438
498
notifyMessageListAdapter ();
439
499
}
@@ -492,8 +552,11 @@ private void showTextMessagesFromHourAgoOn() {
492
552
* @param msg AsyncMessage object which can be parsed to get additional data.
493
553
*/
494
554
private void addTextMessage (AsyncMessage msg ) {
495
- messageList .add (0 , DateFormatter .formatForDisplay (msg .getNode (AsyncMessageNodeKeys .SENT_WITH_TYPE_INFO ), appContext )
496
- + "\n " + msg .getNode (AsyncMessageNodeKeys .FROM ) + ":\n " + msg .getNode (AsyncMessageNodeKeys .MESSAGE ));
555
+ messageList .add (0 , Html .fromHtml (DateFormatter .formatForDisplay (msg .getNode (AsyncMessageNodeKeys .SENT_WITH_TYPE_INFO ), appContext ) + "<br/>" +
556
+ msg .getNode (AsyncMessageNodeKeys .FROM ) + ":<br/>" +
557
+ Html .fromHtml (msg .getNode (AsyncMessageNodeKeys .MESSAGE )).toString ()
558
+ )
559
+ );
497
560
}
498
561
499
562
/**
0 commit comments