1/*
2 * Copyright (C) 2012 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.filtershow.editors;
18
19import android.content.Context;
20import android.content.res.Configuration;
21import android.util.AttributeSet;
22import android.util.Log;
23import android.view.LayoutInflater;
24import android.view.Menu;
25import android.view.MenuItem;
26import android.view.View;
27import android.view.ViewGroup;
28import android.widget.Button;
29import android.widget.FrameLayout;
30import android.widget.LinearLayout;
31import android.widget.PopupMenu;
32import android.widget.SeekBar;
33import android.widget.SeekBar.OnSeekBarChangeListener;
34
35import com.android.gallery3d.R;
36import com.android.gallery3d.filtershow.controller.Control;
37import com.android.gallery3d.filtershow.filters.FilterRepresentation;
38import com.android.gallery3d.filtershow.imageshow.ImageShow;
39import com.android.gallery3d.filtershow.imageshow.MasterImage;
40import com.android.gallery3d.filtershow.pipeline.ImagePreset;
41
42import java.util.ArrayList;
43import java.util.Collection;
44
45/**
46 * Base class for Editors Must contain a mImageShow and a top level view
47 */
48public class Editor implements OnSeekBarChangeListener, SwapButton.SwapButtonListener {
49    protected Context mContext;
50    protected View mView;
51    protected ImageShow mImageShow;
52    protected FrameLayout mFrameLayout;
53    protected SeekBar mSeekBar;
54    Button mEditTitle;
55    protected Button mFilterTitle;
56    protected int mID;
57    private final String LOGTAG = "Editor";
58    protected boolean mChangesGeometry = false;
59    protected FilterRepresentation mLocalRepresentation = null;
60    protected byte mShowParameter = SHOW_VALUE_UNDEFINED;
61    private Button mButton;
62    public static byte SHOW_VALUE_UNDEFINED = -1;
63    public static byte SHOW_VALUE_OFF = 0;
64    public static byte SHOW_VALUE_INT = 1;
65
66    public static void hackFixStrings(Menu menu) {
67        int count = menu.size();
68        for (int i = 0; i < count; i++) {
69            MenuItem item = menu.getItem(i);
70            item.setTitle(item.getTitle().toString().toUpperCase());
71        }
72    }
73
74    public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
75        return effectName.toUpperCase() + " " + parameterValue;
76    }
77
78    protected Editor(int id) {
79        mID = id;
80    }
81
82    public int getID() {
83        return mID;
84    }
85
86    public byte showParameterValue() {
87        return mShowParameter;
88    }
89
90    public boolean showsSeekBar() {
91        return true;
92    }
93
94    public void setUpEditorUI(View actionButton, View editControl,
95                              Button editTitle, Button stateButton) {
96        mEditTitle = editTitle;
97        mFilterTitle = stateButton;
98        mButton = editTitle;
99        MasterImage.getImage().resetGeometryImages(false);
100        setUtilityPanelUI(actionButton, editControl);
101    }
102
103    public boolean showsPopupIndicator() {
104        return false;
105    }
106
107    /**
108     * @param actionButton the would be the area for menu etc
109     * @param editControl this is the black area for sliders etc
110     */
111    public void setUtilityPanelUI(View actionButton, View editControl) {
112
113        AttributeSet aset;
114        Context context = editControl.getContext();
115        LayoutInflater inflater =
116                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
117        LinearLayout lp = (LinearLayout) inflater.inflate(
118                R.layout.filtershow_seekbar, (ViewGroup) editControl, true);
119        mSeekBar = (SeekBar) lp.findViewById(R.id.primarySeekBar);
120        mSeekBar.setOnSeekBarChangeListener(this);
121        mSeekBar.setVisibility(View.GONE);
122        if (context.getResources().getConfiguration().orientation
123                == Configuration.ORIENTATION_PORTRAIT) {
124            if (showsSeekBar()) {
125               mSeekBar.setVisibility(View.VISIBLE);
126            }
127        }
128
129        if (mButton != null) {
130            setMenuIcon(showsPopupIndicator());
131        }
132    }
133
134    @Override
135    public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) {
136
137    }
138
139    public void setPanel() {
140
141    }
142
143    public void createEditor(Context context, FrameLayout frameLayout) {
144        mContext = context;
145        mFrameLayout = frameLayout;
146        mLocalRepresentation = null;
147    }
148
149    protected void unpack(int viewid, int layoutid) {
150
151        if (mView == null) {
152            mView = mFrameLayout.findViewById(viewid);
153            if (mView == null) {
154                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
155                        (Context.LAYOUT_INFLATER_SERVICE);
156                mView = inflater.inflate(layoutid, mFrameLayout, false);
157                mFrameLayout.addView(mView, mView.getLayoutParams());
158            }
159        }
160        mImageShow = findImageShow(mView);
161    }
162
163    private ImageShow findImageShow(View view) {
164        if (view instanceof ImageShow) {
165            return (ImageShow) view;
166        }
167        if (!(view instanceof ViewGroup)) {
168            return null;
169        }
170        ViewGroup vg = (ViewGroup) view;
171        int n = vg.getChildCount();
172        for (int i = 0; i < n; i++) {
173            View v = vg.getChildAt(i);
174            if (v instanceof ImageShow) {
175                return (ImageShow) v;
176            } else if (v instanceof ViewGroup) {
177                return findImageShow(v);
178            }
179        }
180        return null;
181    }
182
183    public View getTopLevelView() {
184        return mView;
185    }
186
187    public ImageShow getImageShow() {
188        return mImageShow;
189    }
190
191    public void setVisibility(int visible) {
192        mView.setVisibility(visible);
193    }
194
195    public FilterRepresentation getLocalRepresentation() {
196        if (mLocalRepresentation == null) {
197            ImagePreset preset = MasterImage.getImage().getPreset();
198            FilterRepresentation filterRepresentation = MasterImage.getImage().getCurrentFilterRepresentation();
199            mLocalRepresentation = preset.getFilterRepresentationCopyFrom(filterRepresentation);
200            if (mShowParameter == SHOW_VALUE_UNDEFINED && filterRepresentation != null) {
201                boolean show = filterRepresentation.showParameterValue();
202                mShowParameter = show ? SHOW_VALUE_INT : SHOW_VALUE_OFF;
203            }
204
205        }
206        return mLocalRepresentation;
207    }
208
209    /**
210     * Call this to update the preset in MasterImage with the current representation
211     * returned by getLocalRepresentation.  This causes the preview bitmap to be
212     * regenerated.
213     */
214    public void commitLocalRepresentation() {
215        commitLocalRepresentation(getLocalRepresentation());
216    }
217
218    /**
219     * Call this to update the preset in MasterImage with a given representation.
220     * This causes the preview bitmap to be regenerated.
221     */
222    public void commitLocalRepresentation(FilterRepresentation rep) {
223        ArrayList<FilterRepresentation> filter = new ArrayList<FilterRepresentation>(1);
224        filter.add(rep);
225        commitLocalRepresentation(filter);
226    }
227
228    /**
229     * Call this to update the preset in MasterImage with a collection of FilterRepresentations.
230     * This causes the preview bitmap to be regenerated.
231     */
232    public void commitLocalRepresentation(Collection<FilterRepresentation> reps) {
233        ImagePreset preset = MasterImage.getImage().getPreset();
234        preset.updateFilterRepresentations(reps);
235        if (mButton != null) {
236            updateText();
237        }
238        if (mChangesGeometry) {
239            // Regenerate both the filtered and the geometry-only bitmaps
240            MasterImage.getImage().resetGeometryImages(true);
241        }
242        // Regenerate the filtered bitmap.
243        MasterImage.getImage().invalidateFiltersOnly();
244        preset.fillImageStateAdapter(MasterImage.getImage().getState());
245    }
246
247    /**
248     * This is called in response to a click to apply and leave the editor.
249     */
250    public void finalApplyCalled() {
251        commitLocalRepresentation();
252    }
253
254    protected void updateText() {
255        String s = "";
256        if (mLocalRepresentation != null) {
257            s = mContext.getString(mLocalRepresentation.getTextId());
258        }
259        mButton.setText(calculateUserMessage(mContext, s, ""));
260    }
261
262    /**
263     * called after the filter is set and the select is called
264     */
265    public void reflectCurrentFilter() {
266        mLocalRepresentation = null;
267        FilterRepresentation representation = getLocalRepresentation();
268        if (representation != null && mFilterTitle != null && representation.getTextId() != 0) {
269            String text = mContext.getString(representation.getTextId()).toUpperCase();
270            mFilterTitle.setText(text);
271            updateText();
272        }
273    }
274
275    public boolean useUtilityPanel() {
276        return true;
277    }
278
279    public void openUtilityPanel(LinearLayout mAccessoryViewList) {
280        setMenuIcon(showsPopupIndicator());
281        if (mImageShow != null) {
282            mImageShow.openUtilityPanel(mAccessoryViewList);
283        }
284    }
285
286    protected void setMenuIcon(boolean on) {
287        mEditTitle.setCompoundDrawablesRelativeWithIntrinsicBounds(
288                0, 0, on ? R.drawable.filtershow_menu_marker_rtl : 0, 0);
289    }
290
291    protected void createMenu(int[] strId, View button) {
292        PopupMenu pmenu = new PopupMenu(mContext, button);
293        Menu menu = pmenu.getMenu();
294        for (int i = 0; i < strId.length; i++) {
295            menu.add(Menu.NONE, Menu.FIRST + i, 0, mContext.getString(strId[i]));
296        }
297        setMenuIcon(true);
298
299    }
300
301    public Control[] getControls() {
302        return null;
303    }
304
305    @Override
306    public void onStartTrackingTouch(SeekBar arg0) {
307
308    }
309
310    @Override
311    public void onStopTrackingTouch(SeekBar arg0) {
312
313    }
314
315    @Override
316    public void swapLeft(MenuItem item) {
317
318    }
319
320    @Override
321    public void swapRight(MenuItem item) {
322
323    }
324
325    public void detach() {
326        if (mImageShow != null) {
327            mImageShow.detach();
328        }
329    }
330}
331