1 /* 2 * Copyright (C) 2007-2008 Esmertec AG. 3 * Copyright (C) 2007-2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package com.android.im.app; 18 19 import com.android.im.IImConnection; 20 import com.android.im.R; 21 import com.android.im.engine.ImErrorInfo; 22 import com.android.im.engine.Presence; 23 import com.android.im.plugin.ImpsConfigNames; 24 import com.android.im.provider.Imps; 25 import com.google.android.collect.Lists; 26 27 import android.app.Activity; 28 import android.app.AlertDialog; 29 import android.content.Context; 30 import android.content.DialogInterface; 31 import android.graphics.drawable.Drawable; 32 import android.os.RemoteException; 33 import android.text.TextUtils; 34 import android.util.AttributeSet; 35 import android.view.KeyEvent; 36 import android.view.View; 37 import android.view.ViewGroup; 38 import android.widget.EditText; 39 import android.widget.ImageButton; 40 import android.widget.LinearLayout; 41 import android.widget.TextView; 42 43 import java.util.List; 44 45 public class UserPresenceView extends LinearLayout { 46 47 private ImageButton mStatusDialogButton; 48 49 // views of the popup window 50 TextView mStatusBar; 51 52 private final SimpleAlertHandler mHandler; 53 54 private IImConnection mConn; 55 private long mProviderId; 56 Presence mPresence; 57 58 private String mLastStatusText; 59 final List<StatusItem> mStatusItems = Lists.newArrayList(); 60 61 public UserPresenceView(Context context, AttributeSet attrs) { 62 super(context, attrs); 63 mHandler = new SimpleAlertHandler((Activity)context); 64 } 65 66 @Override 67 protected void onFinishInflate() { 68 super.onFinishInflate(); 69 70 mStatusDialogButton = (ImageButton)findViewById(R.id.statusDropDownButton); 71 mStatusDialogButton.setOnClickListener(new OnClickListener() { 72 public void onClick(View v) { 73 showStatusListDialog(); 74 } 75 }); 76 } 77 78 private void showStatusListDialog() { 79 if (mConn == null) { 80 return; 81 } 82 83 AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 84 builder.setAdapter(getStatusAdapter(), 85 new DialogInterface.OnClickListener() { 86 public void onClick(DialogInterface dialog, int which) { 87 StatusItem item = mStatusItems.get(which); 88 int oldStatus = mPresence.getStatus(); 89 if (item.getStatus() != oldStatus) { 90 updatePresence(item.getStatus(), item.getText().toString()); 91 } 92 } 93 }); 94 builder.show(); 95 } 96 97 private StatusIconAdapter getStatusAdapter() { 98 try { 99 mStatusItems.clear(); 100 int[] supportedStatus = mConn.getSupportedPresenceStatus(); 101 for (int i = 0; i < supportedStatus.length; i++) { 102 int s = PresenceUtils.convertStatus(supportedStatus[i]); 103 if (s == Imps.Presence.OFFLINE) { 104 s = Imps.Presence.INVISIBLE; 105 } 106 ImApp app = ImApp.getApplication((Activity)mContext); 107 BrandingResources brandingRes = app.getBrandingResource(mProviderId); 108 Drawable icon = brandingRes.getDrawable(PresenceUtils.getStatusIconId(s)); 109 String text = brandingRes.getString(PresenceUtils.getStatusStringRes(s)); 110 mStatusItems.add(new StatusItem(supportedStatus[i], icon, text)); 111 } 112 } catch (RemoteException e) { 113 mHandler.showServiceErrorAlert(); 114 } 115 116 return new StatusIconAdapter(mContext, mStatusItems); 117 } 118 119 void updateStatusText() { 120 String newStatusText = mStatusBar.getText().toString(); 121 if (TextUtils.isEmpty(newStatusText)) { 122 newStatusText = ""; 123 } 124 if (!newStatusText.equals(mLastStatusText)) { 125 updatePresence(-1, newStatusText); 126 } 127 } 128 129 public void setConnection(IImConnection conn) { 130 mConn = conn; 131 try { 132 mPresence = conn.getUserPresence(); 133 mProviderId = conn.getProviderId(); 134 } catch (RemoteException e) { 135 mHandler.showServiceErrorAlert(); 136 } 137 if (mPresence == null) { 138 mPresence = new Presence(); 139 } 140 updateView(); 141 } 142 143 private void updateView() { 144 ImApp app = ImApp.getApplication((Activity)mContext); 145 BrandingResources brandingRes = app.getBrandingResource(mProviderId); 146 int status = PresenceUtils.convertStatus(mPresence.getStatus()); 147 mStatusDialogButton.setImageDrawable(brandingRes.getDrawable( 148 PresenceUtils.getStatusIconId(status))); 149 150 String statusText = mPresence.getStatusText(); 151 if (TextUtils.isEmpty(statusText)) { 152 statusText = brandingRes.getString(PresenceUtils.getStatusStringRes(status)); 153 } 154 mLastStatusText = statusText; 155 156 if (mStatusBar == null) { 157 mStatusBar = initStatusBar(mProviderId); 158 } 159 mStatusBar.setText(statusText); 160 161 // Disable the user to edit the custom status text because 162 // the AIM and MSN server don't support it now. 163 ProviderDef provider = app.getProvider(mProviderId); 164 String providerName = provider == null ? null : provider.mName; 165 if (Imps.ProviderNames.AIM.equals(providerName) 166 || Imps.ProviderNames.MSN.equals(providerName)) { 167 mStatusBar.setFocusable(false); 168 } 169 } 170 171 private TextView initStatusBar(long providerId) { 172 String value = Imps.ProviderSettings.getStringValue( 173 mContext.getContentResolver(), providerId, 174 ImpsConfigNames.SUPPORT_USER_DEFINED_PRESENCE); 175 176 if ("true".equalsIgnoreCase(value)) { 177 EditText statusEdit = (EditText) findViewById(R.id.statusEdit); 178 statusEdit.setVisibility(View.VISIBLE); 179 statusEdit.setOnKeyListener(new OnKeyListener() { 180 public boolean onKey(View v, int keyCode, KeyEvent event) { 181 if (KeyEvent.ACTION_DOWN == event.getAction()) { 182 switch (keyCode) { 183 case KeyEvent.KEYCODE_DPAD_CENTER: 184 case KeyEvent.KEYCODE_ENTER: 185 updateStatusText(); 186 return true; 187 } 188 } 189 return false; 190 } 191 }); 192 193 statusEdit.setOnFocusChangeListener(new View.OnFocusChangeListener(){ 194 public void onFocusChange(View v, boolean hasFocus) { 195 if (!hasFocus) { 196 updateStatusText(); 197 } 198 } 199 }); 200 201 return statusEdit; 202 } else { 203 TextView statusView = (TextView) findViewById(R.id.statusView); 204 statusView.setVisibility(View.VISIBLE); 205 return statusView; 206 } 207 } 208 209 void updatePresence(int status, String statusText) { 210 if (mPresence == null) { 211 // We haven't get the connection yet. Don't allow to update presence now. 212 return; 213 } 214 215 Presence newPresence = new Presence(mPresence); 216 217 if (status != -1) { 218 newPresence.setStatus(status); 219 } 220 newPresence.setStatusText(statusText); 221 222 try { 223 int res = mConn.updateUserPresence(newPresence); 224 if (res != ImErrorInfo.NO_ERROR) { 225 mHandler.showAlert(R.string.error, 226 ErrorResUtils.getErrorRes(getResources(), res)); 227 } else { 228 mPresence = newPresence; 229 updateView(); 230 } 231 } catch (RemoteException e) { 232 mHandler.showServiceErrorAlert(); 233 } 234 } 235 236 private static class StatusItem implements ImageListAdapter.ImageListItem { 237 private final int mStatus; 238 private final Drawable mIcon; 239 private final String mText; 240 241 public StatusItem(int status, Drawable icon, String text) { 242 mStatus = status; 243 mIcon = icon; 244 mText = text; 245 } 246 247 public Drawable getDrawable() { 248 return mIcon; 249 } 250 251 public CharSequence getText() { 252 return mText; 253 } 254 255 public int getStatus() { 256 return mStatus; 257 } 258 } 259 260 private static class StatusIconAdapter extends ImageListAdapter { 261 public StatusIconAdapter(Context context, List<StatusItem> data) { 262 super(context, data); 263 } 264 265 @Override 266 public long getItemId(int position) { 267 StatusItem item = (StatusItem)getItem(position); 268 return item.getStatus(); 269 } 270 271 @Override 272 public View getView(int position, View convertView, ViewGroup parent) { 273 View view = super.getView(position, convertView, parent); 274 return view; 275 } 276 } 277 } 278