Java tutorial
package com.jbirdvegas.mgerrit; /* * Copyright (C) 2013 Android Open Kang Project (AOKP) * Author: Jon Stanford (JBirdVegas), 2013 * * 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. */ import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Typeface; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.view.View; import android.widget.AdapterView; import android.widget.ImageButton; import android.widget.Spinner; import android.widget.ViewFlipper; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.Volley; import com.jbirdvegas.mgerrit.adapters.FileAdapter; import com.jbirdvegas.mgerrit.database.FileChanges; import com.jbirdvegas.mgerrit.helpers.Tools; import com.jbirdvegas.mgerrit.objects.FileInfo; import com.jbirdvegas.mgerrit.tasks.ZipImageRequest; import com.jbirdvegas.mgerrit.tasks.ZipRequest; import com.jbirdvegas.mgerrit.views.DiffTextView; import com.jbirdvegas.mgerrit.views.LoadingView; import com.jbirdvegas.mgerrit.views.StripedImageView; import java.io.UnsupportedEncodingException; import java.util.regex.Pattern; public class DiffViewer extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> { private String mLineSplit = System.getProperty("line.separator"); private DiffTextView mDiffTextView; private Spinner mSpinner; private FileAdapter mAdapter; private final AdapterView.OnItemSelectedListener mSelectedListener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { mFilePath = mAdapter.getPathAtPosition(position); String statusString = (String) view.getTag(R.id.status); FileInfo.Status status = FileInfo.Status.getValue(statusString); switchViews(DiffType.Loading); if (Tools.isImage(mFilePath)) { mLoadingView.loadingDiffImage(); makeImageRequest(mFilePath, status); } else { mLoadingView.loadingDiffText(); loadDiff(mFilePath); } int previousPosition = mAdapter.getPreviousPosition(position); mBtnPrevious.setVisibility(previousPosition >= 0 ? View.VISIBLE : View.INVISIBLE); int nextPosition = mAdapter.getNextPosition(position); mBtnNext.setVisibility(nextPosition >= 0 ? View.VISIBLE : View.INVISIBLE); } @Override public void onNothingSelected(AdapterView<?> parent) { // Not used } }; private ImageButton mBtnPrevious, mBtnNext; private ViewFlipper mSwitcher; private LoadingView mLoadingView; private String mFilePath; private int mChangeNumber; private int mPatchsetNumber; public static final String CHANGE_NUMBER_TAG = "changeNumber"; public static final String PATCH_SET_NUMBER_TAG = "patchSetNumber"; public static final String FILE_PATH_TAG = "file"; private static RequestQueue requestQueue; private ZipRequest request; private enum DiffType { Loading, Text, Image } @Override protected void onCreate(Bundle savedInstanceState) { this.setTheme(Prefs.getCurrentThemeID(this)); super.onCreate(savedInstanceState); setContentView(R.layout.diff_viewer); // Action bar Up affordance getActionBar().setDisplayHomeAsUpEnabled(true); Intent intent = getIntent(); mChangeNumber = getIntent().getIntExtra(CHANGE_NUMBER_TAG, 0); if (mChangeNumber == 0) { throw new IllegalArgumentException("Cannot load diff without a change number"); } setChangeTitle(mChangeNumber); mFilePath = intent.getStringExtra(FILE_PATH_TAG); mPatchsetNumber = intent.getIntExtra(PATCH_SET_NUMBER_TAG, 0); mLoadingView = (LoadingView) findViewById(R.id.diff_loading); mDiffTextView = (DiffTextView) findViewById(R.id.diff_view_diff); mSpinner = (Spinner) findViewById(R.id.diff_spinner); mSwitcher = (ViewFlipper) findViewById(R.id.diff_switcher); mBtnPrevious = (ImageButton) findViewById(R.id.diff_previous); mBtnNext = (ImageButton) findViewById(R.id.diff_next); mAdapter = new FileAdapter(this, null); mSpinner.setAdapter(mAdapter); mSpinner.setOnItemSelectedListener(mSelectedListener); mAdapter = new FileAdapter(this, null); mSpinner.setAdapter(mAdapter); mSpinner.setOnItemSelectedListener(mSelectedListener); getSupportLoaderManager().initLoader(0, null, this); } private void makeImageRequest(final String filePath, final FileInfo.Status fileStatus) { if (filePath == null) return; try { boolean wasDeleted = (fileStatus == FileInfo.Status.DELETED); ZipImageRequest imageRequest = new ZipImageRequest(this, mChangeNumber, mPatchsetNumber, filePath, wasDeleted, new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap bitmap) { if (bitmap == null) { mDiffTextView.setText(R.string.failed_to_decode_image); switchViews(DiffType.Text); return; } if (!filePath.equals(mFilePath)) { // Loaded the wrong image, don't display it return; } StripedImageView imageView = (StripedImageView) findViewById(R.id.diff_image); imageView.setVisibility(View.VISIBLE); imageView.setImageBitmap(bitmap); imageView.setStripe(fileStatus); switchViews(DiffType.Image); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { mDiffTextView.setText(R.string.failed_to_load_image); switchViews(DiffType.Text); } }); Volley.newRequestQueue(this).add(imageRequest); } catch (UnsupportedEncodingException ignored) { mDiffTextView.setText(R.string.failed_to_load_image); } } private void setTextView(String result) { Pattern pattern = Pattern.compile("\\Qdiff --git \\E"); String[] filesChanged = pattern.split(result); StringBuilder builder = new StringBuilder(0); for (String change : filesChanged) { String concat; int index = change.lastIndexOf(mFilePath); if (index < 0) continue; concat = change.substring(2, index).trim().split(" ", 2)[0]; if (concat.equals(mFilePath)) { change.replaceAll("\n", mLineSplit); builder.append(change); } } if (builder.length() == 0) { builder.append("Diff not found!"); } else { // reset text size to default mDiffTextView.setTextAppearance(this, android.R.style.TextAppearance_DeviceDefault_Small); mDiffTextView.setTypeface(Typeface.MONOSPACE); } // rebuild text; required to respect the \n mDiffTextView.setDiffText(builder.toString()); } private void loadDiff(String fileName) { mFilePath = fileName; /* The whole diff may be too large to cache in memory or expired * so we will launch another request for it, even if we have * previously loaded a diff for this change */ request = new ZipRequest(this, mChangeNumber, mPatchsetNumber, new Response.Listener<String>() { @Override public void onResponse(String s) { if (s != null) setTextView(s); else mDiffTextView.setText(getString(R.string.failed_to_get_diff)); switchViews(DiffType.Text); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { mDiffTextView.setText(R.string.failed_to_get_diff); switchViews(DiffType.Text); } }); if (requestQueue == null) requestQueue = Volley.newRequestQueue(this); requestQueue.add(request); } // Set the title of this activity private void setChangeTitle(Integer changeNumber) { String s = getResources().getString(R.string.change_detail_heading); setTitle(String.format(s, changeNumber)); } private void switchViews(DiffType type) { mSwitcher.setDisplayedChild(type.ordinal()); } // Handler for clicking on the previous file button public void onPreviousClick(View view) { int position = mAdapter.getPreviousPosition(mSpinner.getSelectedItemPosition()); if (position >= 0) mSpinner.setSelection(position); } // Handler for clicking on the next file button public void onNextClick(View view) { int position = mAdapter.getNextPosition(mSpinner.getSelectedItemPosition()); if (position >= 0) mSpinner.setSelection(position); } @Override public Loader<Cursor> onCreateLoader(int i, Bundle bundle) { return FileChanges.getDiffableFiles(this, mChangeNumber); } @Override public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { mAdapter.swapCursor(cursor); if (cursor != null && cursor.isAfterLast()) { if (request != null) request.cancel(); mDiffTextView.setText(getString(R.string.diff_no_files)); } int pos = mAdapter.getPositionOfFile(mFilePath); if (pos >= 0) mSpinner.setSelection(pos); } @Override public void onLoaderReset(Loader<Cursor> cursorLoader) { mAdapter.swapCursor(null); } }