Java tutorial
/* * Copyright 2014 Inderjit Gill * * 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 io.indy.seni.ui; import android.annotation.TargetApi; import android.app.ActivityOptions; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.GridView; import android.widget.Toast; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; import io.indy.seni.AppConfig; import io.indy.seni.BuildConfig; import io.indy.seni.R; import io.indy.seni.SeniApp; import io.indy.seni.adapter.EvolveAdapter; import io.indy.seni.lang.AstHolder; import io.indy.seni.lang.Genotype; import io.indy.seni.lang.Node; import io.indy.seni.model.EvolveContainer; import io.indy.seni.util.ImageCache; import io.indy.seni.util.ImageGenerator; public class EvolveGridFragment extends Fragment implements AdapterView.OnItemClickListener { private static final String TAG = "EvolveGridFragment"; private static final boolean D = true; static void ifd(final String message) { if (AppConfig.DEBUG && D) Log.d(TAG, message); } public static final String GENESIS_SCRIPT = "GENESIS_SCRIPT"; public static final String EVOLVE_CONTAINER = "EVOLVE_CONTAINER"; private String mGenesisScript; private int mImageThumbSize; private int mImageThumbSpacing; private EvolveAdapter mAdapter; private EvolveContainer mEvolveContainer; private ImageGenerator mImageGenerator; private GridView mGridView; /** * Empty constructor as per the Fragment documentation */ public EvolveGridFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); ifd("onCreate"); mImageThumbSize = getResources().getDimensionPixelSize(R.dimen.pheno_thumbnail_size); mImageThumbSpacing = getResources().getDimensionPixelSize(R.dimen.pheno_thumbnail_spacing); ImageCache.ImageCacheParams cacheParams = new ImageCache.ImageCacheParams(); cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 25% of app memory // The ImageGenerator takes care of loading images into our ImageView children asynchronously mImageGenerator = new ImageGenerator(getActivity(), mImageThumbSize); mImageGenerator.setLoadingImage(R.drawable.empty_genotype); mImageGenerator.addImageCache(getActivity().getFragmentManager(), cacheParams); if (getArguments().containsKey(GENESIS_SCRIPT)) { // first time call mEvolveContainer = new EvolveContainer(); mGenesisScript = getArguments().getString(EvolveGridFragment.GENESIS_SCRIPT); mEvolveContainer.setScript(mGenesisScript); mEvolveContainer.mutatePopulation(); } else { // if (getArguments().containsKey(EVOLVE_CONTAINER)) { String json = getArguments().getString(EVOLVE_CONTAINER); mEvolveContainer = EvolveContainer.fromJsonString(json); } else { ifd("expected an EVOLVE_CONTAINER value"); } // create 50 genotypes from the latest breeding population mEvolveContainer.breedPopulation(); } mAdapter = new EvolveAdapter(getActivity(), mImageGenerator, mEvolveContainer); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View v = inflater.inflate(R.layout.fragment_evolve, container, false); mGridView = (GridView) v.findViewById(R.id.gridView); mGridView.setAdapter(mAdapter); mGridView.setOnItemClickListener(this); mGridView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView absListView, int scrollState) { // Pause fetcher to ensure smoother scrolling when flinging if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { } else { mImageGenerator.setPauseWork(false); } } @Override public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } }); mGridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL); mGridView.setMultiChoiceModeListener(mMultiChoiceModeListener); // This listener is used to get the final width of the GridView and then calculate the // number of columns and the width of each column. The width of each column is variable // as the GridView has stretchMode=columnWidth. The column width is used to set the height // of each view so we get nice square thumbnails. mGridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (mAdapter.getNumColumns() == 0) { final int numColumns = (int) Math .floor(mGridView.getWidth() / (mImageThumbSize + mImageThumbSpacing)); if (numColumns > 0) { final int columnWidth = (mGridView.getWidth() / numColumns) - mImageThumbSpacing; mAdapter.setNumColumns(numColumns); mAdapter.setItemHeight(columnWidth); if (BuildConfig.DEBUG) { Log.d(TAG, "onCreateView - numColumns set to " + numColumns); } if (AppConfig.hasJellyBean()) { mGridView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } else { mGridView.getViewTreeObserver().removeGlobalOnLayoutListener(this); } } } } }); return v; } @Override public void onResume() { super.onResume(); mImageGenerator.setExitTasksEarly(false); mAdapter.notifyDataSetChanged(); } @Override public void onPause() { super.onPause(); mImageGenerator.setPauseWork(false); mImageGenerator.setExitTasksEarly(true); } @Override public void onDestroy() { super.onDestroy(); } // @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { Genotype genotype = mEvolveContainer.getGenotype((int) id); AstHolder astHolder = genotype.getAstHolder(); try { String script = astHolder.scribe(genotype); Intent intent = new Intent(getActivity(), RenderActivity.class); intent.putExtra(GENESIS_SCRIPT, script); // startActivity(intent); if (AppConfig.hasJellyBean()) { // makeThumbnailScaleUpAnimation() looks kind of ugly here as the loading spinner may // show plus the thumbnail image in GridView is cropped. so using // makeScaleUpAnimation() instead. ActivityOptions options = ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight()); getActivity().startActivity(intent, options.toBundle()); } else { startActivity(intent); } } catch (Node.ScribeException e) { e.printStackTrace(); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.main_menu, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.clear_cache: mImageGenerator.clearCache(); Toast.makeText(getActivity(), R.string.clear_cache_complete_toast, Toast.LENGTH_SHORT).show(); return true; } return super.onOptionsItemSelected(item); } /** * Manage the multiple phenotype selections */ private AbsListView.MultiChoiceModeListener mMultiChoiceModeListener = new AbsListView.MultiChoiceModeListener() { @Override public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { // Here you can do something when items are selected/de-selected, // such as update the title in the CAB ifd("onItemCheckedStateChanged"); int count = mGridView.getCheckedItemCount(); if (count == 1) { mode.setTitle("1 phenotype selected"); } else { mode.setTitle("" + count + " phenotypes selected"); } } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { // Respond to clicks on the actions in the CAB switch (item.getItemId()) { case R.id.menu_breed: // launch a new EvolveGridFragment with the chosen genotypes List<Genotype> genotypes = new ArrayList<>(); long[] ids = mGridView.getCheckedItemIds(); int pos, i; for (i = 0; i < ids.length; i++) { pos = (int) ids[i]; Genotype genotype = mEvolveContainer.getGenotype(pos); genotypes.add(genotype); } Bundle arguments = new Bundle(); mEvolveContainer.newGeneration(genotypes); arguments.putString(EVOLVE_CONTAINER, mEvolveContainer.toJsonString()); mode.finish(); // Action picked, so close the CAB EvolveGridFragment fragment = new EvolveGridFragment(); fragment.setArguments(arguments); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.evolve_container, fragment); ft.commit(); return true; default: return false; } } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { ifd("onCreateActionMode"); // Inflate the menu for the CAB MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.context_evolve, menu); mode.setTitle("Choose the best"); mode.setSubtitle("generation " + mAdapter.getGenerationCount()); return true; } @Override public void onDestroyActionMode(ActionMode mode) { // Here you can make any necessary updates to the activity when // the CAB is removed. By default, selected items are deselected/unchecked. ifd("onDestroyActionMode"); } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { // Here you can perform updates to the CAB due to // an invalidate() request ifd("onPrepareActionMode"); return false; } }; }