14efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren/*
24efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Copyright (C) 2013 The Android Open Source Project
34efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren *
44efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Licensed under the Apache License, Version 2.0 (the "License");
54efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * you may not use this file except in compliance with the License.
64efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * You may obtain a copy of the License at
74efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren *
84efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren *      http://www.apache.org/licenses/LICENSE-2.0
94efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren *
104efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Unless required by applicable law or agreed to in writing, software
114efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * distributed under the License is distributed on an "AS IS" BASIS,
124efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * See the License for the specific language governing permissions and
144efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * limitations under the License.
154efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */
164efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
174efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenpackage com.android.camera.ui;
184efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
194efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.content.Context;
204efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.content.res.Configuration;
214efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.util.AttributeSet;
224efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.view.Gravity;
234efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.view.View;
244efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.view.ViewGroup;
254efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.widget.LinearLayout;
264efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
274efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport java.util.ArrayList;
284efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport java.util.List;
294efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
304efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren/**
314efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * TopRightWeightedLayout is a LinearLayout that reorders its
324efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * children such that the right most child is the top most child
334efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * on an orientation change.
344efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */
354efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenpublic class TopRightWeightedLayout extends LinearLayout {
364efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    public TopRightWeightedLayout(Context context, AttributeSet attrs) {
374efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        super(context, attrs);
384efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
394efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
404efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    @Override
414efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    public void onFinishInflate() {
424efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        Configuration configuration = getContext().getResources().getConfiguration();
434efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        checkOrientation(configuration.orientation);
444efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
454efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
464efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    @Override
474efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    public void onConfigurationChanged(Configuration configuration) {
484efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        super.onConfigurationChanged(configuration);
494efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        checkOrientation(configuration.orientation);
504efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
514efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
524efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
534efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * Set the orientation of this layout if it has changed,
544efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * and center the elements based on the new orientation.
554efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
564efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    private void checkOrientation(int orientation) {
574efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        final boolean isHorizontal = LinearLayout.HORIZONTAL == getOrientation();
584efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        final boolean isPortrait = Configuration.ORIENTATION_PORTRAIT == orientation;
594efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        if (isPortrait && !isHorizontal) {
604efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            // Portrait orientation is out of sync, setting to horizontal
614efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            // and reversing children
62a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            fixGravityAndPadding(LinearLayout.HORIZONTAL);
634efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            setOrientation(LinearLayout.HORIZONTAL);
644efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            reverseChildren();
654efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            requestLayout();
664efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        } else if (!isPortrait && isHorizontal) {
674efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            // Landscape orientation is out of sync, setting to vertical
684efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            // and reversing children
69a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            fixGravityAndPadding(LinearLayout.VERTICAL);
704efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            setOrientation(LinearLayout.VERTICAL);
714efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            reverseChildren();
724efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            requestLayout();
734efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        }
744efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
754efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
764efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
774efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * Reverse the ordering of the children in this layout.
784efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * Note: bringChildToFront produced a non-deterministic ordering.
794efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
804efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    private void reverseChildren() {
814efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        List<View> children = new ArrayList<View>();
824efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        for (int i = getChildCount() - 1; i >= 0; i--) {
834efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            children.add(getChildAt(i));
844efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        }
854efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        for (View v : children) {
864efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            bringChildToFront(v);
874efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        }
884efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
891d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague
901d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague    /**
911d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague     * Swap gravity:
921d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague     * left for bottom
931d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague     * right for top
941d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague     * center horizontal for center vertical
951d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague     * etc
96a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague     *
97a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague     * also swap left|right padding for bottom|top
981d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague     */
99a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague    private void fixGravityAndPadding(int direction) {
1001d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague        for (int i = 0; i < getChildCount(); i++) {
101a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            // gravity swap
1021d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            View v = getChildAt(i);
1031d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) v.getLayoutParams();
1041d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            int gravity = layoutParams.gravity;
1051d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague
1061d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            if (direction == LinearLayout.VERTICAL) {
1071d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                if ((gravity & Gravity.LEFT) != 0) {   // if gravity left is set . . .
1081d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    gravity &= ~Gravity.LEFT;          // unset left
1091d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    gravity |= Gravity.BOTTOM;         // and set bottom
1101d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                }
1111d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            } else {
1121d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                if ((gravity & Gravity.BOTTOM) != 0) { // etc
1131d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    gravity &= ~Gravity.BOTTOM;
1141d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    gravity |= Gravity.LEFT;
1151d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                }
1161d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            }
1171d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague
1181d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            if (direction == LinearLayout.VERTICAL) {
1191d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                if ((gravity & Gravity.RIGHT) != 0) {
1201d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    gravity &= ~Gravity.RIGHT;
1211d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    gravity |= Gravity.TOP;
1221d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                }
1231d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            } else {
1241d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                if ((gravity & Gravity.TOP) != 0) {
1251d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    gravity &= ~Gravity.TOP;
1261d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    gravity |= Gravity.RIGHT;
1271d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                }
1281d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            }
1291d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague
1301d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            // don't mess with children that are centered in both directions
1311d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            if ((gravity & Gravity.CENTER) != Gravity.CENTER) {
1321d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                if (direction == LinearLayout.VERTICAL) {
1331d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    if ((gravity & Gravity.CENTER_VERTICAL) != 0) {
1341d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                        gravity &= ~ Gravity.CENTER_VERTICAL;
1351d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                        gravity |= Gravity.CENTER_HORIZONTAL;
1361d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    }
1371d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                } else {
1381d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    if ((gravity & Gravity.CENTER_HORIZONTAL) != 0) {
1391d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                        gravity &= ~ Gravity.CENTER_HORIZONTAL;
1401d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                        gravity |= Gravity.CENTER_VERTICAL;
1411d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                    }
1421d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague                }
1431d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            }
1441d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague
1451d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague            layoutParams.gravity = gravity;
146a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague
147a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            // padding swap
148a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            int paddingLeft = v.getPaddingLeft();
149a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            int paddingTop = v.getPaddingTop();
150a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            int paddingRight = v.getPaddingRight();
151a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            int paddingBottom = v.getPaddingBottom();
152a84a728d17c439d83a6ebd78e3e54b8480804600Spike Sprague            v.setPadding(paddingBottom, paddingRight, paddingTop, paddingLeft);
1531d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague        }
1541d346bc4df3d0258ee9db30c7232440ed38ee70cSpike Sprague    }
1554efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren}