import android.app.AlarmManager;
import android.app.PendingIntent;
+import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
+import android.net.Uri;
+import android.provider.AlarmClock;
+import android.provider.CalendarContract;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.util.TypedValue;
import android.widget.RelativeLayout;
import android.widget.Switch;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSPanel.Callback;
import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSTile.DetailAdapter;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.WeatherController;
+import com.android.systemui.statusbar.policy.WeatherControllerImpl;
+import com.android.systemui.tuner.TunerService;
import java.text.NumberFormat;
+import cyanogenmod.providers.CMSettings;
+import cyanogenmod.weather.util.WeatherUtils;
+
/**
* The view to manage the header area in the expanded status bar.
*/
-public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener,
- BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback {
+public class StatusBarHeaderView extends BaseStatusBarHeader implements View.OnClickListener,
+ BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback,
+ EmergencyListener, WeatherController.Callback, TunerService.Tunable {
private boolean mExpanded;
private boolean mListening;
private ViewGroup mSystemIconsContainer;
+ private ViewGroup mWeatherContainer;
private View mSystemIconsSuperContainer;
private View mDateGroup;
private View mClock;
private TextView mDateExpanded;
private LinearLayout mSystemIcons;
private View mSignalCluster;
- private View mSettingsButton;
+ private SettingsButton mSettingsButton;
+ private View mSettingsContainer;
private View mQsDetailHeader;
private TextView mQsDetailHeaderTitle;
private Switch mQsDetailHeaderSwitch;
private TextView mEmergencyCallsOnly;
private TextView mBatteryLevel;
private TextView mAlarmStatus;
+ private TextView mWeatherLine1, mWeatherLine2;
private boolean mShowEmergencyCallsOnly;
private boolean mAlarmShowing;
private ActivityStarter mActivityStarter;
private BatteryController mBatteryController;
private NextAlarmController mNextAlarmController;
+ private WeatherController mWeatherController;
private QSPanel mQSPanel;
-
private final Rect mClipBounds = new Rect();
private boolean mCaptureValues;
private float mCurrentT;
private boolean mShowingDetail;
+ private boolean mDetailTransitioning;
+ private boolean mShowWeather;
+
+ private boolean mAllowExpand = true;
public StatusBarHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container);
mSystemIconsSuperContainer.setOnClickListener(this);
mDateGroup = findViewById(R.id.date_group);
+ mDateGroup.setOnClickListener(this);
mClock = findViewById(R.id.clock);
+ mClock.setOnClickListener(this);
mTime = (TextView) findViewById(R.id.time_view);
mAmPm = (TextView) findViewById(R.id.am_pm_view);
mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
mDateCollapsed = (TextView) findViewById(R.id.date_collapsed);
mDateExpanded = (TextView) findViewById(R.id.date_expanded);
- mSettingsButton = findViewById(R.id.settings_button);
+ mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
+ mSettingsContainer = findViewById(R.id.settings_button_container);
mSettingsButton.setOnClickListener(this);
mQsDetailHeader = findViewById(R.id.qs_detail_header);
mQsDetailHeader.setAlpha(0);
mAlarmStatus.setOnClickListener(this);
mSignalCluster = findViewById(R.id.signal_cluster);
mSystemIcons = (LinearLayout) findViewById(R.id.system_icons);
+ mWeatherContainer = (LinearLayout) findViewById(R.id.weather_container);
+ mWeatherContainer.setOnClickListener(this);
+ mWeatherLine1 = (TextView) findViewById(R.id.weather_line_1);
+ mWeatherLine2 = (TextView) findViewById(R.id.weather_line_2);
loadDimens();
updateVisibilities();
updateClockScale();
}
});
requestCaptureValues();
+
+ // RenderThread is doing more harm than good when touching the header (to expand quick
+ // settings), so disable it for this view
+ ((RippleDrawable) getBackground()).setForceSoftware(true);
+ ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+ ((RippleDrawable) mSystemIconsSuperContainer.getBackground()).setForceSoftware(true);
}
@Override
mNextAlarmController = nextAlarmController;
}
+ @Override
+ public void setWeatherController(WeatherController weatherController) {
+ mWeatherController = weatherController;
+ }
+
public int getCollapsedHeight() {
return mCollapsedHeight;
}
public int getExpandedHeight() {
- return mExpandedHeight;
+ return mAllowExpand ? mExpandedHeight : mCollapsedHeight;
}
public void setListening(boolean listening) {
}
public void setExpanded(boolean expanded) {
+ if (!mAllowExpand) {
+ expanded = false;
+ }
boolean changed = expanded != mExpanded;
mExpanded = expanded;
if (changed) {
mDateCollapsed.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE);
mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
- mSettingsButton.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
+ mSettingsContainer.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
+ mWeatherContainer.setVisibility(mExpanded && mShowWeather ? View.VISIBLE : View.GONE);
mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE);
if (mSignalCluster != null) {
updateSignalClusterDetachment();
}
mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE);
mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
+ mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(View.INVISIBLE);
}
private void updateSignalClusterDetachment() {
private void updateSystemIconsLayoutParams() {
RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams();
int rule = mExpanded
- ? mSettingsButton.getId()
+ ? mSettingsContainer.getId()
: mMultiUserSwitch.getId();
if (rule != lp.getRules()[RelativeLayout.START_OF]) {
lp.addRule(RelativeLayout.START_OF, rule);
private void updateListeners() {
if (mListening) {
+ TunerService.get(getContext()).addTunable(this,
+ "cmsystem:" + CMSettings.System.STATUS_BAR_SHOW_WEATHER);
mBatteryController.addStateChangedCallback(this);
mNextAlarmController.addStateChangedCallback(this);
+ mWeatherController.addCallback(this);
} else {
mBatteryController.removeStateChangedCallback(this);
mNextAlarmController.removeStateChangedCallback(this);
+ mWeatherController.removeCallback(this);
+ TunerService.get(getContext()).removeTunable(this);
}
}
}
@Override
- public void onPowerSaveChanged() {
+ public void onPowerSaveChanged(boolean isPowerSave) {
// could not care less
}
requestCaptureValues();
}
+ @Override
+ public void onWeatherChanged(WeatherController.WeatherInfo info) {
+ if (Double.isNaN(info.temp) || info.condition == null) {
+ mWeatherLine1.setText(null);
+ } else {
+ mWeatherLine1.setText(mContext.getString(
+ R.string.status_bar_expanded_header_weather_format,
+ WeatherUtils.formatTemperature(info.temp, info.tempUnit),
+ info.condition));
+ }
+ mWeatherLine2.setText(info.city);
+ }
+
private void updateClickTargets() {
mMultiUserSwitch.setClickable(mExpanded);
mMultiUserSwitch.setFocusable(mExpanded);
}
@Override
+ public void setCallback(Callback qsPanelCallback) {
+ }
+
+ @Override
public void onClick(View v) {
if (v == mSettingsButton) {
+ if (mSettingsButton.isTunerClick()) {
+ if (TunerService.isTunerEnabled(mContext)) {
+ TunerService.showResetRequest(mContext, new Runnable() {
+ @Override
+ public void run() {
+ // Relaunch settings so that the tuner disappears.
+ startSettingsActivity();
+ }
+ });
+ } else {
+ Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
+ TunerService.setTunerEnabled(mContext, true);
+ }
+ }
startSettingsActivity();
} else if (v == mSystemIconsSuperContainer) {
startBatteryActivity();
if (showIntent != null) {
mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
}
+ } else if (v == mClock) {
+ startClockActivity();
+ } else if (v == mDateGroup) {
+ startDateActivity();
+ } else if (v == mWeatherContainer) {
+ startForecastActivity();
}
}
true /* dismissShade */);
}
+ private void startClockActivity() {
+ mActivityStarter.startActivity(new Intent(AlarmClock.ACTION_SHOW_ALARMS),
+ true /* dismissShade */);
+ }
+
+ private void startDateActivity() {
+ Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
+ builder.appendPath("time");
+ ContentUris.appendId(builder, System.currentTimeMillis());
+ Intent intent = new Intent(Intent.ACTION_VIEW).setData(builder.build());
+ mActivityStarter.startActivity(intent, true /* dismissShade */);
+ }
+
+ private void startForecastActivity() {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setComponent(WeatherControllerImpl.COMPONENT_WEATHER_FORECAST);
+ mActivityStarter.startActivity(intent, true /* dismissShade */);
+ }
+
public void setQSPanel(QSPanel qsp) {
mQSPanel = qsp;
if (mQSPanel != null) {
return true;
}
- public void setShowEmergencyCallsOnly(boolean show) {
+ @Override
+ public void setEmergencyCallsOnly(boolean show) {
boolean changed = show != mShowEmergencyCallsOnly;
if (changed) {
mShowEmergencyCallsOnly = show;
target.avatarScale = mMultiUserAvatar.getScaleX();
target.avatarX = mMultiUserSwitch.getLeft() + mMultiUserAvatar.getLeft();
target.avatarY = mMultiUserSwitch.getTop() + mMultiUserAvatar.getTop();
+ target.weatherY = mClock.getBottom() - mWeatherLine1.getHeight();
if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
target.batteryX = mSystemIconsSuperContainer.getLeft()
+ mSystemIconsContainer.getRight();
}
target.batteryY = mSystemIconsSuperContainer.getTop() + mSystemIconsContainer.getTop();
target.batteryLevelAlpha = getAlphaForVisibility(mBatteryLevel);
- target.settingsAlpha = getAlphaForVisibility(mSettingsButton);
+ target.settingsAlpha = getAlphaForVisibility(mSettingsContainer);
target.settingsTranslation = mExpanded
? 0
- : mMultiUserSwitch.getLeft() - mSettingsButton.getLeft();
+ : mMultiUserSwitch.getLeft() - mSettingsContainer.getLeft();
target.signalClusterAlpha = mSignalClusterDetached ? 0f : 1f;
target.settingsRotation = !mExpanded ? 90f : 0f;
}
mTime.setScaleY(values.timeScale);
mClock.setY(values.clockY - mClock.getHeight());
mDateGroup.setY(values.dateY);
+ mWeatherContainer.setY(values.weatherY);
mAlarmStatus.setY(values.dateY - mAlarmStatus.getPaddingTop());
mMultiUserAvatar.setScaleX(values.avatarScale);
mMultiUserAvatar.setScaleY(values.avatarScale);
mSignalCluster.setTranslationX(0f);
mSignalCluster.setTranslationY(0f);
}
- mSettingsButton.setTranslationY(mSystemIconsSuperContainer.getTranslationY());
- mSettingsButton.setTranslationX(values.settingsTranslation);
- mSettingsButton.setRotation(values.settingsRotation);
+ if (!mSettingsButton.isAnimating()) {
+ mSettingsContainer.setTranslationY(mSystemIconsSuperContainer.getTranslationY());
+ mSettingsContainer.setTranslationX(values.settingsTranslation);
+ mSettingsButton.setRotation(values.settingsRotation);
+ }
applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha);
- if (!mShowingDetail) {
+ if (!mShowingDetail && !mDetailTransitioning) {
// Otherwise it needs to stay invisible
applyAlpha(mAlarmStatus, values.alarmStatusAlpha);
}
applyAlpha(mDateCollapsed, values.dateCollapsedAlpha);
applyAlpha(mDateExpanded, values.dateExpandedAlpha);
applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
- applyAlpha(mSettingsButton, values.settingsAlpha);
+ applyAlpha(mSettingsContainer, values.settingsAlpha);
+ applyAlpha(mWeatherLine1, values.settingsAlpha);
+ applyAlpha(mWeatherLine2, values.settingsAlpha);
applyAlpha(mSignalCluster, values.signalClusterAlpha);
if (!mExpanded) {
mTime.setScaleX(1f);
float settingsTranslation;
float signalClusterAlpha;
float settingsRotation;
+ float weatherY;
public void interpoloate(LayoutValues v1, LayoutValues v2, float t) {
timeScale = v1.timeScale * (1 - t) + v2.timeScale * t;
batteryX = v1.batteryX * (1 - t) + v2.batteryX * t;
batteryY = v1.batteryY * (1 - t) + v2.batteryY * t;
settingsTranslation = v1.settingsTranslation * (1 - t) + v2.settingsTranslation * t;
+ weatherY = v1.weatherY * (1 - t) + v2.weatherY * t;
float t1 = Math.max(0, t - 0.5f) * 2;
settingsRotation = v1.settingsRotation * (1 - t1) + v2.settingsRotation * t1;
}
@Override
- public void onShowingDetail(final QSTile.DetailAdapter detail) {
+ public void onShowingDetail(final DetailAdapter detail, int x, int y) {
+ mDetailTransitioning = true;
post(new Runnable() {
@Override
public void run() {
final boolean showingDetail = detail != null;
transition(mClock, !showingDetail);
transition(mDateGroup, !showingDetail);
+ if (mShowWeather) {
+ transition(mWeatherContainer, !showingDetail);
+ }
if (mAlarmShowing) {
transition(mAlarmStatus, !showingDetail);
}
mQsDetailHeader.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- detail.setToggleState(!mQsDetailHeaderSwitch.isChecked());
+ boolean checked = !mQsDetailHeaderSwitch.isChecked();
+ mQsDetailHeaderSwitch.setChecked(checked);
+ detail.setToggleState(checked);
}
});
}
if (!in) {
v.setVisibility(INVISIBLE);
}
+ mDetailTransitioning = false;
}
})
.start();
}
};
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (key.endsWith(CMSettings.System.STATUS_BAR_SHOW_WEATHER)) {
+ mShowWeather = newValue == null || "1".equals(newValue);
+ updateVisibilities();
+ }
+ }
}