1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 package org.mozilla.gecko.overlays.ui; 6 7 import java.util.Collection; 8 9 import org.mozilla.gecko.AppConstants; 10 import org.mozilla.gecko.R; 11 import org.mozilla.gecko.db.RemoteClient; 12 import org.mozilla.gecko.overlays.ui.SendTabList.State; 13 14 import android.app.AlertDialog; 15 import android.content.Context; 16 import android.graphics.drawable.Drawable; 17 import android.view.View; 18 import android.view.View.OnClickListener; 19 import android.view.ViewGroup; 20 import android.widget.ArrayAdapter; 21 22 public class SendTabDeviceListArrayAdapter extends ArrayAdapter<RemoteClient> { 23 @SuppressWarnings("unused") 24 private static final String LOGTAG = "GeckoSendTabAdapter"; 25 26 private State currentState; 27 28 // String to display when in a "button-like" special state. Instead of using a 29 // RemoteClient we override the rendering using this string. 30 private String dummyRecordName; 31 32 private final SendTabTargetSelectedListener listener; 33 34 private Collection<RemoteClient> records; 35 36 // The AlertDialog to show in the event the record is pressed while in the SHOW_DEVICES state. 37 // This will show the user a prompt to select a device from a longer list of devices. 38 private AlertDialog dialog; 39 SendTabDeviceListArrayAdapter(Context context, SendTabTargetSelectedListener aListener)40 public SendTabDeviceListArrayAdapter(Context context, SendTabTargetSelectedListener aListener) { 41 super(context, R.layout.overlay_share_send_tab_item, R.id.overlaybtn_label); 42 43 listener = aListener; 44 45 // We do this manually and avoid multiple notifications when doing compound operations. 46 setNotifyOnChange(false); 47 } 48 49 /** 50 * Get an array of the contents of this adapter were it in the LIST state. 51 * Useful for determining the "real" contents of the adapter. 52 */ toArray()53 public RemoteClient[] toArray() { 54 return records.toArray(new RemoteClient[records.size()]); 55 } 56 setRemoteClientsList(Collection<RemoteClient> remoteClientsList)57 public void setRemoteClientsList(Collection<RemoteClient> remoteClientsList) { 58 records = remoteClientsList; 59 updateRecordList(); 60 } 61 62 /** 63 * Ensure the contents of the Adapter are synchronised with the `records` field. This may not 64 * be the case if records has recently changed, or if we have experienced a state change. 65 */ updateRecordList()66 public void updateRecordList() { 67 if (currentState != State.LIST) { 68 return; 69 } 70 71 clear(); 72 73 setNotifyOnChange(false); // So we don't notify for each add. 74 addAll(records); 75 76 notifyDataSetChanged(); 77 } 78 79 @Override getView(final int position, View convertView, ViewGroup parent)80 public View getView(final int position, View convertView, ViewGroup parent) { 81 final Context context = getContext(); 82 83 // Reuse View objects if they exist. 84 OverlayDialogButton row = (OverlayDialogButton) convertView; 85 if (row == null) { 86 row = (OverlayDialogButton) View.inflate(context, R.layout.overlay_share_send_tab_item, null); 87 } 88 89 // The first view in the list has a unique style. 90 if (position == 0) { 91 row.setBackgroundResource(R.drawable.overlay_share_button_background_first); 92 } else { 93 row.setBackgroundResource(R.drawable.overlay_share_button_background); 94 } 95 96 if (currentState != State.LIST) { 97 // If we're in a special "Button-like" state, use the override string and a generic icon. 98 final Drawable sendTabIcon = context.getResources().getDrawable(R.drawable.shareplane); 99 row.setText(dummyRecordName); 100 row.setDrawable(sendTabIcon); 101 } 102 103 // If we're just a button to launch the dialog, set the listener and abort. 104 if (currentState == State.SHOW_DEVICES) { 105 row.setOnClickListener(new OnClickListener() { 106 @Override 107 public void onClick(View view) { 108 dialog.show(); 109 } 110 }); 111 112 return row; 113 } 114 115 // The remaining states delegate to the SentTabTargetSelectedListener. 116 final RemoteClient remoteClient = getItem(position); 117 if (currentState == State.LIST) { 118 final Drawable clientIcon = context.getResources().getDrawable(getImage(remoteClient)); 119 row.setText(remoteClient.name); 120 row.setDrawable(clientIcon); 121 122 final String listenerGUID = remoteClient.guid; 123 124 row.setOnClickListener(new OnClickListener() { 125 @Override 126 public void onClick(View view) { 127 listener.onSendTabTargetSelected(listenerGUID); 128 } 129 }); 130 } else { 131 row.setOnClickListener(new OnClickListener() { 132 @Override 133 public void onClick(View view) { 134 listener.onSendTabActionSelected(); 135 } 136 }); 137 } 138 139 return row; 140 } 141 getImage(RemoteClient record)142 private static int getImage(RemoteClient record) { 143 if ("mobile".equals(record.deviceType)) { 144 return R.drawable.device_mobile; 145 } 146 147 return R.drawable.device_desktop; 148 } 149 switchState(State newState)150 public void switchState(State newState) { 151 if (currentState == newState) { 152 return; 153 } 154 155 currentState = newState; 156 157 switch (newState) { 158 case LIST: 159 updateRecordList(); 160 break; 161 case NONE: 162 showDummyRecord(getContext().getResources().getString(R.string.overlay_share_send_tab_btn_label)); 163 break; 164 case SHOW_DEVICES: 165 showDummyRecord(getContext().getResources().getString(R.string.overlay_share_send_other)); 166 break; 167 default: 168 throw new IllegalStateException("Unexpected state transition: " + newState); 169 } 170 } 171 172 /** 173 * Set the dummy override string to the given value and clear the list. 174 */ showDummyRecord(String name)175 private void showDummyRecord(String name) { 176 dummyRecordName = name; 177 clear(); 178 add(null); 179 notifyDataSetChanged(); 180 } 181 setDialog(AlertDialog aDialog)182 public void setDialog(AlertDialog aDialog) { 183 dialog = aDialog; 184 } 185 } 186