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