/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.gallery3d.ui; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.text.format.Formatter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; import com.android.gallery3d.R; import com.android.gallery3d.app.AbstractGalleryActivity; import com.android.gallery3d.common.Utils; import com.android.gallery3d.data.MediaDetails; import com.android.gallery3d.ui.DetailsAddressResolver.AddressResolvingListener; import com.android.gallery3d.ui.DetailsHelper.CloseListener; import com.android.gallery3d.ui.DetailsHelper.DetailsSource; import com.android.gallery3d.ui.DetailsHelper.DetailsViewContainer; import com.android.gallery3d.ui.DetailsHelper.ResolutionResolvingListener; import java.util.ArrayList; import java.util.Map.Entry; public class DialogDetailsView implements DetailsViewContainer { @SuppressWarnings("unused") private static final String TAG = "DialogDetailsView"; private final AbstractGalleryActivity mActivity; private DetailsAdapter mAdapter; private MediaDetails mDetails; private final DetailsSource mSource; private int mIndex; private Dialog mDialog; private CloseListener mListener; public DialogDetailsView(AbstractGalleryActivity activity, DetailsSource source) { mActivity = activity; mSource = source; } @Override public void show() { reloadDetails(); mDialog.show(); } @Override public void hide() { mDialog.hide(); } @Override public void reloadDetails() { int index = mSource.setIndex(); if (index == -1) return; MediaDetails details = mSource.getDetails(); if (details != null) { if (mIndex == index && mDetails == details) return; mIndex = index; mDetails = details; setDetails(details); } } private void setDetails(MediaDetails details) { mAdapter = new DetailsAdapter(details); String title = String.format( mActivity.getAndroidContext().getString(R.string.details_title), mIndex + 1, mSource.size()); ListView detailsList = (ListView) LayoutInflater.from(mActivity.getAndroidContext()).inflate( R.layout.details_list, null, false); detailsList.setAdapter(mAdapter); mDialog = new AlertDialog.Builder(mActivity) .setView(detailsList) .setTitle(title) .setPositiveButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int whichButton) { mDialog.dismiss(); } }) .create(); mDialog.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { if (mListener != null) { mListener.onClose(); } } }); } private class DetailsAdapter extends BaseAdapter implements AddressResolvingListener, ResolutionResolvingListener { private final ArrayList mItems; private int mLocationIndex; private int mWidthIndex = -1; private int mHeightIndex = -1; public DetailsAdapter(MediaDetails details) { Context context = mActivity.getAndroidContext(); mItems = new ArrayList(details.size()); mLocationIndex = -1; setDetails(context, details); } private void setDetails(Context context, MediaDetails details) { boolean resolutionIsValid = true; String path = null; for (Entry detail : details) { String value; switch (detail.getKey()) { case MediaDetails.INDEX_LOCATION: { double[] latlng = (double[]) detail.getValue(); mLocationIndex = mItems.size(); value = DetailsHelper.resolveAddress(mActivity, latlng, this); break; } case MediaDetails.INDEX_SIZE: { value = Formatter.formatFileSize( context, (Long) detail.getValue()); break; } case MediaDetails.INDEX_WHITE_BALANCE: { value = "1".equals(detail.getValue()) ? context.getString(R.string.manual) : context.getString(R.string.auto); break; } case MediaDetails.INDEX_FLASH: { MediaDetails.FlashState flash = (MediaDetails.FlashState) detail.getValue(); // TODO: camera doesn't fill in the complete values, show more information // when it is fixed. if (flash.isFlashFired()) { value = context.getString(R.string.flash_on); } else { value = context.getString(R.string.flash_off); } break; } case MediaDetails.INDEX_EXPOSURE_TIME: { value = (String) detail.getValue(); double time = Double.valueOf(value); if (time < 1.0f) { value = String.format("1/%d", (int) (0.5f + 1 / time)); } else { int integer = (int) time; time -= integer; value = String.valueOf(integer) + "''"; if (time > 0.0001) { value += String.format(" 1/%d", (int) (0.5f + 1 / time)); } } break; } case MediaDetails.INDEX_WIDTH: mWidthIndex = mItems.size(); value = detail.getValue().toString(); if (value.equalsIgnoreCase("0")) { value = context.getString(R.string.unknown); resolutionIsValid = false; } break; case MediaDetails.INDEX_HEIGHT: { mHeightIndex = mItems.size(); value = detail.getValue().toString(); if (value.equalsIgnoreCase("0")) { value = context.getString(R.string.unknown); resolutionIsValid = false; } break; } case MediaDetails.INDEX_PATH: // Get the path and then fall through to the default case path = detail.getValue().toString(); default: { Object valueObj = detail.getValue(); // This shouldn't happen, log its key to help us diagnose the problem. if (valueObj == null) { Utils.fail("%s's value is Null", DetailsHelper.getDetailsName(context, detail.getKey())); } value = valueObj.toString(); } } int key = detail.getKey(); if (details.hasUnit(key)) { value = String.format("%s: %s %s", DetailsHelper.getDetailsName( context, key), value, context.getString(details.getUnit(key))); } else { value = String.format("%s: %s", DetailsHelper.getDetailsName( context, key), value); } mItems.add(value); if (!resolutionIsValid) { DetailsHelper.resolveResolution(path, this); } } } @Override public boolean areAllItemsEnabled() { return false; } @Override public boolean isEnabled(int position) { return false; } @Override public int getCount() { return mItems.size(); } @Override public Object getItem(int position) { return mDetails.getDetail(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView tv; if (convertView == null) { tv = (TextView) LayoutInflater.from(mActivity.getAndroidContext()).inflate( R.layout.details, parent, false); } else { tv = (TextView) convertView; } tv.setText(mItems.get(position)); return tv; } @Override public void onAddressAvailable(String address) { mItems.set(mLocationIndex, address); notifyDataSetChanged(); } @Override public void onResolutionAvailable(int width, int height) { if (width == 0 || height == 0) return; // Update the resolution with the new width and height Context context = mActivity.getAndroidContext(); String widthString = String.format("%s: %d", DetailsHelper.getDetailsName( context, MediaDetails.INDEX_WIDTH), width); String heightString = String.format("%s: %d", DetailsHelper.getDetailsName( context, MediaDetails.INDEX_HEIGHT), height); mItems.set(mWidthIndex, String.valueOf(widthString)); mItems.set(mHeightIndex, String.valueOf(heightString)); notifyDataSetChanged(); } } @Override public void setCloseListener(CloseListener listener) { mListener = listener; } }