com.ultramegatech.ey.PeriodicTableActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.ultramegatech.ey.PeriodicTableActivity.java

Source

/*
 * The MIT License (MIT)
 * Copyright  2012 Steve Guidetti
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the Software?), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED AS IS?, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.ultramegatech.ey;

import android.app.ActionBar;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Spinner;
import android.widget.ZoomControls;

import com.ultramegatech.ey.provider.Element;
import com.ultramegatech.ey.provider.Elements;
import com.ultramegatech.ey.util.CommonMenuHandler;
import com.ultramegatech.ey.util.PreferenceUtils;
import com.ultramegatech.ey.util.UnitUtils;
import com.ultramegatech.ey.widget.BlockSubtextValueListAdapter;
import com.ultramegatech.ey.widget.PeriodicTableBlock;
import com.ultramegatech.ey.widget.PeriodicTableView;

import java.text.DecimalFormat;
import java.util.ArrayList;

/**
 * This Activity displays the PeriodicTableView. Clicking on an element block will launch an
 * ElementDetailsActivity for the selected element.
 *
 * @author Steve Guidetti
 */
public class PeriodicTableActivity extends FragmentActivity implements OnSharedPreferenceChangeListener {
    /**
     * Delay in milliseconds before entering or re-entering immersive full screen mode
     */
    private static final long IMMERSIVE_MODE_DELAY = 4000;

    /**
     * Delay in milliseconds before hiding the zoom controls
     */
    private static final long ZOOM_BUTTON_DELAY = 5000;

    /**
     * Handler for posting delayed callbacks
     */
    @NonNull
    private final Handler mHandler = new Handler();

    /**
     * Callback to enter immersive full screen mode
     */
    private Runnable mImmersiveModeCallback;

    /**
     * The main View
     */
    private PeriodicTableView mPeriodicTableView;

    /**
     * The controls for the Periodic Table
     */
    private View mControlBar;

    /**
     * The zoom controls
     */
    private ZoomControls mZoomControls;

    /**
     * The Spinner to choose the block subtext value
     */
    private Spinner mSpinnerSubtextValue;

    /**
     * The Spinner to choose how to color the blocks
     */
    private Spinner mSpinnerBlockColors;

    /**
     * Format for decimal values
     */
    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat();

    static {
        DECIMAL_FORMAT.setMaximumFractionDigits(4);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
        final boolean darkTheme = PreferenceUtils.getPrefDarkTheme();
        setTheme(darkTheme ? R.style.DarkTheme_TableView : R.style.LightTheme_TableView);

        super.onCreate(savedInstanceState);

        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        prefs.registerOnSharedPreferenceChangeListener(this);

        setupImmersiveMode();
        setContentView(R.layout.activity_periodic_table);

        mPeriodicTableView = (PeriodicTableView) findViewById(R.id.ptview);
        mPeriodicTableView.setPeriodicTableListener(new PeriodicTableView.PeriodicTableListener() {
            @Override
            public void onItemClick(@NonNull PeriodicTableBlock item) {
                ElementDetailsFragment.showDialog(getSupportFragmentManager(), item.element.number);
            }

            @Override
            public void onZoomEnd(@NonNull PeriodicTableView periodicTableView) {
                mZoomControls.setIsZoomInEnabled(periodicTableView.canZoomIn());
                mZoomControls.setIsZoomOutEnabled(periodicTableView.canZoomOut());
            }
        });

        mControlBar = findViewById(R.id.controls);
        if (PreferenceUtils.getPrefShowControls()) {
            mControlBar.setVisibility(View.VISIBLE);
        }

        setupZoomControls();
        setupSubtextValueSpinner();
        setupBlockColorSpinner();

        loadElements();
    }

