1/*
2 * Copyright (C) 2008 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.calculator2;
18
19import android.app.Activity;
20import android.content.res.Resources;
21import android.content.res.TypedArray;
22import android.os.Bundle;
23import android.os.Parcelable;
24import android.support.v4.view.PagerAdapter;
25import android.support.v4.view.ViewPager;
26import android.util.Log;
27import android.view.KeyEvent;
28import android.view.LayoutInflater;
29import android.view.Menu;
30import android.view.MenuItem;
31import android.view.View;
32import android.view.View.OnClickListener;
33import android.view.ViewConfiguration;
34import android.view.ViewGroup;
35import android.view.WindowManager;
36import android.widget.PopupMenu;
37import android.widget.PopupMenu.OnMenuItemClickListener;
38
39public class Calculator extends Activity implements PanelSwitcher.Listener, Logic.Listener,
40        OnClickListener, OnMenuItemClickListener {
41    EventListener mListener = new EventListener();
42    private CalculatorDisplay mDisplay;
43    private Persist mPersist;
44    private History mHistory;
45    private Logic mLogic;
46    private ViewPager mPager;
47    private View mClearButton;
48    private View mBackspaceButton;
49    private View mOverflowMenuButton;
50
51    static final int BASIC_PANEL    = 0;
52    static final int ADVANCED_PANEL = 1;
53
54    private static final String LOG_TAG = "Calculator";
55    private static final boolean DEBUG  = false;
56    private static final boolean LOG_ENABLED = false;
57    private static final String STATE_CURRENT_VIEW = "state-current-view";
58
59    @Override
60    public void onCreate(Bundle state) {
61        super.onCreate(state);
62
63        // Disable IME for this application
64        getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
65                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
66
67        setContentView(R.layout.main);
68        mPager = (ViewPager) findViewById(R.id.panelswitch);
69        if (mPager != null) {
70            mPager.setAdapter(new PageAdapter(mPager));
71        } else {
72            // Single page UI
73            final TypedArray buttons = getResources().obtainTypedArray(R.array.buttons);
74            for (int i = 0; i < buttons.length(); i++) {
75                setOnClickListener(null, buttons.getResourceId(i, 0));
76            }
77            buttons.recycle();
78        }
79
80        if (mClearButton == null) {
81            mClearButton = findViewById(R.id.clear);
82            mClearButton.setOnClickListener(mListener);
83            mClearButton.setOnLongClickListener(mListener);
84        }
85        if (mBackspaceButton == null) {
86            mBackspaceButton = findViewById(R.id.del);
87            mBackspaceButton.setOnClickListener(mListener);
88            mBackspaceButton.setOnLongClickListener(mListener);
89        }
90
91        mPersist = new Persist(this);
92        mPersist.load();
93
94        mHistory = mPersist.history;
95
96        mDisplay = (CalculatorDisplay) findViewById(R.id.display);
97
98        mLogic = new Logic(this, mHistory, mDisplay);
99        mLogic.setListener(this);
100
101        mLogic.setDeleteMode(mPersist.getDeleteMode());
102        mLogic.setLineLength(mDisplay.getMaxDigits());
103
104        HistoryAdapter historyAdapter = new HistoryAdapter(this, mHistory, mLogic);
105        mHistory.setObserver(historyAdapter);
106
107        if (mPager != null) {
108            mPager.setCurrentItem(state == null ? 0 : state.getInt(STATE_CURRENT_VIEW, 0));
109        }
110
111        mListener.setHandler(mLogic, mPager);
112        mDisplay.setOnKeyListener(mListener);
113
114        if (!ViewConfiguration.get(this).hasPermanentMenuKey()) {
115            createFakeMenu();
116        }
117
118        mLogic.resumeWithHistory();
119        updateDeleteMode();
120    }
121
122    private void updateDeleteMode() {
123        if (mLogic.getDeleteMode() == Logic.DELETE_MODE_BACKSPACE) {
124            mClearButton.setVisibility(View.GONE);
125            mBackspaceButton.setVisibility(View.VISIBLE);
126        } else {
127            mClearButton.setVisibility(View.VISIBLE);
128            mBackspaceButton.setVisibility(View.GONE);
129        }
130    }
131
132    void setOnClickListener(View root, int id) {
133        final View target = root != null ? root.findViewById(id) : findViewById(id);
134        target.setOnClickListener(mListener);
135    }
136
137    @Override
138    public boolean onCreateOptionsMenu(Menu menu) {
139        super.onCreateOptionsMenu(menu);
140        getMenuInflater().inflate(R.menu.menu, menu);
141        return true;
142    }
143
144    @Override
145    public boolean onPrepareOptionsMenu(Menu menu) {
146        super.onPrepareOptionsMenu(menu);
147        menu.findItem(R.id.basic).setVisible(!getBasicVisibility());
148        menu.findItem(R.id.advanced).setVisible(!getAdvancedVisibility());
149        return true;
150    }
151
152
153    private void createFakeMenu() {
154        mOverflowMenuButton = findViewById(R.id.overflow_menu);
155        if (mOverflowMenuButton != null) {
156            mOverflowMenuButton.setVisibility(View.VISIBLE);
157            mOverflowMenuButton.setOnClickListener(this);
158        }
159    }
160
161    @Override
162    public void onClick(View v) {
163        switch (v.getId()) {
164            case R.id.overflow_menu:
165                PopupMenu menu = constructPopupMenu();
166                if (menu != null) {
167                    menu.show();
168                }
169                break;
170        }
171    }
172
173    private PopupMenu constructPopupMenu() {
174        final PopupMenu popupMenu = new PopupMenu(this, mOverflowMenuButton);
175        mOverflowMenuButton.setOnTouchListener(popupMenu.getDragToOpenListener());
176        final Menu menu = popupMenu.getMenu();
177        popupMenu.inflate(R.menu.menu);
178        popupMenu.setOnMenuItemClickListener(this);
179        onPrepareOptionsMenu(menu);
180        return popupMenu;
181    }
182
183
184    @Override
185    public boolean onMenuItemClick(MenuItem item) {
186        return onOptionsItemSelected(item);
187    }
188
189    private boolean getBasicVisibility() {
190        return mPager != null && mPager.getCurrentItem() == BASIC_PANEL;
191    }
192
193    private boolean getAdvancedVisibility() {
194        return mPager != null && mPager.getCurrentItem() == ADVANCED_PANEL;
195    }
196
197    @Override
198    public boolean onOptionsItemSelected(MenuItem item) {
199        switch (item.getItemId()) {
200            case R.id.clear_history:
201                mHistory.clear();
202                mLogic.onClear();
203                break;
204
205            case R.id.basic:
206                if (!getBasicVisibility() && mPager != null) {
207                    mPager.setCurrentItem(BASIC_PANEL, true);
208                }
209                break;
210
211            case R.id.advanced:
212                if (!getAdvancedVisibility() && mPager != null) {
213                    mPager.setCurrentItem(ADVANCED_PANEL, true);
214                }
215                break;
216        }
217        return super.onOptionsItemSelected(item);
218    }
219
220    @Override
221    protected void onSaveInstanceState(Bundle state) {
222        super.onSaveInstanceState(state);
223        if (mPager != null) {
224            state.putInt(STATE_CURRENT_VIEW, mPager.getCurrentItem());
225        }
226    }
227
228    @Override
229    public void onPause() {
230        super.onPause();
231        mLogic.updateHistory();
232        mPersist.setDeleteMode(mLogic.getDeleteMode());
233        mPersist.save();
234    }
235
236    @Override
237    public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
238        if (keyCode == KeyEvent.KEYCODE_BACK && getAdvancedVisibility()
239                && mPager != null) {
240            mPager.setCurrentItem(BASIC_PANEL);
241            return true;
242        } else {
243            return super.onKeyDown(keyCode, keyEvent);
244        }
245    }
246
247    static void log(String message) {
248        if (LOG_ENABLED) {
249            Log.v(LOG_TAG, message);
250        }
251    }
252
253    @Override
254    public void onChange() {
255        invalidateOptionsMenu();
256    }
257
258    @Override
259    public void onDeleteModeChange() {
260        updateDeleteMode();
261    }
262
263    class PageAdapter extends PagerAdapter {
264        private View mSimplePage;
265        private View mAdvancedPage;
266
267        public PageAdapter(ViewPager parent) {
268            final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
269            final View simplePage = inflater.inflate(R.layout.simple_pad, parent, false);
270            final View advancedPage = inflater.inflate(R.layout.advanced_pad, parent, false);
271            mSimplePage = simplePage;
272            mAdvancedPage = advancedPage;
273
274            final Resources res = getResources();
275            final TypedArray simpleButtons = res.obtainTypedArray(R.array.simple_buttons);
276            for (int i = 0; i < simpleButtons.length(); i++) {
277                setOnClickListener(simplePage, simpleButtons.getResourceId(i, 0));
278            }
279            simpleButtons.recycle();
280
281            final TypedArray advancedButtons = res.obtainTypedArray(R.array.advanced_buttons);
282            for (int i = 0; i < advancedButtons.length(); i++) {
283                setOnClickListener(advancedPage, advancedButtons.getResourceId(i, 0));
284            }
285            advancedButtons.recycle();
286
287            final View clearButton = simplePage.findViewById(R.id.clear);
288            if (clearButton != null) {
289                mClearButton = clearButton;
290            }
291
292            final View backspaceButton = simplePage.findViewById(R.id.del);
293            if (backspaceButton != null) {
294                mBackspaceButton = backspaceButton;
295            }
296        }
297
298        @Override
299        public int getCount() {
300            return 2;
301        }
302
303        @Override
304        public void startUpdate(View container) {
305        }
306
307        @Override
308        public Object instantiateItem(View container, int position) {
309            final View page = position == 0 ? mSimplePage : mAdvancedPage;
310            ((ViewGroup) container).addView(page);
311            return page;
312        }
313
314        @Override
315        public void destroyItem(View container, int position, Object object) {
316            ((ViewGroup) container).removeView((View) object);
317        }
318
319        @Override
320        public void finishUpdate(View container) {
321        }
322
323        @Override
324        public boolean isViewFromObject(View view, Object object) {
325            return view == object;
326        }
327
328        @Override
329        public Parcelable saveState() {
330            return null;
331        }
332
333        @Override
334        public void restoreState(Parcelable state, ClassLoader loader) {
335        }
336    }
337}
338