package eu.hgross.blaubot.android.views; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; import android.util.AttributeSet; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import eu.hgross.blaubot.android.R; import eu.hgross.blaubot.core.Blaubot; import eu.hgross.blaubot.core.IBlaubotConnection; import eu.hgross.blaubot.core.IBlaubotDevice; import eu.hgross.blaubot.core.acceptor.IBlaubotConnectionManagerListener; import eu.hgross.blaubot.core.statemachine.IBlaubotConnectionStateMachineListener; import eu.hgross.blaubot.core.statemachine.states.IBlaubotState; import eu.hgross.blaubot.ui.IBlaubotDebugView; import eu.hgross.blaubot.util.KingdomCensusLifecycleListener; import eu.hgross.blaubot.util.Log; /** * Android view to display informations about the StateMachine's state. * * Add this view to a blaubot instance like this: stateView.registerBlaubotInstance(blaubot); * * @author Henning Gross {@literal (mail.to@henning-gross.de)} * */ public class StateView extends FrameLayout implements IBlaubotDebugView { private TextView mCurrentStateTextView; private TextView mConnectedDevicesCountTextView; private TextView mKingdomDevicesCountTextView; private ImageView mStateImageView; private Button mStartStopButton; private Handler mUiHandler; private Blaubot mBlaubot; private boolean mShowOwnUniqueId = false; private TextView mOwnUniqueIdTextView; private KingdomCensusLifecycleListener mKingdomCensusLifecycleListener; public StateView(Context context, AttributeSet attrs) { super(context, attrs); initView(context, attrs); } public StateView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context, attrs); } private void initView(Context context, AttributeSet attrs) { View view = inflate(getContext(), R.layout.blaubot_status_view, null); if (attrs != null) { TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.StateView, 0, 0); try { mShowOwnUniqueId = a.getBoolean(R.styleable.StateView_showOwnUniqueId, mShowOwnUniqueId); } finally { a.recycle(); } } addView(view); mUiHandler = new Handler(Looper.getMainLooper()); mCurrentStateTextView = (TextView) findViewById(R.id.blaubot_status_view_current_state); mConnectedDevicesCountTextView = (TextView) findViewById(R.id.blaubot_status_view_connected_devices_count); mOwnUniqueIdTextView = (TextView) findViewById(R.id.blaubot_status_view_ownUnqiueId); mOwnUniqueIdTextView.setVisibility(mShowOwnUniqueId ? VISIBLE : GONE); mKingdomDevicesCountTextView = (TextView) findViewById(R.id.blaubot_status_view_kigndom_devices_count); mStateImageView = (ImageView) findViewById(R.id.blaubot_status_view_state_image); mStartStopButton = (Button) findViewById(R.id.blaubot_status_view_start_stop_button); mStartStopButton.setOnClickListener(new OnClickListener() { private String LOG_TAG = "StateView.mStartStopButton.onClickListener"; @Override public synchronized void onClick(View v) { if(mBlaubot == null) { if(Log.logWarningMessages()) { Log.w(LOG_TAG , "Blaubot not set - ignoring onClick."); } return; } mStartStopButton.setEnabled(false); if(mBlaubot.isStarted()) { mBlaubot.stopBlaubot(); } else { mBlaubot.startBlaubot(); } } }); } private final IBlaubotConnectionStateMachineListener mConnectionStateMachineListener = new IBlaubotConnectionStateMachineListener() { @Override public void onStateChanged(IBlaubotState oldState, IBlaubotState newState) { // not used } @Override public void onStateMachineStopped() { setButtonText(); } @Override public void onStateMachineStarted() { setButtonText(); } }; private IBlaubotConnectionManagerListener mConnectionManagerListener = new IBlaubotConnectionManagerListener() { private void updateUI() { final int num; if(mBlaubot != null) { num = mBlaubot.getConnectionManager().getAllConnections().size(); } else { num = 0; } mUiHandler.post(new Runnable() { @Override public void run() { String text = String.format(getResources().getString(R.string.blaubot_status_view_connected_devices_count), num); mConnectedDevicesCountTextView.setText(text); } }); } @Override public void onConnectionClosed(IBlaubotConnection connection) { updateUI(); } @Override public void onConnectionEstablished(IBlaubotConnection connection) { updateUI(); } }; private void setButtonText() { final boolean started = mBlaubot.isStarted(); mUiHandler.post(new Runnable() { @Override public void run() { // await either started or stopped final Resources resources = getContext().getResources(); final Drawable img; if(started) { img = resources.getDrawable(R.drawable.ic_media_stop); mStartStopButton.setText("Stop"); } else { img = resources.getDrawable(R.drawable.ic_media_play); mStartStopButton.setText("Start"); } mStartStopButton.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null); mStartStopButton.setEnabled(true); } }); } private volatile IBlaubotState mCurrentBlaubotState; private IBlaubotConnectionStateMachineListener mBlaubotConnectionListener = new IBlaubotConnectionStateMachineListener() { private void updateUI() { mUiHandler.post(new Runnable() { @Override public void run() { if(mCurrentBlaubotState != null) { mCurrentStateTextView.setText(mCurrentBlaubotState.toString()); mStateImageView.setImageDrawable(ViewUtils.getDrawableForBlaubotState(getContext(), mCurrentBlaubotState)); } else { mCurrentStateTextView.setText("no registered instance"); } } }); } @Override public void onStateChanged(IBlaubotState oldState, final IBlaubotState state) { mCurrentBlaubotState = state; updateUI(); } @Override public void onStateMachineStopped() { updateUI(); } @Override public void onStateMachineStarted() { updateUI(); } }; /** * Register this view with the given blaubot instance * * @param blaubot * the blaubot instance to connect with */ public void registerBlaubotInstance(Blaubot blaubot) { if (mBlaubot != null) { unregisterBlaubotInstance(); } this.mBlaubot = blaubot; this.mKingdomCensusLifecycleListener = new KingdomCensusLifecycleListener(mBlaubot.getOwnDevice()) { { updateUI(); } private void updateUI() { mUiHandler.post(new Runnable() { @Override public void run() { final long size = getDevices().size(); mKingdomDevicesCountTextView.setText("Kingdom size: " + size); } }); } @Override public void onConnected() { super.onConnected(); updateUI(); } @Override public void onDisconnected() { super.onDisconnected(); updateUI(); } @Override public void onDeviceJoined(IBlaubotDevice blaubotDevice) { super.onDeviceJoined(blaubotDevice); updateUI(); } @Override public void onDeviceLeft(IBlaubotDevice blaubotDevice) { super.onDeviceLeft(blaubotDevice); updateUI(); } }; this.mBlaubot.addLifecycleListener(mKingdomCensusLifecycleListener); this.mCurrentBlaubotState = blaubot.getConnectionStateMachine().getCurrentState(); this.mBlaubot.getConnectionStateMachine().addConnectionStateMachineListener(mBlaubotConnectionListener); this.mBlaubot.getConnectionManager().addConnectionListener(mConnectionManagerListener); this.mBlaubot.getConnectionStateMachine().addConnectionStateMachineListener(mConnectionStateMachineListener); this.mOwnUniqueIdTextView.setText(mBlaubot.getOwnDevice().getUniqueDeviceID()); // force some updates mConnectionManagerListener.onConnectionClosed(null); mBlaubotConnectionListener.onStateMachineStarted(); setButtonText(); } @Override public void unregisterBlaubotInstance() { if(mBlaubot != null) { this.mBlaubot.getConnectionStateMachine().removeConnectionStateMachineListener(mBlaubotConnectionListener); this.mBlaubot.getConnectionManager().removeConnectionListener(mConnectionManagerListener); this.mBlaubot.removeLifecycleListener(mKingdomCensusLifecycleListener); this.mBlaubot.getConnectionStateMachine().removeConnectionStateMachineListener(mConnectionStateMachineListener); this.mBlaubot = null; this.mKingdomCensusLifecycleListener = null; this.mCurrentBlaubotState = null; } // force some updates mConnectionManagerListener.onConnectionClosed(null); mBlaubotConnectionListener.onStateMachineStarted(); } }