From fb6a8e166f0a46d2a994a408b1679e3a67fdcb52 Mon Sep 17 00:00:00 2001 From: nicolasroard Date: Mon, 15 Apr 2013 14:41:00 -0700 Subject: [PATCH] New state panel bug:8620913 bug:8503386 Change-Id: I35c95103e3b5097df93fa3f48e5562a479915f06 --- res/layout-land/filtershow_activity.xml | 112 ++++---- res/layout/filtershow_state_panel_new.xml | 47 ++++ res/values/filtershow_strings.xml | 6 + .../gallery3d/filtershow/FilterShowActivity.java | 53 ++-- .../gallery3d/filtershow/PanelController.java | 3 + .../filtershow/imageshow/MasterImage.java | 8 +- .../gallery3d/filtershow/presets/ImagePreset.java | 8 +- .../gallery3d/filtershow/state/DragListener.java | 110 ++++++++ .../gallery3d/filtershow/state/PanelTrack.java | 37 +++ .../android/gallery3d/filtershow/state/State.java | 66 +++++ .../gallery3d/filtershow/state/StateAdapter.java | 99 +++++++ .../gallery3d/filtershow/state/StatePanel.java | 44 +++ .../filtershow/state/StatePanelTrack.java | 297 +++++++++++++++++++++ .../gallery3d/filtershow/state/StateView.java | 263 ++++++++++++++++++ 14 files changed, 1054 insertions(+), 99 deletions(-) create mode 100644 res/layout/filtershow_state_panel_new.xml create mode 100644 src/com/android/gallery3d/filtershow/state/DragListener.java create mode 100644 src/com/android/gallery3d/filtershow/state/PanelTrack.java create mode 100644 src/com/android/gallery3d/filtershow/state/State.java create mode 100644 src/com/android/gallery3d/filtershow/state/StateAdapter.java create mode 100644 src/com/android/gallery3d/filtershow/state/StatePanel.java create mode 100644 src/com/android/gallery3d/filtershow/state/StatePanelTrack.java create mode 100644 src/com/android/gallery3d/filtershow/state/StateView.java diff --git a/res/layout-land/filtershow_activity.xml b/res/layout-land/filtershow_activity.xml index f1294f525..311a3e639 100644 --- a/res/layout-land/filtershow_activity.xml +++ b/res/layout-land/filtershow_activity.xml @@ -28,56 +28,55 @@ android:orientation="horizontal" android:animateLayoutChanges="true"> - + - + - + - + + android:orientation="vertical"> - + + android:layout_height="0dip" + android:visibility="gone"/> + android:visibility="gone"> + android:background="@color/background_screen"/> @@ -96,29 +95,29 @@ xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d" android:id="@+id/filtersPanel" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center" + android:layout_height="177dip" + android:layout_gravity="center|bottom" custom:max_width="600dip" android:orientation="vertical"> + android:layout_height="128dip"> + android:visibility="gone"> + android:inflatedId="@+id/editorPanel" + android:layout="@layout/filtershow_editor_panel" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="visible"/> @@ -127,14 +126,14 @@ android:layout_width="match_parent" android:layout_height="@dimen/thumbnail_size" android:background="@color/background_main_toolbar" - android:scrollbars="none" > + android:scrollbars="none"> + android:orientation="horizontal"> @@ -144,14 +143,14 @@ android:layout_height="@dimen/thumbnail_size" android:background="@color/background_main_toolbar" android:visibility="gone" - android:scrollbars="none" > + android:scrollbars="none"> + android:orientation="horizontal"> @@ -161,14 +160,14 @@ android:layout_height="@dimen/thumbnail_size" android:background="@color/background_main_toolbar" android:visibility="gone" - android:scrollbars="none" > + android:scrollbars="none"> + android:orientation="horizontal"/> @@ -178,7 +177,7 @@ android:layout_height="wrap_content" android:background="@color/background_main_toolbar" android:visibility="gone" - android:scrollbars="none" > + android:scrollbars="none"> + android:orientation="horizontal"> @@ -195,22 +194,21 @@ + android:layout_width="match_parent"/> - + diff --git a/res/layout/filtershow_state_panel_new.xml b/res/layout/filtershow_state_panel_new.xml new file mode 100644 index 000000000..771122192 --- /dev/null +++ b/res/layout/filtershow_state_panel_new.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + diff --git a/res/values/filtershow_strings.xml b/res/values/filtershow_strings.xml index a7bc92dcc..11f27cf1b 100644 --- a/res/values/filtershow_strings.xml +++ b/res/values/filtershow_strings.xml @@ -193,4 +193,10 @@ OK + + Original + + + Result + diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index 1a7d200f1..e445a5d8d 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -17,7 +17,6 @@ package com.android.gallery3d.filtershow; import android.app.ActionBar; -import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.app.WallpaperManager; @@ -35,6 +34,8 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.provider.MediaStore; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentTransaction; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; @@ -75,6 +76,8 @@ import com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet; import com.android.gallery3d.filtershow.imageshow.MasterImage; import com.android.gallery3d.filtershow.presets.ImagePreset; import com.android.gallery3d.filtershow.provider.SharedImageProvider; +import com.android.gallery3d.filtershow.state.StateAdapter; +import com.android.gallery3d.filtershow.state.StatePanel; import com.android.gallery3d.filtershow.tools.BitmapTask; import com.android.gallery3d.filtershow.tools.SaveCopyTask; import com.android.gallery3d.filtershow.ui.FilterIconButton; @@ -88,9 +91,11 @@ import java.io.IOException; import java.lang.ref.WeakReference; import java.util.Vector; -public class FilterShowActivity extends Activity implements OnItemClickListener, +public class FilterShowActivity extends FragmentActivity implements OnItemClickListener, OnShareTargetSelectedListener { + private String mPanelFragmentTag = "StatePanel"; + // fields for supporting crop action public static final String CROP_ACTION = "com.android.camera.action.CROP"; private CropExtras mCropExtras = null; @@ -157,10 +162,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, } else { findViewById(R.id.historyPanel).setVisibility(View.GONE); } - if (mShowingImageStatePanel) { - findViewById(R.id.imageStatePanel).setVisibility(View.VISIBLE); - } else { - findViewById(R.id.imageStatePanel).setVisibility(View.GONE); + if (mShowingImageStatePanel && (savedInstanceState == null)) { + loadImageStatePanel(); } setDefaultPreset(); @@ -174,7 +177,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, ((ViewStub) findViewById(R.id.stateCategoryStub)).inflate(); ((ViewStub) findViewById(R.id.editorPanelStub)).inflate(); ((ViewStub) findViewById(R.id.historyPanelStub)).inflate(); - ((ViewStub) findViewById(R.id.statePanelStub)).inflate(); ActionBar actionBar = getActionBar(); actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); @@ -242,8 +244,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, } public void setupStatePanel() { - ListView imageStateList = (ListView) findViewById(R.id.imageStateList); - imageStateList.setAdapter(mMasterImage.getState()); mImageLoader.setAdapter(mMasterImage.getHistory()); mPanelController.setRowPanel(findViewById(R.id.secondRowPanel)); mPanelController.setUtilityPanel(this, findViewById(R.id.filterButtonsList)); @@ -849,21 +849,16 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, } private void toggleImageStatePanel() { - final View viewList = findViewById(R.id.imageStatePanel); + invalidateOptionsMenu(); + } - if (mShowingHistoryPanel) { - findViewById(R.id.historyPanel).setVisibility(View.GONE); - mShowingHistoryPanel = false; + private void loadImageStatePanel() { + StatePanel statePanel = new StatePanel(); + if (findViewById(R.id.state_panel_container) != null) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.replace(R.id.state_panel_container, statePanel, mPanelFragmentTag); + transaction.commit(); } - - if (!mShowingImageStatePanel) { - mShowingImageStatePanel = true; - viewList.setVisibility(View.VISIBLE); - } else { - mShowingImageStatePanel = false; - viewList.setVisibility(View.GONE); - } - invalidateOptionsMenu(); } @Override @@ -878,6 +873,9 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, } else if (mShowingImageStatePanel) { toggleImageStatePanel(); } + if (mShowingImageStatePanel) { + loadImageStatePanel(); + } if (mShowingHistoryPanel) { toggleHistoryPanel(); } @@ -897,9 +895,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, HistoryAdapter mHistoryAdapter = new HistoryAdapter( this, R.layout.filtershow_history_operation_row, R.id.rowTextView); - ImageStateAdapter mImageStateAdapter = new ImageStateAdapter(this, - R.layout.filtershow_imagestate_row); + StateAdapter mImageStateAdapter = new StateAdapter(this, 0); MasterImage.reset(); mMasterImage = MasterImage.getImage(); mMasterImage.setHistoryAdapter(mHistoryAdapter); @@ -921,10 +918,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, final View view = findViewById(R.id.mainPanel); final View viewList = findViewById(R.id.historyPanel); - if (mShowingImageStatePanel) { - findViewById(R.id.imageStatePanel).setVisibility(View.GONE); - } - int translate = translateMainPanel(viewList); if (!mShowingHistoryPanel) { mShowingHistoryPanel = true; @@ -968,10 +961,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, } else { viewList.setVisibility(View.GONE); findViewById(R.id.filtersPanel).setVisibility(View.VISIBLE); - // In landscape, bring back the state panel if it was there - if (mShowingImageStatePanel) { - findViewById(R.id.imageStatePanel).setVisibility(View.VISIBLE); - } } } invalidateOptionsMenu(); diff --git a/src/com/android/gallery3d/filtershow/PanelController.java b/src/com/android/gallery3d/filtershow/PanelController.java index 1d0118f85..e9a913610 100644 --- a/src/com/android/gallery3d/filtershow/PanelController.java +++ b/src/com/android/gallery3d/filtershow/PanelController.java @@ -544,6 +544,9 @@ public class PanelController implements OnClickListener { if (filterRepresentation == null) { return; } + if (filterRepresentation == MasterImage.getImage().getCurrentFilterRepresentation()) { + return; + } Set views = mViews.keySet(); for (View view : views) { if (view instanceof FilterIconButton) { diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java index 94573bc61..c36befc2c 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java +++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java @@ -22,11 +22,11 @@ import android.os.Message; import com.android.gallery3d.filtershow.FilterShowActivity; import com.android.gallery3d.filtershow.HistoryAdapter; -import com.android.gallery3d.filtershow.ImageStateAdapter; import com.android.gallery3d.filtershow.cache.*; import com.android.gallery3d.filtershow.filters.FilterRepresentation; import com.android.gallery3d.filtershow.filters.ImageFilter; import com.android.gallery3d.filtershow.presets.ImagePreset; +import com.android.gallery3d.filtershow.state.StateAdapter; import java.util.Vector; @@ -55,7 +55,7 @@ public class MasterImage implements RenderingRequestCaller { private ImageLoader mLoader = null; private HistoryAdapter mHistory = null; - private ImageStateAdapter mState = null; + private StateAdapter mState = null; private FilterShowActivity mActivity = null; @@ -192,7 +192,7 @@ public class MasterImage implements RenderingRequestCaller { return mHistory; } - public ImageStateAdapter getState() { + public StateAdapter getState() { return mState; } @@ -200,7 +200,7 @@ public class MasterImage implements RenderingRequestCaller { mHistory = adapter; } - public void setStateAdapter(ImageStateAdapter adapter) { + public void setStateAdapter(StateAdapter adapter) { mState = adapter; } diff --git a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java index 00f5977d1..bd2f494cd 100644 --- a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java +++ b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java @@ -21,15 +21,14 @@ import android.graphics.Rect; import android.support.v8.renderscript.Allocation; import android.util.Log; -import com.android.gallery3d.filtershow.ImageStateAdapter; import com.android.gallery3d.filtershow.cache.CachingPipeline; import com.android.gallery3d.filtershow.cache.ImageLoader; import com.android.gallery3d.filtershow.filters.BaseFiltersManager; import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FiltersManager; import com.android.gallery3d.filtershow.filters.ImageFilter; import com.android.gallery3d.filtershow.imageshow.GeometryMetadata; import com.android.gallery3d.filtershow.imageshow.MasterImage; +import com.android.gallery3d.filtershow.state.StateAdapter; import java.util.Vector; @@ -533,14 +532,11 @@ public class ImagePreset { return true; } - public void fillImageStateAdapter(ImageStateAdapter imageStateAdapter) { + public void fillImageStateAdapter(StateAdapter imageStateAdapter) { if (imageStateAdapter == null) { return; } - imageStateAdapter.clear(); - // TODO: re-enable the state panel imageStateAdapter.addAll(mFilters); - imageStateAdapter.notifyDataSetChanged(); } public void setPartialRendering(boolean partialRendering, Rect bounds) { diff --git a/src/com/android/gallery3d/filtershow/state/DragListener.java b/src/com/android/gallery3d/filtershow/state/DragListener.java new file mode 100644 index 000000000..1aa81ed69 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/state/DragListener.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2013 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.filtershow.state; + +import android.view.DragEvent; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.LinearLayout; + +class DragListener implements View.OnDragListener { + + private static final String LOGTAG = "DragListener"; + private PanelTrack mStatePanelTrack; + private static float sSlope = 0.2f; + + public DragListener(PanelTrack statePanelTrack) { + mStatePanelTrack = statePanelTrack; + } + + private void setState(DragEvent event) { + float translation = event.getY() - mStatePanelTrack.getTouchPoint().y; + float alpha = 1.0f - (Math.abs(translation) + / mStatePanelTrack.getCurrentView().getHeight()); + if (mStatePanelTrack.getOrientation() == LinearLayout.VERTICAL) { + translation = event.getX() - mStatePanelTrack.getTouchPoint().x; + alpha = 1.0f - (Math.abs(translation) + / mStatePanelTrack.getCurrentView().getWidth()); + mStatePanelTrack.getCurrentView().setTranslationX(translation); + } else { + mStatePanelTrack.getCurrentView().setTranslationY(translation); + } + mStatePanelTrack.getCurrentView().setBackgroundAlpha(alpha); + } + + @Override + public boolean onDrag(View v, DragEvent event) { + switch (event.getAction()) { + case DragEvent.ACTION_DRAG_STARTED: { + break; + } + case DragEvent.ACTION_DRAG_LOCATION: { + if (mStatePanelTrack.getCurrentView() != null) { + setState(event); + View over = mStatePanelTrack.findChildAt((int) event.getX(), + (int) event.getY()); + if (over != null && over != mStatePanelTrack.getCurrentView()) { + StateView stateView = (StateView) over; + if (stateView != mStatePanelTrack.getCurrentView()) { + int pos = mStatePanelTrack.findChild(over); + int origin = mStatePanelTrack.findChild( + mStatePanelTrack.getCurrentView()); + ArrayAdapter array = (ArrayAdapter) mStatePanelTrack.getAdapter(); + if (origin != -1 && pos != -1) { + State current = (State) array.getItem(origin); + array.remove(current); + array.insert(current, pos); + mStatePanelTrack.fillContent(false); + mStatePanelTrack.setCurrentView(mStatePanelTrack.getChildAt(pos)); + } + } + } + } + break; + } + case DragEvent.ACTION_DRAG_ENTERED: { + mStatePanelTrack.setExited(false); + if (mStatePanelTrack.getCurrentView() != null) { + mStatePanelTrack.getCurrentView().setVisibility(View.VISIBLE); + } + return true; + } + case DragEvent.ACTION_DRAG_EXITED: { + if (mStatePanelTrack.getCurrentView() != null) { + setState(event); + mStatePanelTrack.getCurrentView().setVisibility(View.INVISIBLE); + } + mStatePanelTrack.setExited(true); + break; + } + case DragEvent.ACTION_DROP: { + break; + } + case DragEvent.ACTION_DRAG_ENDED: { + if (mStatePanelTrack.getCurrentView() != null + && mStatePanelTrack.getCurrentView().getAlpha() > sSlope) { + setState(event); + } + mStatePanelTrack.checkEndState(); + break; + } + default: + break; + } + return true; + } +} diff --git a/src/com/android/gallery3d/filtershow/state/PanelTrack.java b/src/com/android/gallery3d/filtershow/state/PanelTrack.java new file mode 100644 index 000000000..d02207d9b --- /dev/null +++ b/src/com/android/gallery3d/filtershow/state/PanelTrack.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 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.filtershow.state; + +import android.graphics.Point; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Adapter; + +public interface PanelTrack { + public int getOrientation(); + public void onTouch(MotionEvent event, StateView view); + public StateView getCurrentView(); + public void setCurrentView(View view); + public Point getTouchPoint(); + public View findChildAt(int x, int y); + public int findChild(View view); + public Adapter getAdapter(); + public void fillContent(boolean value); + public View getChildAt(int pos); + public void setExited(boolean value); + public void checkEndState(); +} diff --git a/src/com/android/gallery3d/filtershow/state/State.java b/src/com/android/gallery3d/filtershow/state/State.java new file mode 100644 index 000000000..a853371e7 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/state/State.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2013 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.filtershow.state; + +import com.android.gallery3d.filtershow.filters.FilterRepresentation; + +public class State { + private String mText; + private int mType; + private FilterRepresentation mFilterRepresentation; + + public State(State state) { + this(state.getText(), state.getType()); + } + + public State(String text) { + this(text, StateView.DEFAULT); + } + + State(String text, int type) { + mText = text; + mType = type; + } + + public boolean isDraggable() { + return mFilterRepresentation != null; + } + + String getText() { + return mText; + } + + void setText(String text) { + mText = text; + } + + int getType() { + return mType; + } + + void setType(int type) { + mType = type; + } + + public FilterRepresentation getFilterRepresentation() { + return mFilterRepresentation; + } + + public void setFilterRepresentation(FilterRepresentation filterRepresentation) { + mFilterRepresentation = filterRepresentation; + } +} diff --git a/src/com/android/gallery3d/filtershow/state/StateAdapter.java b/src/com/android/gallery3d/filtershow/state/StateAdapter.java new file mode 100644 index 000000000..ae81e0b38 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/state/StateAdapter.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013 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.filtershow.state; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import com.android.gallery3d.R; +import com.android.gallery3d.filtershow.FilterShowActivity; +import com.android.gallery3d.filtershow.filters.FilterRepresentation; + +import java.util.Vector; + +public class StateAdapter extends ArrayAdapter { + + private int mOrientation; + private PanelTrack mListener; + private String mOriginalText; + private String mResultText; + + public StateAdapter(Context context, int textViewResourceId) { + super(context, textViewResourceId); + mOriginalText = context.getString(R.string.state_panel_original); + mResultText = context.getString(R.string.state_panel_result); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + StateView view = null; + if (convertView == null) { + convertView = new StateView(getContext()); + } + view = (StateView) convertView; + State state = getItem(position); + view.setState(state); + view.setOrientation(mOrientation); + view.setBackgroundAlpha(1.0f); + return view; + } + + public boolean contains(State state) { + for (int i = 0; i < getCount(); i++) { + if (state == getItem(i)) { + return true; + } + } + return false; + } + + public void setOrientation(int orientation) { + mOrientation = orientation; + } + + @Override + public void notifyDataSetChanged() { + if (mListener != null) { + mListener.fillContent(false); + } + } + + public void addAll(Vector filters) { + clear(); + add(new State(mOriginalText)); + for (FilterRepresentation filter : filters) { + State state = new State(filter.getName()); + state.setFilterRepresentation(filter); + add(state); + } + add(new State(mResultText)); + notifyDataSetChanged(); + } + + void setListener(PanelTrack listener) { + mListener = listener; + } + + @Override + public void remove(State state) { + super.remove(state); + FilterRepresentation filterRepresentation = state.getFilterRepresentation(); + FilterShowActivity activity = (FilterShowActivity) getContext(); + activity.getPanelController().removeFilterRepresentation(filterRepresentation); + } +} diff --git a/src/com/android/gallery3d/filtershow/state/StatePanel.java b/src/com/android/gallery3d/filtershow/state/StatePanel.java new file mode 100644 index 000000000..fd33b051d --- /dev/null +++ b/src/com/android/gallery3d/filtershow/state/StatePanel.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013 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.filtershow.state; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import com.android.gallery3d.R; +import com.android.gallery3d.filtershow.imageshow.MasterImage; + +public class StatePanel extends Fragment { + private static final String LOGTAG = "StatePanel"; + StatePanelTrack track; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + LinearLayout main = (LinearLayout) inflater.inflate( + R.layout.filtershow_state_panel_new, container, + false); + + View panel = main.findViewById(R.id.listStates); + track = (StatePanelTrack) panel; + track.setAdapter(MasterImage.getImage().getState()); + return main; + } +} diff --git a/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java b/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java new file mode 100644 index 000000000..1f6c27210 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2013 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.filtershow.state; + +import android.animation.LayoutTransition; +import android.content.Context; +import android.graphics.Point; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Adapter; +import android.widget.LinearLayout; +import com.android.gallery3d.filtershow.FilterShowActivity; +import com.android.gallery3d.filtershow.filters.FilterRepresentation; + +public class StatePanelTrack extends LinearLayout implements PanelTrack { + + private static final String LOGTAG = "StatePanelTrack"; + private Point mTouchPoint; + private StateView mCurrentView; + private StateView mCurrentSelectedView; + private boolean mExited = false; + private boolean mStartedDrag = false; + private StateAdapter mAdapter; + private DragListener mDragListener = new DragListener(this); + GestureDetector mGestureDetector; + private int mContainerWidth = 668; // TODO: get this from XML + private int mContainerHeight = 200; + + public StatePanelTrack(Context context, AttributeSet attrs) { + super(context, attrs); + GestureDetector.SimpleOnGestureListener simpleOnGestureListener + = new GestureDetector.SimpleOnGestureListener(){ + @Override + public void onLongPress(MotionEvent e) { + longPress(e); + } + @Override + public boolean onDoubleTap(MotionEvent e) { + addDuplicate(e); + return true; + } + }; + mGestureDetector = new GestureDetector(context, simpleOnGestureListener); + } + + private void addDuplicate(MotionEvent e) { + if (mCurrentSelectedView == null) { + return; + } + int pos = findChild(mCurrentSelectedView); + if (pos != -1) { + mAdapter.insert(new State(mCurrentSelectedView.getState()), pos); + fillContent(true); + } + } + + private void longPress(MotionEvent e) { + View view = findChildAt((int) e.getX(), (int) e.getY()); + if (view == null) { + return; + } + if (view instanceof StateView) { + StateView stateView = (StateView) view; + stateView.setDuplicateButton(true); + } + } + + public void setAdapter(StateAdapter adapter) { + mAdapter = adapter; + mAdapter.setListener(this); + mAdapter.setOrientation(getOrientation()); + fillContent(false); + requestLayout(); + } + + public StateView findChildWithState(State state) { + for (int i = 0; i < getChildCount(); i++) { + StateView view = (StateView) getChildAt(i); + if (view.getState() == state) { + return view; + } + } + return null; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ + int w = MeasureSpec.getSize(widthMeasureSpec); + if (w > 0) { + mContainerWidth = w; + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + fillContent(false); + } + + public void fillContent(boolean animate) { + if (!animate) { + this.setLayoutTransition(null); + } + int n = mAdapter.getCount(); + int w = mContainerWidth; + int h = mContainerHeight; + for (int i = 0; i < getChildCount(); i++) { + StateView child = (StateView) getChildAt(i); + child.resetPosition(); + if (!mAdapter.contains(child.getState())) { + removeView(child); + } + } + LayoutParams params; + params = new LayoutParams(w, h); + LayoutParams paramsEnds; + paramsEnds = new LayoutParams(w, h/2); + for (int i = 0; i < n; i++) { + State s = mAdapter.getItem(i); + if (findChildWithState(s) == null) { + View view = mAdapter.getView(i, null, this); + addView(view, i, params); + } + } + for (int i = 0; i < n; i++) { + State state = mAdapter.getItem(i); + StateView view = (StateView) getChildAt(i); + view.setState(state); + if (i == 0) { + view.setType(StateView.BEGIN); + } else if (i == n - 1) { + view.setType(StateView.END); + } + view.resetPosition(); + if (i == 0 || (i == n -1)) { + if (view.getWidth() != w || view.getHeight() != h/2) { + view.setLayoutParams(paramsEnds); + requestLayout(); + } + } else { + if (view.getWidth() != w || view.getHeight() != h) { + view.setLayoutParams(params); + requestLayout(); + } + } + } + + if (!animate) { + this.setLayoutTransition(new LayoutTransition()); + } + } + + public void onTouch(MotionEvent event, StateView view) { + if (!view.isDraggable()) { + return; + } + mCurrentView = view; + if (mCurrentSelectedView == mCurrentView) { + return; + } + if (mCurrentSelectedView != null) { + mCurrentSelectedView.setSelected(false); + } + // We changed the current view -- let's reset the + // gesture detector. + MotionEvent cancelEvent = MotionEvent.obtain(event); + cancelEvent.setAction(MotionEvent.ACTION_CANCEL); + mGestureDetector.onTouchEvent(cancelEvent); + mCurrentSelectedView = mCurrentView; + mCurrentSelectedView.setSelected(true); + // We have to send the event to the gesture detector + mGestureDetector.onTouchEvent(event); + FilterShowActivity activity = (FilterShowActivity) getContext(); + activity.getPanelController().showComponentWithRepresentation( + mCurrentSelectedView.getState().getFilterRepresentation()); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + if (mCurrentView != null) { + return true; + } + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mCurrentView == null) { + return false; + } + mGestureDetector.onTouchEvent(event); + if (mTouchPoint == null) { + mTouchPoint = new Point(); + mTouchPoint.x = (int) event.getX(); + mTouchPoint.y = (int) event.getY(); + } + if (event.getActionMasked() == MotionEvent.ACTION_MOVE) { + float translation = event.getY() - mTouchPoint.y; + float alpha = 1.0f - (Math.abs(translation) / mCurrentView.getHeight()); + if (getOrientation() == LinearLayout.VERTICAL) { + translation = event.getX() - mTouchPoint.x; + alpha = 1.0f - (Math.abs(translation) / mCurrentView.getWidth()); + mCurrentView.setTranslationX(translation); + } else { + mCurrentView.setTranslationY(translation); + } + mCurrentView.setBackgroundAlpha(alpha); + if (alpha < 0.7) { + setOnDragListener(mDragListener); + DragShadowBuilder shadowBuilder = new DragShadowBuilder(mCurrentView); + mCurrentView.startDrag(null, shadowBuilder, mCurrentView, 0); + mStartedDrag = true; + } + } + if (event.getActionMasked() == MotionEvent.ACTION_UP + || (!mStartedDrag && event.getActionMasked() == MotionEvent.ACTION_CANCEL)) { + checkEndState(); + } + return true; + } + + public void checkEndState() { + mTouchPoint = null; + if (mExited || mCurrentView.getAlpha() < 0.2) { + int origin = findChild(mCurrentView); + if (origin != -1) { + State current = mAdapter.getItem(origin); + mAdapter.remove(current); + fillContent(true); + } + } else { + mCurrentView.setBackgroundAlpha(1.0f); + mCurrentView.setTranslationX(0); + mCurrentView.setTranslationY(0); + } + mCurrentView = null; + mExited = false; + mStartedDrag = false; + } + + public View findChildAt(int x, int y) { + Rect frame = new Rect(); + int scrolledXInt = getScrollX() + x; + int scrolledYInt = getScrollY() + y; + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + child.getHitRect(frame); + if (frame.contains(scrolledXInt, scrolledYInt)) { + return child; + } + } + return null; + } + + public int findChild(View view) { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (child == view) { + return i; + } + } + return -1; + } + + public StateView getCurrentView() { + return mCurrentView; + } + + public void setCurrentView(View currentView) { + mCurrentView = (StateView) currentView; + } + + public void setExited(boolean value) { + mExited = value; + } + + public Point getTouchPoint() { + return mTouchPoint; + } + + public Adapter getAdapter() { + return mAdapter; + } +} diff --git a/src/com/android/gallery3d/filtershow/state/StateView.java b/src/com/android/gallery3d/filtershow/state/StateView.java new file mode 100644 index 000000000..eb19b5229 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/state/StateView.java @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2013 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.filtershow.state; + +import android.content.Context; +import android.graphics.*; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewParent; +import android.widget.LinearLayout; +import com.android.gallery3d.filtershow.FilterShowActivity; + +public class StateView extends View { + + private Path mPath = new Path(); + private Paint mPaint = new Paint(); + + public static int DEFAULT = 0; + public static int BEGIN = 1; + public static int END = 2; + + public static int UP = 1; + public static int DOWN = 2; + public static int LEFT = 3; + public static int RIGHT = 4; + + private int mType = DEFAULT; + private float mAlpha = 1.0f; + private String mText = "Default"; + private float mTextSize = 32; + private static int sMargin = 16; + private static int sArrowHeight = 16; + private static int sArrowWidth = 8; + private int mOrientation = LinearLayout.VERTICAL; + private int mDirection = DOWN; + private boolean mDuplicateButton; + private State mState; + + public StateView(Context context) { + this(context, DEFAULT); + } + + public StateView(Context context, int type) { + super(context); + mType = type; + } + + public StateView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public String getText() { + return mText; + } + + public void setText(String text) { + mText = text; + invalidate(); + } + + public void setType(int type) { + mType = type; + invalidate(); + } + + @Override + public void setSelected(boolean value) { + super.setSelected(value); + if (!value) { + mDuplicateButton = false; + } + invalidate(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + ViewParent parent = getParent(); + if (parent instanceof PanelTrack) { + ((PanelTrack) getParent()).onTouch(event, this); + } + } + return true; + } + + public void drawText(Canvas canvas) { + if (mText == null) { + return; + } + mPaint.reset(); + if (isSelected()) { + mPaint.setColor(Color.BLACK); + } else { + mPaint.setColor(Color.WHITE); + } + mPaint.setTextSize(mTextSize); + float textWidth = mPaint.measureText(mText); + int x = (int) ((canvas.getWidth() - textWidth) / 2); + int y = canvas.getHeight() - sMargin; + if (canvas.getHeight() > canvas.getWidth()) { + y = canvas.getHeight() - (canvas.getHeight() - canvas.getWidth() - 2 * sMargin) / 2; + } + canvas.drawText(mText, x, y, mPaint); + } + + public void onDraw(Canvas canvas) { + canvas.drawARGB(0, 0, 0, 0); + mPath.reset(); + + float w = canvas.getWidth(); + float h = canvas.getHeight(); + float r = sArrowHeight; + float d = sArrowWidth; + + if (mOrientation == LinearLayout.HORIZONTAL) { + drawHorizontalPath(w, h, r, d); + } else { + if (mDirection == DOWN) { + drawVerticalDownPath(w, h, r, d); + } else { + drawVerticalPath(w, h, r, d); + } + } + + if (mType == DEFAULT) { + if (mDuplicateButton) { + mPaint.setARGB(255, 200, 0, 0); + } else if (isSelected()) { + mPaint.setARGB(255, 200, 200, 200); + } else { + mPaint.setARGB(255, 70, 70, 70); + } + } else { + mPaint.setARGB(255, 150, 150, 150); + } + canvas.drawPath(mPath, mPaint); + drawText(canvas); + } + + private void drawHorizontalPath(float w, float h, float r, float d) { + mPath.moveTo(0, 0); + if (mType == END) { + mPath.lineTo(w, 0); + mPath.lineTo(w, h); + } else { + mPath.lineTo(w - d, 0); + mPath.lineTo(w - d, r); + mPath.lineTo(w, r + d); + mPath.lineTo(w - d, r + d + r); + mPath.lineTo(w - d, h); + } + mPath.lineTo(0, h); + if (mType != BEGIN) { + mPath.lineTo(0, r + d + r); + mPath.lineTo(d, r + d); + mPath.lineTo(0, r); + } + mPath.close(); + } + + private void drawVerticalPath(float w, float h, float r, float d) { + if (mType == BEGIN) { + mPath.moveTo(0, 0); + mPath.lineTo(w, 0); + } else { + mPath.moveTo(0, d); + mPath.lineTo(r, d); + mPath.lineTo(r + d, 0); + mPath.lineTo(r + d + r, d); + mPath.lineTo(w, d); + } + mPath.lineTo(w, h); + if (mType != END) { + mPath.lineTo(r + d + r, h); + mPath.lineTo(r + d, h - d); + mPath.lineTo(r, h); + } + mPath.lineTo(0, h); + mPath.close(); + } + + private void drawVerticalDownPath(float w, float h, float r, float d) { + mPath.moveTo(0, 0); + if (mType != BEGIN) { + mPath.lineTo(r, 0); + mPath.lineTo(r + d, d); + mPath.lineTo(r + d + r, 0); + } + mPath.lineTo(w, 0); + + if (mType != END) { + mPath.lineTo(w, h - d); + + mPath.lineTo(r + d + r, h - d); + mPath.lineTo(r + d, h); + mPath.lineTo(r, h - d); + + mPath.lineTo(0, h - d); + } else { + mPath.lineTo(w, h); + mPath.lineTo(0, h); + } + + mPath.close(); + } + + public void setBackgroundAlpha(float alpha) { + if (mType != DEFAULT) { + return; + } + mAlpha = alpha; + invalidate(); + } + + public float getAlpha() { + return mAlpha; + } + + public void setOrientation(int orientation) { + mOrientation = orientation; + } + + public void setDuplicateButton(boolean b) { + mDuplicateButton = b; + invalidate(); + } + + public State getState() { + return mState; + } + + public void setState(State state) { + mState = state; + mText = mState.getText(); + mType = mState.getType(); + setBackgroundAlpha(1.0f); + invalidate(); + } + + public void resetPosition() { + setTranslationX(0); + setTranslationY(0); + } + + public boolean isDraggable() { + return mState.isDraggable(); + } +} -- 2.11.0