Android Open Source - virtual-stat Single Stat Control Fan






From Project

Back to project page virtual-stat.

License

The source code is released under:

Copyright (c) 2014, Delta Controls Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are...

If you think the Android project virtual-stat listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/* Copyright (c) 2014, Delta Controls Inc.
All rights reserved./*  w w  w  .  j a  v  a 2s  .c om*/

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this 
list of conditions and the following disclaimer in the documentation and/or other 
materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may 
be used to endorse or promote products derived from this software without specific 
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
*/
/**
 * SingleStatControlFan.java
 */
package com.deltacontrols.virtualstat.fragment;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;

import com.deltacontrols.virtualstat.App;
import com.deltacontrols.virtualstat.R;
import com.deltacontrols.virtualstat.UIFactory;
import com.deltacontrols.virtualstat.VirtualStat;
import com.deltacontrols.virtualstat.VirtualStat.ExposeVirtualStat;
import com.deltacontrols.virtualstat.controls.SeekBarWithValue;
import com.deltacontrols.virtualstat.controls.StackedStates;
import com.deltacontrols.virtualstat.points.FanPoint;
import com.deltacontrols.virtualstat.points.VirtualStatPoint;
import com.deltacontrols.virtualstat.points.VirtualStatPoint.SetBy;

/**
 * Fragment containing the fan point; uses virtualStatDelegate (from VirtualStat.UseVirtualStat.getStatDelegate) to interact with the current VirtalStat data points.
 */
public class SingleStatControlFan extends Fragment implements VirtualStat.UseVirtualStat {

    // Common support
    private View activeInput; // Reference to the active input (SeekBarWithValue or StackedStates)
    private CheckBox autoManualCheckbox;

    // VirtualStat (model) Interface delegates
    private VirtualStat virtualStatDelegate = null;
    private boolean isReady;
    private boolean suppressSounds = false;
    private VirtualStatPoint.Type mPointType;
    private final String autoTextForSeek = "";

    // Input Listeners
    private SeekBarWithValue.ChangeListener valueSliderListener = new SeekBarWithValue.ChangeListener() {
        @Override
        public void onValueChange(int value) {
            // Analog value
            String newValue = Integer.toString(value);

            // Actual and display value may be different, only update if we need to.
            if (convertDelegateToDisplay() != value) {
                virtualStatDelegate.setValue(virtualStatDelegate.Fan, newValue);
                playClick();
            }
        }
    };

    private StackedStates.StatesGroupListener statesGroupListener = new StackedStates.StatesGroupListener() {
        @Override
        public void onStateSelected(String result) {
            // If non-auto (null) state selected, then we want to toggle the auto/manual checkbox if has not
            // already been toggled.
            if (result == null) {
                if (autoManualCheckbox.isChecked()) {
                    autoManualCheckbox.setChecked(false);
                }
                result = "1"; // MV states indexed on 1, so by having no states selected we are in auto mode, which corresponds to a value of 1.
            }
            else {
                if (!autoManualCheckbox.isChecked()) {
                    autoManualCheckbox.setChecked(true);
                }
            }

            virtualStatDelegate.setValue(virtualStatDelegate.Fan, result);
            playClick();
        }
    };

    // --------------------------------------------------------------------------------
    // Lifecycle
    // --------------------------------------------------------------------------------
    public SingleStatControlFan() {
        // Required empty public constructor
    }

