diff options
author | John Spurlock <jspurlock@google.com> | 2014-04-15 16:14:46 -0400 |
---|---|---|
committer | John Spurlock <jspurlock@google.com> | 2014-04-17 10:26:45 -0400 |
commit | 73203ebf976c403e40deabc15beb5ef01ac20cb0 (patch) | |
tree | f436960279bd2a7e533920dc25bd812d10fd1a00 /packages | |
parent | 33ac0dfc9f9480b71aa45436807682219e3e160b (diff) | |
download | frameworks_base-73203ebf976c403e40deabc15beb5ef01ac20cb0.zip frameworks_base-73203ebf976c403e40deabc15beb5ef01ac20cb0.tar.gz frameworks_base-73203ebf976c403e40deabc15beb5ef01ac20cb0.tar.bz2 |
Interim quick settings update.
Make existing QS panel available via pulldown from header
(or keyguard status view on keyguard), update the affordances
as a hint.
Don't allow QS to scroll, cap to max rows.
Add scrim over panel to indicate that this is purely temporary.
Bug:14081801
Bug:14059974
Change-Id: I166033975cbc44b91f45ee70ea5c7540390670dd
Diffstat (limited to 'packages')
27 files changed, 467 insertions, 172 deletions
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png Binary files differindex 092b561..3c0dc4e 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png Binary files differindex 064860d..3b1944d 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png Binary files differdeleted file mode 100644 index 13f6b7f..0000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png Binary files differdeleted file mode 100644 index ecdb240..0000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png Binary files differdeleted file mode 100644 index c98911c..0000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png Binary files differdeleted file mode 100644 index bb99022..0000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png Binary files differdeleted file mode 100644 index d9d8b13..0000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png Binary files differdeleted file mode 100644 index 09e0a3c..0000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png Binary files differdeleted file mode 100644 index c0855b5..0000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png Binary files differdeleted file mode 100644 index e3fb992..0000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png Binary files differindex ae5d263..8010ce7 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png Binary files differindex 32fbed4..807f607 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png Binary files differindex 990f8bb..6d46fdd 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png Binary files differindex 96eaafe..e562bc2 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png Binary files differindex 60579f9..7742207 100644 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png Binary files differindex abb9b18..a2e8fe1 100644 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png diff --git a/packages/SystemUI/res/layout/flip_settings.xml b/packages/SystemUI/res/layout/flip_settings.xml index 1b8898c5..28d9625 100644 --- a/packages/SystemUI/res/layout/flip_settings.xml +++ b/packages/SystemUI/res/layout/flip_settings.xml @@ -14,18 +14,12 @@ limitations under the License. --> -<com.android.systemui.statusbar.phone.QuickSettingsScrollView +<com.android.systemui.statusbar.phone.QuickSettingsContainerView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/quick_settings_container" + android:padding="@dimen/notification_side_padding" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/close_handle_underlap" - android:overScrollMode="ifContentScrolls" - > - <com.android.systemui.statusbar.phone.QuickSettingsContainerView - android:id="@+id/quick_settings_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:animateLayoutChanges="true" - android:columnCount="@integer/quick_settings_num_columns" - /> -</com.android.systemui.statusbar.phone.QuickSettingsScrollView>
\ No newline at end of file + android:background="#5f000000" + android:animateLayoutChanges="true" + android:columnCount="@integer/quick_settings_num_columns" />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 8f4417e..8a3f090 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -41,7 +41,7 @@ android:layout_width="50dp" android:layout_height="50dp" android:layout_gravity="right|top" - android:layout_marginTop="@*android:dimen/status_bar_height" + android:layout_marginTop="@dimen/status_bar_height" android:visibility="gone" /> <LinearLayout diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 9176d24..2b01a06 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -27,14 +27,14 @@ <include layout="@layout/status_bar" android:layout_width="match_parent" - android:layout_height="@*android:dimen/status_bar_height" /> + android:layout_height="@dimen/status_bar_height" /> <com.android.systemui.statusbar.phone.PanelHolder android:id="@+id/panel_holder" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="@dimen/panel_holder_padding_top" - android:layout_marginBottom="@*android:dimen/navigation_bar_height"> + android:layout_marginBottom="@dimen/navigation_bar_height"> <include layout="@layout/status_bar_expanded" android:layout_width="@dimen/notification_panel_width" android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml index 6476d88..7223773 100644 --- a/packages/SystemUI/res/values-land/config.xml +++ b/packages/SystemUI/res/values-land/config.xml @@ -27,6 +27,9 @@ <!-- The number of columns in the QuickSettings --> <integer name="quick_settings_num_columns">6</integer> + <!-- The maximum number of rows in the QuickSettings --> + <integer name="quick_settings_max_rows">2</integer> + <!-- The number of columns that the top level tiles span in the QuickSettings --> <integer name="quick_settings_user_time_settings_tile_span">2</integer> </resources> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index 440ead6..c6bc44d 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -26,6 +26,9 @@ <!-- The number of columns in the QuickSettings --> <integer name="quick_settings_num_columns">3</integer> + <!-- The maximum number of rows in the QuickSettings --> + <integer name="quick_settings_max_rows">4</integer> + <!-- The number of columns that the top level tiles span in the QuickSettings --> <integer name="quick_settings_user_time_settings_tile_span">1</integer> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 73e3e05..f908a1e 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -81,6 +81,12 @@ <!-- The number of columns in the QuickSettings --> <integer name="quick_settings_num_columns">3</integer> + <!-- The maximum number of rows in the QuickSettings --> + <integer name="quick_settings_max_rows">4</integer> + + <!-- The maximum number of rows in the QuickSettings when on the keyguard --> + <integer name="quick_settings_max_rows_keyguard">3</integer> + <!-- The number of columns that the top level tiles span in the QuickSettings --> <integer name="quick_settings_user_time_settings_tile_span">1</integer> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index e7959ab..9aacf42 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -269,4 +269,7 @@ <!-- Camera affordance drag distance --> <dimen name="camera_drag_distance">100dp</dimen> + + <dimen name="quick_settings_tmp_scrim_stroke_width">8dp</dimen> + <dimen name="quick_settings_tmp_scrim_text_size">30dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/internal.xml b/packages/SystemUI/res/values/internal.xml new file mode 100644 index 0000000..ddaab94 --- /dev/null +++ b/packages/SystemUI/res/values/internal.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<resources> + <dimen name="status_bar_height">@*android:dimen/status_bar_height</dimen> + <dimen name="navigation_bar_height">@*android:dimen/navigation_bar_height</dimen> + <drawable name="notification_quantum_bg">@*android:drawable/notification_quantum_bg</drawable> +</resources> + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 6f93bed..45ac50b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -30,11 +30,14 @@ public class NotificationPanelView extends PanelView { public static final boolean DEBUG_GESTURES = true; PhoneStatusBar mStatusBar; + private View mHeader; + private View mKeyguardStatusView; + private NotificationStackScrollLayout mNotificationStackScroller; private int[] mTempLocation = new int[2]; private int[] mTempChildLocation = new int[2]; private View mNotificationParent; - + private boolean mTrackingSettings; public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); @@ -59,6 +62,8 @@ public class NotificationPanelView extends PanelView { protected void onFinishInflate() { super.onFinishInflate(); + mHeader = findViewById(R.id.header); + mKeyguardStatusView = findViewById(R.id.keyguard_status_view); mNotificationStackScroller = (NotificationStackScrollLayout) findViewById(R.id.notification_stack_scroller); mNotificationParent = findViewById(R.id.notification_container_parent); @@ -99,9 +104,38 @@ public class NotificationPanelView extends PanelView { } @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + // intercept for quick settings + if (event.getAction() == MotionEvent.ACTION_DOWN) { + final View target = mStatusBar.isOnKeyguard() ? mKeyguardStatusView : mHeader; + final boolean inTarget = PhoneStatusBar.inBounds(target, event, true); + if (inTarget && !isInSettings()) { + mTrackingSettings = true; + return true; + } + if (!inTarget && isInSettings()) { + mTrackingSettings = true; + return true; + } + } + return super.onInterceptTouchEvent(event); + } + + @Override public boolean onTouchEvent(MotionEvent event) { // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference // implementation. + if (mTrackingSettings) { + mStatusBar.onSettingsEvent(event); + if (event.getAction() == MotionEvent.ACTION_UP + || event.getAction() == MotionEvent.ACTION_CANCEL) { + mTrackingSettings = false; + } + return true; + } + if (isInSettings()) { + return true; + } return super.onTouchEvent(event); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 5f71516..d577070 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -73,6 +73,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewPropertyAnimator; @@ -97,11 +98,9 @@ import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.InterceptedNotifications; -import com.android.systemui.statusbar.LatestItemView; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.NotificationData.Entry; import com.android.systemui.statusbar.NotificationOverflowContainer; -import com.android.systemui.statusbar.NotificationOverflowIconsView; import com.android.systemui.statusbar.SignalClusterView; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.policy.BatteryController; @@ -233,8 +232,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { int mKeyguardMaxNotificationCount; View mDateTimeView; View mClearButton; - ImageView mSettingsButton, mNotificationButton; - View mKeyguardSettingsFlipButton; + FlipperButton mHeaderFlipper, mKeyguardFlipper; // carrier/wifi label private TextView mCarrierLabel; @@ -314,9 +312,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " + "selfChange=%s userSetup=%s mUserSetup=%s", selfChange, userSetup, mUserSetup)); - if (mSettingsButton != null && mHasFlipSettings) { - mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE); - } + mHeaderFlipper.userSetup(userSetup); + mKeyguardFlipper.userSetup(userSetup); + if (mSettingsPanel != null) { mSettingsPanel.setEnabled(userSetup); } @@ -371,6 +369,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { private Runnable mOnFlipRunnable; private InterceptedNotifications mIntercepted; + private VelocityTracker mSettingsTracker; + private float mSettingsDownY; + private boolean mSettingsCancelled; + private boolean mSettingsClosing; + private int mNotificationPadding; private final OnChildLocationsChangedListener mOnChildLocationsChangedListener = new OnChildLocationsChangedListener() { @@ -631,35 +634,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mDateTimeView.setEnabled(true); } - mSettingsButton = (ImageView) mStatusBarWindow.findViewById(R.id.settings_button); - if (mSettingsButton != null) { - mSettingsButton.setOnClickListener(mSettingsButtonListener); - if (mHasSettingsPanel) { - if (mStatusBarView.hasFullWidthNotifications()) { - // the settings panel is hiding behind this button - mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings); - mSettingsButton.setVisibility(View.VISIBLE); - } else { - // there is a settings panel, but it's on the other side of the (large) screen - final View buttonHolder = mStatusBarWindow.findViewById( - R.id.settings_button_holder); - if (buttonHolder != null) { - buttonHolder.setVisibility(View.GONE); - } - } - } else { - // no settings panel, go straight to settings - mSettingsButton.setVisibility(View.VISIBLE); - mSettingsButton.setImageResource(R.drawable.ic_notify_settings); - } - } - if (mHasFlipSettings) { - mNotificationButton = (ImageView) mStatusBarWindow.findViewById( - R.id.notification_button); - if (mNotificationButton != null) { - mNotificationButton.setOnClickListener(mNotificationButtonListener); - } - } + mHeaderFlipper = new FlipperButton(mNotificationPanelHeader + .findViewById(R.id.settings_button_holder)); + ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub); + mKeyguardFlipper = new FlipperButton(flipStub.inflate()); if (!mNotificationPanelIsFullScreenWidth) { mNotificationPanel.setSystemUiVisibility( @@ -735,6 +713,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } // Quick Settings (where available, some restrictions apply) + mNotificationPadding = mContext.getResources() + .getDimensionPixelSize(R.dimen.notification_side_padding); if (mHasSettingsPanel) { // first, figure out where quick settings should be inflated final View settings_stub; @@ -803,6 +783,87 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { return mStatusBarView; } + public boolean onSettingsEvent(MotionEvent event) { + if (mSettingsTracker != null) { + mSettingsTracker.addMovement(event); + } + + if (event.getAction() == MotionEvent.ACTION_DOWN) { + mSettingsTracker = VelocityTracker.obtain(); + mSettingsDownY = event.getY(); + mSettingsCancelled = false; + mSettingsClosing = mFlipSettingsView.getVisibility() == View.VISIBLE; + mFlipSettingsView.setVisibility(View.VISIBLE); + mStackScroller.setVisibility(View.VISIBLE); + positionSettings(0); + if (!mSettingsClosing) { + mFlipSettingsView.setTranslationY(-mNotificationPanel.getMeasuredHeight()); + } + dispatchSettingsEvent(event); + } else if (mSettingsTracker != null && (event.getAction() == MotionEvent.ACTION_UP + || event.getAction() == MotionEvent.ACTION_CANCEL)) { + final float dy = event.getY() - mSettingsDownY; + final FlipperButton flipper = mOnKeyguard ? mKeyguardFlipper : mHeaderFlipper; + final boolean inButton = flipper.inHolderBounds(event); + final int slop = ViewConfiguration.get(mContext).getScaledTouchSlop(); + final boolean qsTap = mSettingsClosing && Math.abs(dy) < slop; + if (!qsTap && !inButton) { + mSettingsTracker.computeCurrentVelocity(1000); + final float vy = mSettingsTracker.getYVelocity(); + if (dy <= slop || vy <= 0) { + flipToNotifications(); + } else { + flipToSettings(); + } + } + mSettingsTracker.recycle(); + mSettingsTracker = null; + dispatchSettingsEvent(event); + } else if (mSettingsTracker != null && event.getAction() == MotionEvent.ACTION_MOVE) { + final float dy = event.getY() - mSettingsDownY; + positionSettings(dy); + if (mSettingsClosing) { + final boolean qsTap = + Math.abs(dy) < ViewConfiguration.get(mContext).getScaledTouchSlop(); + if (!mSettingsCancelled && !qsTap) { + MotionEvent cancelEvent = MotionEvent.obtainNoHistory(event); + cancelEvent.setAction(MotionEvent.ACTION_CANCEL); + dispatchSettingsEvent(cancelEvent); + mSettingsCancelled = true; + } + } else { + dispatchSettingsEvent(event); + } + } + return true; + } + + private void dispatchSettingsEvent(MotionEvent event) { + final View target = mSettingsClosing ? mFlipSettingsView : mNotificationPanelHeader; + final int[] targetLoc = new int[2]; + target.getLocationInWindow(targetLoc); + final int[] panelLoc = new int[2]; + mNotificationPanel.getLocationInWindow(panelLoc); + final int dx = targetLoc[0] - panelLoc[0]; + final int dy = targetLoc[1] - panelLoc[1]; + event.offsetLocation(-dx, -dy); + target.dispatchTouchEvent(event); + } + + private void positionSettings(float dy) { + final int h = mFlipSettingsView.getMeasuredHeight(); + final int ph = mNotificationPanel.getMeasuredHeight(); + if (mSettingsClosing) { + dy = Math.min(Math.max(-ph, dy), 0); + mFlipSettingsView.setTranslationY(dy); + mStackScroller.setTranslationY(ph + dy); + } else { + dy = Math.min(Math.max(0, dy), ph); + mFlipSettingsView.setTranslationY(-h + dy - mNotificationPadding * 2); + mStackScroller.setTranslationY(dy); + } + } + private void startKeyguard() { KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class); mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, @@ -1163,17 +1224,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { ((ImageView)mClearButton).setImageResource(R.drawable.ic_notify_clear); } - if (mSettingsButton != null) { - // Force asset reloading - mSettingsButton.setImageDrawable(null); - mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings); - } - - if (mNotificationButton != null) { - // Force asset reloading - mNotificationButton.setImageDrawable(null); - mNotificationButton.setImageResource(R.drawable.ic_notifications); - } + mHeaderFlipper.refreshLayout(); + mKeyguardFlipper.refreshLayout(); refreshAllStatusBarIcons(); } @@ -1228,9 +1280,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } } - if (mSettingsButton != null) { - mSettingsButton.setEnabled(isDeviceProvisioned()); - } + mHeaderFlipper.provisionCheck(provisioned); + mKeyguardFlipper.provisionCheck(provisioned); } @Override @@ -1647,6 +1698,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mStatusBarWindow.cancelExpandHelper(); mStatusBarView.collapseAllPanels(true); + if (isFlippedToSettings()) { + flipToNotifications(); + } } } @@ -1694,8 +1748,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { final int FLIP_DURATION_IN = 225; final int FLIP_DURATION = (FLIP_DURATION_IN + FLIP_DURATION_OUT); - Animator mScrollViewAnim, mFlipSettingsViewAnim, mNotificationButtonAnim, - mSettingsButtonAnim, mClearButtonAnim; + Animator mScrollViewAnim, mFlipSettingsViewAnim, mClearButtonAnim; @Override public void animateExpandNotificationsPanel() { @@ -1715,33 +1768,29 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { public void flipToNotifications() { if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel(); if (mScrollViewAnim != null) mScrollViewAnim.cancel(); - if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel(); - if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel(); + mHeaderFlipper.cancel(); + mKeyguardFlipper.cancel(); if (mClearButtonAnim != null) mClearButtonAnim.cancel(); mStackScroller.setVisibility(View.VISIBLE); + final int h = mNotificationPanel.getMeasuredHeight(); + final float settingsY = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : 0; + final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : h; mScrollViewAnim = start( - startDelay(FLIP_DURATION_OUT, + startDelay(0, interpolator(mDecelerateInterpolator, - ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 0f, 1f) - .setDuration(FLIP_DURATION_IN) + ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, 0) + .setDuration(FLIP_DURATION) ))); mFlipSettingsViewAnim = start( setVisibilityWhenDone( - interpolator(mAccelerateInterpolator, - ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 1f, 0f) + interpolator(mDecelerateInterpolator, + ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, settingsY, -h) ) - .setDuration(FLIP_DURATION_OUT), - mFlipSettingsView, View.INVISIBLE)); - mNotificationButtonAnim = start( - setVisibilityWhenDone( - ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f) .setDuration(FLIP_DURATION), - mNotificationButton, View.INVISIBLE)); - mSettingsButton.setVisibility(View.VISIBLE); - mSettingsButtonAnim = start( - ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f) - .setDuration(FLIP_DURATION)); + mFlipSettingsView, View.INVISIBLE)); + mHeaderFlipper.flipToNotifications(); + mKeyguardFlipper.flipToNotifications(); mClearButton.setVisibility(View.VISIBLE); mClearButton.setAlpha(0f); setAreThereNotifications(); // this will show/hide the button as necessary @@ -1767,7 +1816,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (mHasFlipSettings) { mNotificationPanel.expand(); - if (mFlipSettingsView.getVisibility() != View.VISIBLE) { + if (mFlipSettingsView.getVisibility() != View.VISIBLE + || mFlipSettingsView.getTranslationY() < 0) { flipToSettings(); } } else if (mSettingsPanel != null) { @@ -1777,23 +1827,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (false) postStartTracing(); } - public void switchToSettings() { - // Settings are not available in setup - if (!mUserSetup) return; - - mFlipSettingsView.setScaleX(1f); - mFlipSettingsView.setVisibility(View.VISIBLE); - mSettingsButton.setVisibility(View.GONE); - mStackScroller.setVisibility(View.GONE); - mStackScroller.setScaleX(0f); - mNotificationButton.setVisibility(View.VISIBLE); - mNotificationButton.setAlpha(1f); - mClearButton.setVisibility(View.GONE); - if (mOnFlipRunnable != null) { - mOnFlipRunnable.run(); - } - } - public boolean isFlippedToSettings() { if (mFlipSettingsView != null) { return mFlipSettingsView.getVisibility() == View.VISIBLE; @@ -1807,34 +1840,29 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel(); if (mScrollViewAnim != null) mScrollViewAnim.cancel(); - if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel(); - if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel(); + mHeaderFlipper.cancel(); + mKeyguardFlipper.cancel(); if (mClearButtonAnim != null) mClearButtonAnim.cancel(); mFlipSettingsView.setVisibility(View.VISIBLE); - mFlipSettingsView.setScaleX(0f); + final int h = mNotificationPanel.getMeasuredHeight(); + final float settingsY = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : -h; + final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : 0; mFlipSettingsViewAnim = start( - startDelay(FLIP_DURATION_OUT, - interpolator(mDecelerateInterpolator, - ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 0f, 1f) - .setDuration(FLIP_DURATION_IN) - ))); + startDelay(0, + interpolator(mDecelerateInterpolator, + ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, settingsY, 0f) + .setDuration(FLIP_DURATION) + ))); mScrollViewAnim = start( setVisibilityWhenDone( - interpolator(mAccelerateInterpolator, - ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 1f, 0f) + interpolator(mDecelerateInterpolator, + ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, h) ) - .setDuration(FLIP_DURATION_OUT), - mStackScroller, View.INVISIBLE)); - mSettingsButtonAnim = start( - setVisibilityWhenDone( - ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f) .setDuration(FLIP_DURATION), mStackScroller, View.INVISIBLE)); - mNotificationButton.setVisibility(View.VISIBLE); - mNotificationButtonAnim = start( - ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f) - .setDuration(FLIP_DURATION)); + mHeaderFlipper.flipToSettings(); + mKeyguardFlipper.flipToSettings(); mClearButtonAnim = start( setVisibilityWhenDone( ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f) @@ -1883,18 +1911,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { // reset things to their proper state if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel(); if (mScrollViewAnim != null) mScrollViewAnim.cancel(); - if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel(); - if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel(); if (mClearButtonAnim != null) mClearButtonAnim.cancel(); - mStackScroller.setScaleX(1f); mStackScroller.setVisibility(View.VISIBLE); - mSettingsButton.setAlpha(1f); - mSettingsButton.setVisibility(View.VISIBLE); mNotificationPanel.setVisibility(View.GONE); mFlipSettingsView.setVisibility(View.GONE); - mNotificationButton.setVisibility(View.GONE); + setAreThereNotifications(); // show the clear button + + mHeaderFlipper.reset(); + mKeyguardFlipper.reset(); } mExpandedVisible = false; @@ -2947,15 +2973,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } mKeyguardStatusView.setVisibility(View.VISIBLE); mNotificationPanelHeader.setVisibility(View.GONE); - if (mKeyguardSettingsFlipButton == null) { - ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub); - mKeyguardSettingsFlipButton = flipStub.inflate(); - installSettingsButton(mKeyguardSettingsFlipButton); - } - mKeyguardSettingsFlipButton.setVisibility(View.VISIBLE); - mKeyguardSettingsFlipButton.findViewById(R.id.settings_button).setVisibility(View.VISIBLE); - mKeyguardSettingsFlipButton.findViewById(R.id.notification_button) - .setVisibility(View.INVISIBLE); + + mKeyguardFlipper.setVisibility(View.VISIBLE); + mSettingsContainer.setKeyguardShowing(true); updateRowStates(); } @@ -2963,9 +2983,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { mOnKeyguard = false; mKeyguardStatusView.setVisibility(View.GONE); mNotificationPanelHeader.setVisibility(View.VISIBLE); - if (mKeyguardSettingsFlipButton != null) { - mKeyguardSettingsFlipButton.setVisibility(View.GONE); - } + + mKeyguardFlipper.setVisibility(View.GONE); + mSettingsContainer.setKeyguardShowing(false); updateRowStates(); instantCollapseNotificationPanel(); } @@ -3030,39 +3050,112 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } } - private void installSettingsButton(View parent) { - final ImageView settingsButton = - (ImageView) mStatusBarWindow.findViewById(R.id.settings_button); - final ImageView notificationButton = - (ImageView) mStatusBarWindow.findViewById(R.id.notification_button); - if (settingsButton != null) { - settingsButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - animateExpandSettingsPanel(); - v.setVisibility(View.INVISIBLE); - notificationButton.setVisibility(View.VISIBLE); + public static boolean inBounds(View view, MotionEvent event, boolean orAbove) { + final int[] location = new int[2]; + view.getLocationInWindow(location); + final int rx = (int) event.getRawX(); + final int ry = (int) event.getRawY(); + return rx >= location[0] && rx <= location[0] + view.getMeasuredWidth() + && (orAbove || ry >= location[1]) && ry <= location[1] + view.getMeasuredHeight(); + } + + private final class FlipperButton { + private final View mHolder; + + private ImageView mSettingsButton, mNotificationButton; + private Animator mSettingsButtonAnim, mNotificationButtonAnim; + + public FlipperButton(View holder) { + mHolder = holder; + mSettingsButton = (ImageView) holder.findViewById(R.id.settings_button); + if (mSettingsButton != null) { + mSettingsButton.setOnClickListener(mSettingsButtonListener); + if (mHasSettingsPanel) { + // the settings panel is hiding behind this button + mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings); + mSettingsButton.setVisibility(View.VISIBLE); + } else { + // no settings panel, go straight to settings + mSettingsButton.setVisibility(View.VISIBLE); + mSettingsButton.setImageResource(R.drawable.ic_notify_settings); } - }); - settingsButton.setVisibility(View.VISIBLE); - if (mHasSettingsPanel) { - // the settings panel is hiding behind this button - settingsButton.setImageResource(R.drawable.ic_notify_quicksettings); - } else { - // no settings panel, go straight to settings - settingsButton.setImageResource(R.drawable.ic_notify_settings); } - } - if (notificationButton != null) { - notificationButton.setVisibility(View.INVISIBLE); - notificationButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - flipToNotifications(); - v.setVisibility(View.INVISIBLE); - settingsButton.setVisibility(View.VISIBLE); + if (mHasFlipSettings) { + mNotificationButton = (ImageView) holder.findViewById(R.id.notification_button); + if (mNotificationButton != null) { + mNotificationButton.setOnClickListener(mNotificationButtonListener); } - }); + } + } + + public boolean inHolderBounds(MotionEvent event) { + return inBounds(mHolder, event, false); + } + + public void provisionCheck(boolean provisioned) { + if (mSettingsButton != null) { + mSettingsButton.setEnabled(provisioned); + } + } + + public void userSetup(boolean userSetup) { + if (mSettingsButton != null && mHasFlipSettings) { + mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE); + } + } + + public void reset() { + cancel(); + mSettingsButton.setVisibility(View.VISIBLE); + mNotificationButton.setVisibility(View.GONE); + } + + public void refreshLayout() { + if (mSettingsButton != null) { + // Force asset reloading + mSettingsButton.setImageDrawable(null); + mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings); + } + + if (mNotificationButton != null) { + // Force asset reloading + mNotificationButton.setImageDrawable(null); + mNotificationButton.setImageResource(R.drawable.ic_notifications); + } + } + + public void flipToSettings() { + mSettingsButtonAnim = start( + setVisibilityWhenDone( + ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f) + .setDuration(FLIP_DURATION), + mStackScroller, View.INVISIBLE)); + mNotificationButton.setVisibility(View.VISIBLE); + mNotificationButtonAnim = start( + ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f) + .setDuration(FLIP_DURATION)); + } + + public void flipToNotifications() { + mNotificationButtonAnim = start( + setVisibilityWhenDone( + ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f) + .setDuration(FLIP_DURATION), + mNotificationButton, View.INVISIBLE)); + + mSettingsButton.setVisibility(View.VISIBLE); + mSettingsButtonAnim = start( + ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f) + .setDuration(FLIP_DURATION)); + } + + public void cancel() { + if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel(); + if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel(); + } + + public void setVisibility(int vis) { + mHolder.setVisibility(vis); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java index 17ee017..02e9c0d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java @@ -19,7 +19,13 @@ package com.android.systemui.statusbar.phone; import android.animation.LayoutTransition; import android.content.Context; import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.Typeface; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -31,30 +37,58 @@ import com.android.systemui.R; */ class QuickSettingsContainerView extends FrameLayout { + private static boolean sShowScrim = true; + + private final Context mContext; + // The number of columns in the QuickSettings grid private int mNumColumns; + private boolean mKeyguardShowing; + private int mMaxRows; + private int mMaxRowsOnKeyguard; + // The gap between tiles in the QuickSettings grid private float mCellGap; + private ScrimView mScrim; + public QuickSettingsContainerView(Context context, AttributeSet attrs) { super(context, attrs); - + mContext = context; updateResources(); } @Override protected void onFinishInflate() { super.onFinishInflate(); - + mScrim = new ScrimView(mContext); + addView(mScrim); + mScrim.setAlpha(sShowScrim ? 1 : 0); // TODO: Setup the layout transitions LayoutTransition transitions = getLayoutTransition(); } + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mScrim.getAlpha() == 1) { + mScrim.animate().alpha(0).setDuration(1000).start(); + sShowScrim = false; + } + return super.onTouchEvent(event); + } + void updateResources() { Resources r = getContext().getResources(); mCellGap = r.getDimension(R.dimen.quick_settings_cell_gap); mNumColumns = r.getInteger(R.integer.quick_settings_num_columns); + mMaxRows = r.getInteger(R.integer.quick_settings_max_rows); + mMaxRowsOnKeyguard = r.getInteger(R.integer.quick_settings_max_rows_keyguard); + requestLayout(); + } + + void setKeyguardShowing(boolean showing) { + mKeyguardShowing = showing; requestLayout(); } @@ -71,10 +105,18 @@ class QuickSettingsContainerView extends FrameLayout { final int N = getChildCount(); int cellHeight = 0; int cursor = 0; + int maxRows = mKeyguardShowing ? mMaxRowsOnKeyguard : mMaxRows; + for (int i = 0; i < N; ++i) { + if (getChildAt(i).equals(mScrim)) { + continue; + } // Update the child's width QuickSettingsTileView v = (QuickSettingsTileView) getChildAt(i); if (v.getVisibility() != View.GONE) { + int row = (int) (cursor / mNumColumns); + if (row >= maxRows) continue; + ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); int colSpan = v.getColumnSpan(); lp.width = (int) ((colSpan * cellWidth) + (colSpan - 1) * mCellGap); @@ -102,6 +144,7 @@ class QuickSettingsContainerView extends FrameLayout { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + mScrim.bringToFront(); final int N = getChildCount(); final boolean isLayoutRtl = isLayoutRtl(); final int width = getWidth(); @@ -109,8 +152,18 @@ class QuickSettingsContainerView extends FrameLayout { int x = getPaddingStart(); int y = getPaddingTop(); int cursor = 0; + int maxRows = mKeyguardShowing ? mMaxRowsOnKeyguard : mMaxRows; for (int i = 0; i < N; ++i) { + if (getChildAt(i).equals(mScrim)) { + int w = right - left - getPaddingLeft() - getPaddingRight(); + int h = bottom - top - getPaddingTop() - getPaddingBottom(); + mScrim.measure( + MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); + mScrim.layout(getPaddingLeft(), getPaddingTop(), right, bottom); + continue; + } QuickSettingsTileView child = (QuickSettingsTileView) getChildAt(i); ViewGroup.LayoutParams lp = child.getLayoutParams(); if (child.getVisibility() != GONE) { @@ -121,6 +174,7 @@ class QuickSettingsContainerView extends FrameLayout { final int childHeight = lp.height; int row = (int) (cursor / mNumColumns); + if (row >= maxRows) continue; // Push the item to the next row if it can't fit on this one if ((col + colSpan) > mNumColumns) { @@ -150,4 +204,87 @@ class QuickSettingsContainerView extends FrameLayout { } } } + + private static final class ScrimView extends View { + private static final int COLOR = 0xaf4285f4; + + private final Paint mLinePaint; + private final int mStrokeWidth; + private final Rect mTmp = new Rect(); + private final Paint mTextPaint; + private final int mTextSize; + + public ScrimView(Context context) { + super(context); + setFocusable(false); + final Resources res = context.getResources(); + mStrokeWidth = res.getDimensionPixelSize(R.dimen.quick_settings_tmp_scrim_stroke_width); + mTextSize = res.getDimensionPixelSize(R.dimen.quick_settings_tmp_scrim_text_size); + + mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mLinePaint.setColor(COLOR); + mLinePaint.setStrokeWidth(mStrokeWidth); + mLinePaint.setStrokeJoin(Paint.Join.ROUND); + mLinePaint.setStrokeCap(Paint.Cap.ROUND); + mLinePaint.setStyle(Paint.Style.STROKE); + + mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTextPaint.setColor(COLOR); + mTextPaint.setTextSize(mTextSize); + mTextPaint.setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD)); + } + + @Override + protected void onDraw(Canvas canvas) { + final int w = getMeasuredWidth(); + final int h = getMeasuredHeight(); + final int f = mStrokeWidth * 3 / 4; + + canvas.drawPath(line(f, h / 2, w - f, h / 2), mLinePaint); + canvas.drawPath(line(w / 2, f, w / 2, h - f), mLinePaint); + + final int s = mStrokeWidth; + mTextPaint.setTextAlign(Paint.Align.RIGHT); + canvas.drawText("FUTURE", w / 2 - s, h / 2 - s, mTextPaint); + mTextPaint.setTextAlign(Paint.Align.LEFT); + canvas.drawText("SITE OF", w / 2 + s, h / 2 - s , mTextPaint); + mTextPaint.setTextAlign(Paint.Align.RIGHT); + drawUnder(canvas, "QUANTUM", w / 2 - s, h / 2 + s); + mTextPaint.setTextAlign(Paint.Align.LEFT); + drawUnder(canvas, "SETTINGS", w / 2 + s, h / 2 + s); + } + + private void drawUnder(Canvas c, String text, float x, float y) { + if (mTmp.isEmpty()) { + mTextPaint.getTextBounds(text, 0, text.length(), mTmp); + } + c.drawText(text, x, y + mTmp.height() * .85f, mTextPaint); + } + + private Path line(float x1, float y1, float x2, float y2) { + final int a = mStrokeWidth * 2; + final Path p = new Path(); + p.moveTo(x1, y1); + p.lineTo(x2, y2); + if (y1 == y2) { + p.moveTo(x1 + a, y1 + a); + p.lineTo(x1, y1); + p.lineTo(x1 + a, y1 - a); + + p.moveTo(x2 - a, y2 - a); + p.lineTo(x2, y2); + p.lineTo(x2 - a, y2 + a); + } + if (x1 == x2) { + p.moveTo(x1 - a, y1 + a); + p.lineTo(x1, y1); + p.lineTo(x1 + a, y1 + a); + + p.moveTo(x2 - a, y2 - a); + p.lineTo(x2, y2); + p.lineTo(x2 + a, y2 - a); + } + return p; + } + } }
\ No newline at end of file |