1 /* 2 * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game 3 * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 */ 19 20 package org.hedgewars.hedgeroid.netplay; 21 22 import java.util.Collection; 23 import java.util.Collections; 24 import java.util.Date; 25 import java.util.LinkedList; 26 import java.util.List; 27 28 import org.hedgewars.hedgeroid.R; 29 import org.hedgewars.hedgeroid.frontlib.Frontlib; 30 31 import android.content.Context; 32 import android.graphics.Color; 33 import android.graphics.Typeface; 34 import android.text.Html; 35 import android.text.Spannable; 36 import android.text.SpannableString; 37 import android.text.SpannableStringBuilder; 38 import android.text.Spanned; 39 import android.text.TextUtils; 40 import android.text.format.DateFormat; 41 import android.text.style.ForegroundColorSpan; 42 import android.text.style.RelativeSizeSpan; 43 import android.text.style.StyleSpan; 44 import android.util.Log; 45 46 public class MessageLog { 47 private static final int BACKLOG_LINES = 200; 48 49 private static final int INFO_COLOR = Color.GRAY; 50 private static final int PLAYERINFO_COLOR = Color.GREEN; 51 private static final int CHAT_COLOR = Color.GREEN; 52 private static final int MECHAT_COLOR = Color.CYAN; 53 private static final int WARN_COLOR = Color.RED; 54 private static final int ERROR_COLOR = Color.RED; 55 56 private final Context context; 57 private List<Listener> observers = new LinkedList<Listener>(); 58 private List<CharSequence> log = new LinkedList<CharSequence>(); 59 MessageLog(Context context)60 public MessageLog(Context context) { 61 this.context = context; 62 } 63 makeLogTime()64 private Spanned makeLogTime() { 65 String time = DateFormat.getTimeFormat(context).format(new Date()); 66 return withColor("[" + time + "] ", INFO_COLOR); 67 } 68 span(CharSequence s, Object o)69 private static Spanned span(CharSequence s, Object o) { 70 Spannable spannable = new SpannableString(s); 71 spannable.setSpan(o, 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 72 return spannable; 73 } 74 withColor(CharSequence s, int color)75 private static Spanned withColor(CharSequence s, int color) { 76 return span(s, new ForegroundColorSpan(color)); 77 } 78 bold(CharSequence s)79 private static Spanned bold(CharSequence s) { 80 return span(s, new StyleSpan(Typeface.BOLD)); 81 } 82 append(CharSequence msg)83 private void append(CharSequence msg) { 84 SpannableStringBuilder ssb = new SpannableStringBuilder(); 85 ssb.append(makeLogTime()).append(msg); 86 appendRaw(ssb); 87 } 88 appendRaw(CharSequence msg)89 private void appendRaw(CharSequence msg) { 90 if(log.size() > BACKLOG_LINES) { 91 log.remove(0); 92 for(Listener o : observers) { 93 o.lineRemoved(); 94 } 95 } 96 log.add(msg); 97 for(Listener o : observers) { 98 o.lineAdded(msg); 99 } 100 } 101 appendPlayerJoin(String playername)102 void appendPlayerJoin(String playername) { 103 append(withColor("***" + context.getResources().getString(R.string.log_player_join, playername), INFO_COLOR)); 104 } 105 appendPlayerLeave(String playername, String partMsg)106 void appendPlayerLeave(String playername, String partMsg) { 107 String msg = "***"; 108 if(partMsg != null) { 109 msg += context.getResources().getString(R.string.log_player_leave_with_msg, playername, partMsg); 110 } else { 111 msg += context.getResources().getString(R.string.log_player_leave, playername); 112 } 113 append(withColor(msg, INFO_COLOR)); 114 } 115 appendChat(String playerName, String msg)116 void appendChat(String playerName, String msg) { 117 if(msg.startsWith("/me ")) { 118 append(withColor("*"+playerName+" "+msg.substring(4), MECHAT_COLOR)); 119 } else { 120 Spanned name = bold(playerName+": "); 121 Spanned fullMessage = withColor(TextUtils.concat(name, msg), CHAT_COLOR); 122 append(fullMessage); 123 } 124 } 125 appendMessage(int type, String msg)126 void appendMessage(int type, String msg) { 127 switch(type) { 128 case Frontlib.NETCONN_MSG_TYPE_ERROR: 129 append(withColor("***"+msg, ERROR_COLOR)); 130 break; 131 case Frontlib.NETCONN_MSG_TYPE_WARNING: 132 append(withColor("***"+msg, WARN_COLOR)); 133 break; 134 case Frontlib.NETCONN_MSG_TYPE_PLAYERINFO: 135 append(withColor(msg.replace("\n", " "), PLAYERINFO_COLOR)); 136 break; 137 case Frontlib.NETCONN_MSG_TYPE_SERVERMESSAGE: 138 appendRaw(span(TextUtils.concat("\n", Html.fromHtml(msg), "\n"), new RelativeSizeSpan(1.5f))); 139 break; 140 default: 141 Log.e("MessageLog", "Unknown messagetype "+type); 142 } 143 } 144 clear()145 void clear() { 146 for(Listener o : observers) { 147 o.clear(); 148 } 149 log.clear(); 150 } 151 addListener(Listener o)152 public void addListener(Listener o) { 153 observers.add(o); 154 } 155 removeListener(Listener o)156 public void removeListener(Listener o) { 157 observers.remove(o); 158 } 159 160 public static interface Listener { lineAdded(CharSequence text)161 void lineAdded(CharSequence text); lineRemoved()162 void lineRemoved(); clear()163 void clear(); 164 } 165 getLog()166 public Collection<CharSequence> getLog() { 167 return Collections.unmodifiableList(log); 168 } 169 } 170