    /**
     * Creates the view for the fan fragment; if the point is not valid, then show an error view.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        final View view = inflater.inflate(R.layout.fragment_single_stat_control_fan, container, false);
        View resultView = null;

        suppressSounds = true; // Suppress sound during setup to avoid undesired "clicks"

        // Set the stat delegate
        getStatDelegate();
        mPointType = virtualStatDelegate.Fan.getType();

        // Check for errors

        if (!virtualStatDelegate.Fan.isValid()) {
            final View errorView = inflater.inflate(R.layout.fragment_single_stat_error, container, false);
            isReady = false;
            resultView = errorView;
        }
        else {
            // Setup outlets
            RelativeLayout fanInputLayout = (RelativeLayout) view.findViewById(R.id.fanInputLayout);
            createInputControls(fanInputLayout);

            // Setup auto manual
            autoManualCheckbox = (CheckBox) view.findViewById(R.id.autoManualCheckbox);
            autoManualCheckbox.setChecked(virtualStatDelegate.Fan.getManualState()); // Set manual state before changing
            autoManualCheckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (activeInput == null) { 
                        return;
                    }

                    // If using an MV, State1 = auto. When switching to manual default to State2.
                    if (mPointType == VirtualStatPoint.Type.MULTISTATE) {
                        StackedStates states = (StackedStates) activeInput;
                        if (!isChecked) {
                            states.clearCheck();
                        }
                        else if (!states.hasSelection()) {
                            // If no other state has been selected (ie. the user toggled the a/m checkbox) then
                            // set a default state for them.
                            states.selectState("2");
                        }
                        // No click, state change will apply a click for us
                    }

                    else {
                        SeekBarWithValue bar = ((SeekBarWithValue) activeInput);
                        if (isChecked) {
                            bar.setValue(convertDelegateToDisplay());
                        }
                        else {
                            bar.setError(autoTextForSeek);
                        }
                        // Play sound, since not changing the value of the slider, it will not provide the click.
                        playClick();
                    }

                    // Note, we are not going through VirtualStat.setValue (because Fan does trickery for setting the manual state),
                    // We need to force a put to the server.
                    virtualStatDelegate.Fan.setManualState(isChecked, SetBy.USER);
                    virtualStatDelegate.forcePut();
                }
            });

            isReady = true;
            resultView = view;
        }

        // Set custom font
        UIFactory.setCustomFont(getActivity(), resultView);
        return resultView;
    }

    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }

    public void onResume() {
        // Suppress sounds during resume to avoid undesired clicks
        suppressSounds = true;
        super.onResume();
        updateWithDelegate();
        suppressSounds = false;
    }

    // --------------------------------------------------------------------------------
    // Methods
    // --------------------------------------------------------------------------------
    /**
     * Dynamically generate the fan input based on {@link VirtualStatPoint.Type}. 
     * Analog value -> SeekBarWithValue control 
     * Multistate value -> StackedStates control
     */
    private void createInputControls(RelativeLayout parentLayout) {
        Context ctx = getActivity().getApplicationContext();
        float largeTextSize = UIFactory.getDPDimen(ctx, R.dimen.text_size_large);

        // Containing layout
        RelativeLayout inputLayout = new RelativeLayout(ctx);
        RelativeLayout.LayoutParams inputLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        inputLayoutParams.setMargins(0, 0, 0, 10);
        inputLayout.setLayoutParams(inputLayoutParams);

        // Create input based on type of reference
        if (mPointType == VirtualStatPoint.Type.ANALOG) {
            activeInput = new SeekBarWithValue(ctx, valueSliderListener, largeTextSize);
            activeInput.setEnabled(false); // By default, set disabled (auto)
        }
        else if (mPointType == VirtualStatPoint.Type.MULTISTATE) {
            activeInput = new StackedStates(ctx, FanPoint.FanValueByState, largeTextSize, statesGroupListener);
        }
        else {
            // Should not get here, if unsupported we should see an error page.
            return;
        }

        // Add to parent layout
        inputLayout.addView(activeInput);
        parentLayout.addView(inputLayout);
    }

    /**
     * Converts the fan delegate value to be displayed in the fragment; we display integers, but the true value may be any double.
     * 
     * @return The value rounded up to the nearest integer
     */
    private int convertDelegateToDisplay() {
        int value;

        try {
            value = (int) Math.round(Double.parseDouble(virtualStatDelegate.Fan.getValue()));
        } catch (Exception e) {
            value = 0;
        }

        return value;
    }

    private void playClick() {
        if (!suppressSounds) {
            App.getAudioManager().playSoundEffect(SoundEffectConstants.CLICK);
        }
    }

    // --------------------------------------------------------------------------------
    // VirtualStat.UseVirtualStat interface
    // --------------------------------------------------------------------------------
    /**
     * Get the VirtualStat object from the parent activity; use ExposeVirtualStat interface to ensure that the parent correctly exposes the object.
     */
    @Override
    public void getStatDelegate() {
        Activity activity = getActivity();

        try {
            virtualStatDelegate = ((ExposeVirtualStat) activity).getCurrentStat();
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement ExposeVirtualStat");
        }
    }

