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