1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.gallery3d.ui; 18 19 import android.app.AlertDialog; 20 import android.app.Dialog; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.DialogInterface.OnDismissListener; 24 import android.text.format.Formatter; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.view.ViewGroup; 28 import android.widget.BaseAdapter; 29 import android.widget.ListView; 30 import android.widget.TextView; 31 32 import com.android.gallery3d.R; 33 import com.android.gallery3d.app.AbstractGalleryActivity; 34 import com.android.gallery3d.common.Utils; 35 import com.android.gallery3d.data.MediaDetails; 36 import com.android.gallery3d.ui.DetailsAddressResolver.AddressResolvingListener; 37 import com.android.gallery3d.ui.DetailsHelper.CloseListener; 38 import com.android.gallery3d.ui.DetailsHelper.DetailsSource; 39 import com.android.gallery3d.ui.DetailsHelper.DetailsViewContainer; 40 41 import java.util.ArrayList; 42 import java.util.Map.Entry; 43 44 public class DialogDetailsView implements DetailsViewContainer { 45 @SuppressWarnings("unused") 46 private static final String TAG = "DialogDetailsView"; 47 48 private final AbstractGalleryActivity mActivity; 49 private DetailsAdapter mAdapter; 50 private MediaDetails mDetails; 51 private final DetailsSource mSource; 52 private int mIndex; 53 private Dialog mDialog; 54 private CloseListener mListener; 55 56 public DialogDetailsView(AbstractGalleryActivity activity, DetailsSource source) { 57 mActivity = activity; 58 mSource = source; 59 } 60 61 @Override 62 public void show() { 63 reloadDetails(); 64 mDialog.show(); 65 } 66 67 @Override 68 public void hide() { 69 mDialog.hide(); 70 } 71 72 @Override 73 public void reloadDetails() { 74 int index = mSource.setIndex(); 75 if (index == -1) return; 76 MediaDetails details = mSource.getDetails(); 77 if (details != null) { 78 if (mIndex == index && mDetails == details) return; 79 mIndex = index; 80 mDetails = details; 81 setDetails(details); 82 } 83 } 84 85 private void setDetails(MediaDetails details) { 86 mAdapter = new DetailsAdapter(details); 87 String title = String.format( 88 mActivity.getAndroidContext().getString(R.string.details_title), 89 mIndex + 1, mSource.size()); 90 ListView detailsList = (ListView) LayoutInflater.from(mActivity.getAndroidContext()).inflate( 91 R.layout.details_list, null, false); 92 detailsList.setAdapter(mAdapter); 93 mDialog = new AlertDialog.Builder(mActivity) 94 .setView(detailsList) 95 .setTitle(title) 96 .setPositiveButton(R.string.close, new DialogInterface.OnClickListener() { 97 @Override 98 public void onClick(DialogInterface dialog, int whichButton) { 99 mDialog.dismiss(); 100 } 101 }) 102 .create(); 103 104 mDialog.setOnDismissListener(new OnDismissListener() { 105 @Override 106 public void onDismiss(DialogInterface dialog) { 107 if (mListener != null) { 108 mListener.onClose(); 109 } 110 } 111 }); 112 } 113 114 private class DetailsAdapter extends BaseAdapter implements AddressResolvingListener { 115 private final ArrayList<String> mItems; 116 private int mLocationIndex; 117 118 public DetailsAdapter(MediaDetails details) { 119 Context context = mActivity.getAndroidContext(); 120 mItems = new ArrayList<String>(details.size()); 121 mLocationIndex = -1; 122 setDetails(context, details); 123 } 124 125 private void setDetails(Context context, MediaDetails details) { 126 for (Entry<Integer, Object> detail : details) { 127 String value; 128 switch (detail.getKey()) { 129 case MediaDetails.INDEX_LOCATION: { 130 double[] latlng = (double[]) detail.getValue(); 131 mLocationIndex = mItems.size(); 132 value = DetailsHelper.resolveAddress(mActivity, latlng, this); 133 break; 134 } 135 case MediaDetails.INDEX_SIZE: { 136 value = Formatter.formatFileSize( 137 context, (Long) detail.getValue()); 138 break; 139 } 140 case MediaDetails.INDEX_WHITE_BALANCE: { 141 value = "1".equals(detail.getValue()) 142 ? context.getString(R.string.manual) 143 : context.getString(R.string.auto); 144 break; 145 } 146 case MediaDetails.INDEX_FLASH: { 147 MediaDetails.FlashState flash = 148 (MediaDetails.FlashState) detail.getValue(); 149 // TODO: camera doesn't fill in the complete values, show more information 150 // when it is fixed. 151 if (flash.isFlashFired()) { 152 value = context.getString(R.string.flash_on); 153 } else { 154 value = context.getString(R.string.flash_off); 155 } 156 break; 157 } 158 case MediaDetails.INDEX_EXPOSURE_TIME: { 159 value = (String) detail.getValue(); 160 double time = Double.valueOf(value); 161 if (time < 1.0f) { 162 value = String.format("1/%d", (int) (0.5f + 1 / time)); 163 } else { 164 int integer = (int) time; 165 time -= integer; 166 value = String.valueOf(integer) + "''"; 167 if (time > 0.0001) { 168 value += String.format(" 1/%d", (int) (0.5f + 1 / time)); 169 } 170 } 171 break; 172 } 173 default: { 174 Object valueObj = detail.getValue(); 175 // This shouldn't happen, log its key to help us diagnose the problem. 176 if (valueObj == null) { 177 Utils.fail("%s's value is Null", 178 DetailsHelper.getDetailsName(context, detail.getKey())); 179 } 180 value = valueObj.toString(); 181 } 182 } 183 int key = detail.getKey(); 184 if (details.hasUnit(key)) { 185 value = String.format("%s: %s %s", DetailsHelper.getDetailsName( 186 context, key), value, context.getString(details.getUnit(key))); 187 } else { 188 value = String.format("%s: %s", DetailsHelper.getDetailsName( 189 context, key), value); 190 } 191 mItems.add(value); 192 } 193 } 194 195 @Override 196 public boolean areAllItemsEnabled() { 197 return false; 198 } 199 200 @Override 201 public boolean isEnabled(int position) { 202 return false; 203 } 204 205 @Override 206 public int getCount() { 207 return mItems.size(); 208 } 209 210 @Override 211 public Object getItem(int position) { 212 return mDetails.getDetail(position); 213 } 214 215 @Override 216 public long getItemId(int position) { 217 return position; 218 } 219 220 @Override 221 public View getView(int position, View convertView, ViewGroup parent) { 222 TextView tv; 223 if (convertView == null) { 224 tv = (TextView) LayoutInflater.from(mActivity.getAndroidContext()).inflate( 225 R.layout.details, parent, false); 226 } else { 227 tv = (TextView) convertView; 228 } 229 tv.setText(mItems.get(position)); 230 return tv; 231 } 232 233 @Override 234 public void onAddressAvailable(String address) { 235 mItems.set(mLocationIndex, address); 236 notifyDataSetChanged(); 237 } 238 } 239 240 @Override 241 public void setCloseListener(CloseListener listener) { 242 mListener = listener; 243 } 244 } 245