    /**
     * Update the fragment with the desired values from the VirtualStat delegate; allows the parent activity to 'push' updates to each fragment.
     */
    @Override
    public void updateWithDelegate() {
        if (!isReady || (virtualStatDelegate == null)) {
            return;
        }

        // When updating with delegate, always use virtualStatDelegate.Fan as the reference may have changed since last call.
        FanPoint point = virtualStatDelegate.Fan;
        boolean isError = point.getValue().startsWith("QERR");
        boolean isInManual = point.getManualState();

        // Update UI according to object type
        if (mPointType == VirtualStatPoint.Type.ANALOG) {
            if (isError) {
                ((SeekBarWithValue) activeInput).setError();
            } else if (isInManual) {
                // Setting the progress should trigger the value text to update.
                ((SeekBarWithValue) activeInput).setValue(convertDelegateToDisplay());
            }
            else {
                ((SeekBarWithValue) activeInput).setError(autoTextForSeek);
            }
        }
        else if (mPointType == VirtualStatPoint.Type.MULTISTATE) {
            // Note: Cannot use setEnabled/Disabled here since it conflicts with using enabled/disabled to show auto/manual.
            // Note: Being inError will also disable the entire fragment, so not being able to disable the input directly may not be a huge issue.
            if (isError) {
                // activeInput.setEnabled(false);
            }
            else {
                ((StackedStates) activeInput).selectState(point.getValue());
            }
        }
        else {
            return;
        }

        // Update auto/manual checkbox
        autoManualCheckbox.setChecked(point.getManualState());

        // Disable entire fragment
        if (isError) {
            UIFactory.disableFragment(getActivity(), this);
        }
        else {
            UIFactory.enableFragment(getActivity(), this);
        }
    }
}




Java Source Code List

com.deltacontrols.virtualstat.App.java
com.deltacontrols.virtualstat.LoginInfo.java
com.deltacontrols.virtualstat.StatListItemAdapter.java
com.deltacontrols.virtualstat.StatListItem.java
com.deltacontrols.virtualstat.StatListView.java
com.deltacontrols.virtualstat.UIFactory.java
com.deltacontrols.virtualstat.VirtualStat.java
com.deltacontrols.virtualstat.activity.LoginActivity.java
com.deltacontrols.virtualstat.activity.NFCFetchActivity.java
com.deltacontrols.virtualstat.activity.SettingsActivity.java
com.deltacontrols.virtualstat.activity.SingleStatControlActivity.java
com.deltacontrols.virtualstat.activity.SummaryActivity.java
com.deltacontrols.virtualstat.controls.AlertWindow.java
com.deltacontrols.virtualstat.controls.OnOffToggle.java
com.deltacontrols.virtualstat.controls.RotatingImageView.java
com.deltacontrols.virtualstat.controls.SeekBarWithValue.java
com.deltacontrols.virtualstat.controls.SlidingWindow.java
com.deltacontrols.virtualstat.controls.StackedStates.java
com.deltacontrols.virtualstat.controls.ToggleBar.java
com.deltacontrols.virtualstat.fragment.SingleStatControlBlinds.java
com.deltacontrols.virtualstat.fragment.SingleStatControlFan.java
com.deltacontrols.virtualstat.fragment.SingleStatControlLights.java
com.deltacontrols.virtualstat.fragment.SingleStatControlTabs.java
com.deltacontrols.virtualstat.fragment.SingleStatControlTemperature.java
com.deltacontrols.virtualstat.fragment.SingleStatSummaryFragment.java
com.deltacontrols.virtualstat.fragment.StatListFragment.java
com.deltacontrols.virtualstat.nfc.NFCHelper.java
com.deltacontrols.virtualstat.points.BlindsPoint.java
com.deltacontrols.virtualstat.points.FanOverridePoint.java
com.deltacontrols.virtualstat.points.FanPoint.java
com.deltacontrols.virtualstat.points.LightsPoint.java
com.deltacontrols.virtualstat.points.TempPoint.java
com.deltacontrols.virtualstat.points.VirtualStatPoint.java