    /**
     * Set up the controls for zooming in and out.
     */
    private void setupZoomControls() {
        final Runnable hideZoom = new Runnable() {
            @Override
            public void run() {
                mZoomControls.hide();
                mZoomControls.setVisibility(View.INVISIBLE);
            }
        };

        mZoomControls = (ZoomControls) findViewById(R.id.zoom);
        mZoomControls.setVisibility(View.INVISIBLE);
        mZoomControls.setIsZoomOutEnabled(false);
        mZoomControls.setOnZoomInClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mHandler.removeCallbacks(hideZoom);
                mPeriodicTableView.zoomIn();
                mZoomControls.setIsZoomOutEnabled(true);
                mHandler.postDelayed(hideZoom, ZOOM_BUTTON_DELAY);
            }
        });
        mZoomControls.setOnZoomOutClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mHandler.removeCallbacks(hideZoom);
                mPeriodicTableView.zoomOut();
                mZoomControls.setIsZoomInEnabled(true);
                mHandler.postDelayed(hideZoom, ZOOM_BUTTON_DELAY);
            }
        });

        findViewById(R.id.zoomButton).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mHandler.removeCallbacks(hideZoom);
                if (mZoomControls.getVisibility() == View.INVISIBLE) {
                    mZoomControls.show();
                    mZoomControls.setVisibility(View.VISIBLE);
                }
                mHandler.postDelayed(hideZoom, ZOOM_BUTTON_DELAY);
            }
        });
    }

    /**
     * Set up the Spinner for choosing the value to display as the subtext of each block.
     */
    private void setupSubtextValueSpinner() {
        mSpinnerSubtextValue = (Spinner) findViewById(R.id.subtextValue);
        final BlockSubtextValueListAdapter adapter = new BlockSubtextValueListAdapter(this);
        mSpinnerSubtextValue.setAdapter(adapter);
        mSpinnerSubtextValue.setSelection(adapter.getItemIndex(PreferenceUtils.getPrefSubtextValue()));
        mSpinnerSubtextValue.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                PreferenceUtils.setPrefSubtextValue(adapter.getItem(i));
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
            }
        });
    }

    /**
     * Set up the Spinner for choosing how to color the blocks.
     */
    private void setupBlockColorSpinner() {
        mSpinnerBlockColors = (Spinner) findViewById(R.id.blockColors);
        if (mSpinnerBlockColors == null) {
            return;
        }

        final String pref = PreferenceUtils.getPrefElementColors();
        mSpinnerBlockColors.setSelection(pref.equals(PreferenceUtils.COLOR_CAT) ? 0 : 1);
        mSpinnerBlockColors.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                PreferenceUtils
                        .setPrefElementColors(i == 0 ? PreferenceUtils.COLOR_CAT : PreferenceUtils.COLOR_BLOCK);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        prefs.unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            mHandler.removeCallbacks(mImmersiveModeCallback);
            hideSystemUi();
        }
    }

    /**
     * Set up immersive full screen mode for supported devices.
     */
    private void setupImmersiveMode() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            mImmersiveModeCallback = new Runnable() {
                @Override
                public void run() {
                    hideSystemUi();
                }
            };

            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
                    | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            getWindow().getDecorView()
                    .setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
                        @Override
                        public void onSystemUiVisibilityChange(int visibility) {
                            mHandler.removeCallbacks(mImmersiveModeCallback);
                            if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
                                mHandler.postDelayed(mImmersiveModeCallback, IMMERSIVE_MODE_DELAY);
                            }
                        }
                    });

            final ActionBar actionBar = getActionBar();
            if (actionBar != null) {
                actionBar.addOnMenuVisibilityListener(new ActionBar.OnMenuVisibilityListener() {
                    @Override
                    public void onMenuVisibilityChanged(boolean isVisible) {
                        if (isVisible) {
                            mHandler.removeCallbacks(mImmersiveModeCallback);
                        } else {
                            mHandler.postDelayed(mImmersiveModeCallback, IMMERSIVE_MODE_DELAY);
                        }
                    }
                });
            }
        }
    }

    /**
     * Enable immersive full screen mode.
     */
    private void hideSystemUi() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE);

            findViewById(R.id.touchFrame).setVisibility(View.VISIBLE);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        final MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.periodic_table, menu);
        inflater.inflate(R.menu.common, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        final int id = item.getItemId();
        switch (id) {
        case R.id.menu_list:
            startActivity(new Intent(this, ElementListActivity.class));
            return true;
        }
        return CommonMenuHandler.handleSelect(this, id) || super.onOptionsItemSelected(item);
    }

    /**
     * Get the block subtext for an element block.
     *
     * @param element The Element
     * @return The subtext for the element
     */
    @NonNull
    private String getSubtext(@NonNull Element element) {
        switch (PreferenceUtils.getPrefSubtextValue()) {
        case PreferenceUtils.SUBTEXT_WEIGHT:
            if (element.unstable) {
                return "[" + (int) element.weight + "]";
            } else {
                return DECIMAL_FORMAT.format(element.weight);
            }
        case PreferenceUtils.SUBTEXT_MELT:
        case PreferenceUtils.SUBTEXT_BOIL:
            Double value;
            if (PreferenceUtils.SUBTEXT_MELT.equals(PreferenceUtils.getPrefSubtextValue())) {
                value = element.melt;
            } else {
                value = element.boil;
            }
            if (value != null) {
                switch (PreferenceUtils.getPrefTempUnit()) {
                case PreferenceUtils.TEMP_C:
                    value = UnitUtils.KtoC(value);
                    break;
                case PreferenceUtils.TEMP_F:
                    value = UnitUtils.KtoF(value);
                    break;
                }
                return DECIMAL_FORMAT.format(value);
            }
            break;
        case PreferenceUtils.SUBTEXT_DENSITY:
            if (element.density != null) {
                if (element.density < 0.0001) {
                    return "<0.0001";
                }
                return DECIMAL_FORMAT.format(element.density);
            }
            break;
        case PreferenceUtils.SUBTEXT_ABUNDANCE:
            if (element.abundance != null) {
                if (element.abundance < 0.001) {
                    return "<0.001";
                }
                return DECIMAL_FORMAT.format(element.abundance);
            }
            break;
        case PreferenceUtils.SUBTEXT_HEAT:
            if (element.heat != null) {
                return String.valueOf(element.heat);
            }
            break;
        case PreferenceUtils.SUBTEXT_NEGATIVITY:
            if (element.negativity != null) {
                return String.valueOf(element.negativity);
            }
            break;
        }
        return "?";
    }

    /**
     * Load the Elements into PeriodicTableBlock.
     */
    private void loadElements() {
        final ArrayList<PeriodicTableBlock> periodicTableBlocks = new ArrayList<>();
        PeriodicTableBlock block;
        for (Element element : Elements.getElements()) {
            block = new PeriodicTableBlock(element);
            block.subtext = getSubtext(element);

            periodicTableBlocks.add(block);
        }

        mPeriodicTableView.setBlocks(periodicTableBlocks);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        switch (key) {
        case PreferenceUtils.KEY_SHOW_CONTROLS:
            mControlBar.setVisibility(PreferenceUtils.getPrefShowControls() ? View.VISIBLE : View.GONE);
            break;
        case PreferenceUtils.KEY_ELEMENT_COLORS:
            loadElements();
            if (PreferenceUtils.COLOR_BLOCK.equals(PreferenceUtils.getPrefElementColors())) {
                mSpinnerBlockColors.setSelection(1);
            } else {
                mSpinnerBlockColors.setSelection(0);
            }
            mPeriodicTableView.invalidateLegend();
            break;
        case PreferenceUtils.KEY_SUBTEXT_VALUE:
            loadElements();
            mSpinnerSubtextValue.setSelection(((BlockSubtextValueListAdapter) mSpinnerSubtextValue.getAdapter())
                    .getItemIndex(PreferenceUtils.getPrefSubtextValue()));
        }
    }
}