/* * Copyright (C) 2008 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.systemui.statusbar.powerwidget; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.provider.Settings; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import com.android.systemui.R; public class PowerWidget extends FrameLayout { private static final String TAG = "PowerWidget"; public static final String BUTTON_DELIMITER = "|"; private static final String BUTTONS_DEFAULT = PowerButton.BUTTON_WIFI + BUTTON_DELIMITER + PowerButton.BUTTON_BLUETOOTH + BUTTON_DELIMITER + PowerButton.BUTTON_GPS + BUTTON_DELIMITER + PowerButton.BUTTON_SOUND; private static final FrameLayout.LayoutParams WIDGET_LAYOUT_PARAMS = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, // width = match_parent ViewGroup.LayoutParams.WRAP_CONTENT // height = wrap_content ); private static final LinearLayout.LayoutParams BUTTON_LAYOUT_PARAMS = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, // width = wrap_content ViewGroup.LayoutParams.MATCH_PARENT, // height = match_parent 1.0f // weight = 1 ); private static final int LAYOUT_SCROLL_BUTTON_THRESHOLD = 6; private Context mContext; private LayoutInflater mInflater; private WidgetBroadcastReceiver mBroadcastReceiver = null; private WidgetSettingsObserver mObserver = null; private HorizontalScrollView mScrollView; public PowerWidget(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); // get an initial width updateButtonLayoutWidth(); setupWidget(); updateVisibility(); } public void setupWidget() { Log.i(TAG, "Clearing any old widget stuffs"); // remove all views from the layout removeAllViews(); // unregister our content receiver if (mBroadcastReceiver != null) { mContext.unregisterReceiver(mBroadcastReceiver); } // unobserve our content if (mObserver != null) { mObserver.unobserve(); } // clear the button instances PowerButton.unloadAllButtons(); Log.i(TAG, "Setting up widget"); String buttons = Settings.System.getString(mContext.getContentResolver(), Settings.System.WIDGET_BUTTONS); if (buttons == null) { Log.i(TAG, "Default buttons being loaded"); buttons = BUTTONS_DEFAULT; // Add the WiMAX button if it's supported // if (WimaxHelper.isWimaxSupported(mContext)) { // buttons += BUTTON_DELIMITER + PowerButton.BUTTON_WIMAX; // } } Log.i(TAG, "Button list: " + buttons); // create a linearlayout to hold our buttons LinearLayout ll = new LinearLayout(mContext); ll.setOrientation(LinearLayout.HORIZONTAL); ll.setGravity(Gravity.CENTER_HORIZONTAL); int buttonCount = 0; for (String button : buttons.split("\\|")) { Log.i(TAG, "Setting up button: " + button); // inflate our button, we don't add it to a parent and don't do any // layout shit yet View buttonView = mInflater.inflate(R.layout.power_widget_button, null, false); if (PowerButton.loadButton(button, buttonView)) { // add the button here ll.addView(buttonView, BUTTON_LAYOUT_PARAMS); buttonCount++; } else { Log.e(TAG, "Error setting up button: " + button); } } // we determine if we're using a horizontal scroll view based on a // threshold of button counts if (buttonCount > LAYOUT_SCROLL_BUTTON_THRESHOLD) { // we need our horizontal scroll view to wrap the linear layout mScrollView = new HorizontalScrollView(mContext); // make the fading edge the size of a button (makes it more // noticible that we can scroll mScrollView.setFadingEdgeLength(mContext.getResources().getDisplayMetrics().widthPixels / LAYOUT_SCROLL_BUTTON_THRESHOLD); mScrollView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); mScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER); // set the padding on the linear layout to the size of our // scrollbar, so we don't have them overlap ll.setPadding(ll.getPaddingLeft(), ll.getPaddingTop(), ll.getPaddingRight(), mScrollView.getVerticalScrollbarWidth()); mScrollView.addView(ll, WIDGET_LAYOUT_PARAMS); updateScrollbar(); addView(mScrollView, WIDGET_LAYOUT_PARAMS); } else { // not needed, just add the linear layout addView(ll, WIDGET_LAYOUT_PARAMS); } // set up a broadcast receiver for our intents, based off of what our // power buttons have been loaded setupBroadcastReceiver(); IntentFilter filter = PowerButton.getAllBroadcastIntentFilters(); // we add this so we can update views and such if the settings for our // widget change filter.addAction(Settings.SETTINGS_CHANGED); // we need to detect orientation changes and update the static button // width value appropriately filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); // register the receiver mContext.registerReceiver(mBroadcastReceiver, filter); // register our observer if (mObserver != null) { mObserver.observe(); } } public void updateWidget() { PowerButton.updateAllButtons(); } public void setupSettingsObserver(Handler handler) { if (mObserver == null) { mObserver = new WidgetSettingsObserver(handler); } } public void setGlobalButtonOnClickListener(View.OnClickListener listener) { PowerButton.setGlobalOnClickListener(listener); } public void setGlobalButtonOnLongClickListener(View.OnLongClickListener listener) { PowerButton.setGlobalOnLongClickListener(listener); } private void setupBroadcastReceiver() { if (mBroadcastReceiver == null) { mBroadcastReceiver = new WidgetBroadcastReceiver(); } } private void updateButtonLayoutWidth() { // use our context to set a valid button width BUTTON_LAYOUT_PARAMS.width = mContext.getResources().getDisplayMetrics().widthPixels / LAYOUT_SCROLL_BUTTON_THRESHOLD; } private void updateVisibility() { // now check if we need to display the widget still boolean displayPowerWidget = Settings.System.getInt(mContext.getContentResolver(), Settings.System.EXPANDED_VIEW_WIDGET, 1) == 1; if (!displayPowerWidget) { setVisibility(View.GONE); } else { setVisibility(View.VISIBLE); } } private void updateScrollbar() { if (mScrollView == null) return; boolean hideScrollBar = Settings.System.getInt(mContext.getContentResolver(), Settings.System.EXPANDED_HIDE_SCROLLBAR, 0) == 1; mScrollView.setHorizontalScrollBarEnabled(!hideScrollBar); } // our own broadcast receiver :D private class WidgetBroadcastReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) { updateButtonLayoutWidth(); setupWidget(); } else { // handle the intent through our power buttons PowerButton.handleOnReceive(context, intent); } // update our widget updateWidget(); } }; // our own settings observer :D private class WidgetSettingsObserver extends ContentObserver { public WidgetSettingsObserver(Handler handler) { super(handler); } public void observe() { ContentResolver resolver = mContext.getContentResolver(); // watch for display widget resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.EXPANDED_VIEW_WIDGET), false, this); // watch for scrollbar hiding resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.EXPANDED_HIDE_SCROLLBAR), false, this); // watch for haptic feedback resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.EXPANDED_HAPTIC_FEEDBACK), false, this); // watch for changes in buttons resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.WIDGET_BUTTONS), false, this); // watch for changes in color resolver.registerContentObserver( Settings.System.getUriFor(Settings.System.EXPANDED_VIEW_WIDGET_COLOR), false, this); // watch for power-button specifc stuff that has been loaded for (Uri uri : PowerButton.getAllObservedUris()) { resolver.registerContentObserver(uri, false, this); } } public void unobserve() { ContentResolver resolver = mContext.getContentResolver(); resolver.unregisterContentObserver(this); } public void onChangeUri(Uri uri, boolean selfChange) { ContentResolver resolver = mContext.getContentResolver(); Resources res = mContext.getResources(); // first check if our widget buttons have changed if (uri.equals(Settings.System.getUriFor(Settings.System.WIDGET_BUTTONS))) { setupWidget(); // now check if we change visibility } else if (uri.equals(Settings.System.getUriFor(Settings.System.EXPANDED_VIEW_WIDGET))) { updateVisibility(); // now check for scrollbar hiding } else if (uri.equals(Settings.System .getUriFor(Settings.System.EXPANDED_HIDE_SCROLLBAR))) { updateScrollbar(); } // do whatever the individual buttons must PowerButton.handleOnChangeUri(uri); // something happened so update the widget updateWidget(); } } }