edu.berkeley.boinc.ProjectDetailsFragment.java Source code

Java tutorial

Introduction

Here is the source code for edu.berkeley.boinc.ProjectDetailsFragment.java

Source

/*******************************************************************************
 * This file is part of BOINC.
 * http://boinc.berkeley.edu
 * Copyright (C) 2012 University of California
 * 
 * BOINC is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 * 
 * BOINC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package edu.berkeley.boinc;

import edu.berkeley.boinc.utils.*;
import java.util.ArrayList;
import android.app.Activity;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.support.v4.app.Fragment;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import edu.berkeley.boinc.rpc.ImageWrapper;
import edu.berkeley.boinc.rpc.Project;
import edu.berkeley.boinc.rpc.ProjectInfo;
import edu.berkeley.boinc.rpc.RpcClient;

public class ProjectDetailsFragment extends Fragment {

    private String url;
    private ProjectInfo projectInfo; // might be null for projects added via manual URL attach
    private Project project;
    private ArrayList<ImageWrapper> slideshowImages = new ArrayList<ImageWrapper>();

    private LayoutInflater li;
    private View root;
    private HorizontalScrollView slideshowWrapper;
    private LinearLayout slideshowHook;
    private ProgressBar slideshowLoading;

    // display dimensions
    private int width;
    private int height;

    private boolean retryLayout = true;

    // BroadcastReceiver event is used to update the UI with updated information from 
    // the client.  This is generally called once a second.
    //
    private IntentFilter ifcsc = new IntentFilter("edu.berkeley.boinc.clientstatuschange");
    private BroadcastReceiver mClientStatusChangeRec = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //if(Logging.DEBUG) Log.d(Logging.TAG, "ClientStatusChange - onReceive()");
            getCurrentProjectData();
            if (retryLayout)
                populateLayout();
            else
                updateChangingItems(root);

        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // get data
        url = getArguments().getString("url");
        getCurrentProjectData();

        setHasOptionsMenu(true); // enables fragment specific menu
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (Logging.VERBOSE)
            Log.v(Logging.TAG, "ProjectDetailsFragment onCreateView");
        // Inflate the layout for this fragment
        this.li = inflater;
        View layout = inflater.inflate(R.layout.project_details_layout, container, false);
        root = layout;
        return layout;
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onAttach(Activity activity) {
        // first time fragment can get a valid context (before this, getActivity() will return null!)
        Display display = activity.getWindowManager().getDefaultDisplay();
        width = display.getWidth();
        height = display.getHeight();
        super.onAttach(activity);
    }

    @Override
    public void onPause() {
        getActivity().unregisterReceiver(mClientStatusChangeRec);
        super.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        getActivity().registerReceiver(mClientStatusChangeRec, ifcsc);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // appends the project specific menu to the main menu.
        inflater.inflate(R.menu.project_details_menu, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {

        super.onPrepareOptionsMenu(menu);
        if (project == null)
            return;

        // no new tasks, adapt based on status 
        MenuItem nnt = menu.findItem(R.id.projects_control_nonewtasks);
        if (project.dont_request_more_work)
            nnt.setTitle(R.string.projects_control_allownewtasks);
        else
            nnt.setTitle(R.string.projects_control_nonewtasks);

        // project suspension, adapt based on status 
        MenuItem suspend = menu.findItem(R.id.projects_control_suspend);
        if (project.suspended_via_gui)
            suspend.setTitle(R.string.projects_control_resume);
        else
            suspend.setTitle(R.string.projects_control_suspend);

        // detach, only show when project not managed
        MenuItem remove = menu.findItem(R.id.projects_control_remove);
        if (project.attached_via_acct_mgr)
            remove.setVisible(false);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.projects_control_update:
            new ProjectOperationAsync().execute(RpcClient.PROJECT_UPDATE);
            break;
        case R.id.projects_control_suspend:
            if (project.suspended_via_gui)
                new ProjectOperationAsync().execute(RpcClient.PROJECT_RESUME);
            else
                new ProjectOperationAsync().execute(RpcClient.PROJECT_SUSPEND);
            break;
        case R.id.projects_control_nonewtasks:
            if (project.dont_request_more_work)
                new ProjectOperationAsync().execute(RpcClient.PROJECT_ANW);
            else
                new ProjectOperationAsync().execute(RpcClient.PROJECT_NNW);
            break;
        case R.id.projects_control_reset:
            showConfirmationDialog(RpcClient.PROJECT_RESET);
            break;
        case R.id.projects_control_remove:
            showConfirmationDialog(RpcClient.PROJECT_DETACH);
            break;
        default:
            if (Logging.WARNING)
                Log.w(Logging.TAG, "ProjectDetailsFragment onOptionsItemSelected: could not match ID");
        }

        return super.onOptionsItemSelected(item);
    }

    private void showConfirmationDialog(final int operation) {
        final Dialog dialog = new Dialog(getActivity());
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(R.layout.dialog_confirm);
        Button confirm = (Button) dialog.findViewById(R.id.confirm);
        TextView tvTitle = (TextView) dialog.findViewById(R.id.title);
        TextView tvMessage = (TextView) dialog.findViewById(R.id.message);

        // operation dependend texts
        if (operation == RpcClient.PROJECT_DETACH) {
            tvTitle.setText(R.string.projects_confirm_detach_title);
            tvMessage.setText(getString(R.string.projects_confirm_detach_message) + " " + project.project_name + " "
                    + getString(R.string.projects_confirm_detach_message2));
            confirm.setText(R.string.projects_confirm_detach_confirm);
        } else if (operation == RpcClient.PROJECT_RESET) {
            tvTitle.setText(R.string.projects_confirm_reset_title);
            tvMessage.setText(getString(R.string.projects_confirm_reset_message) + " " + project.project_name
                    + getString(R.string.projects_confirm_reset_message2));
            confirm.setText(R.string.projects_confirm_reset_confirm);
        }

        confirm.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                new ProjectOperationAsync().execute(operation);
                dialog.dismiss();
            }
        });
        Button cancel = (Button) dialog.findViewById(R.id.cancel);
        cancel.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
        dialog.show();
    }

    private void populateLayout() {

        if (project == null) {
            retryLayout = true;
            return; // if data not available yet, return. frequently retrys with onReceive
        }

        retryLayout = false;
        View v = root;

        updateChangingItems(v);

        slideshowWrapper = (HorizontalScrollView) v.findViewById(R.id.slideshow_wrapper);
        slideshowHook = (LinearLayout) v.findViewById(R.id.slideshow_hook);
        slideshowLoading = (ProgressBar) v.findViewById(R.id.slideshow_loading);

        // set website
        TextView website = (TextView) v.findViewById(R.id.project_url);
        SpannableString content = new SpannableString(project.master_url);
        content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
        website.setText(content);
        website.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(project.master_url));
                startActivity(i);
            }
        });

        // set general area
        if (projectInfo != null && projectInfo.generalArea != null) {
            TextView generalArea = (TextView) v.findViewById(R.id.general_area);
            generalArea.setText(projectInfo.generalArea);
        } else {
            LinearLayout wrapper = (LinearLayout) v.findViewById(R.id.general_area_wrapper);
            wrapper.setVisibility(View.GONE);
        }

        // set specific area
        if (projectInfo != null && projectInfo.specificArea != null) {
            TextView specificArea = (TextView) v.findViewById(R.id.specific_area);
            specificArea.setText(projectInfo.specificArea);
        } else {
            LinearLayout wrapper = (LinearLayout) v.findViewById(R.id.specific_area_wrapper);
            wrapper.setVisibility(View.GONE);
        }

        // set description
        if (projectInfo != null && projectInfo.description != null) {
            TextView description = (TextView) v.findViewById(R.id.description);
            description.setText(projectInfo.description);
        } else {
            LinearLayout wrapper = (LinearLayout) v.findViewById(R.id.description_wrapper);
            wrapper.setVisibility(View.GONE);
        }

        // set home
        if (projectInfo != null && projectInfo.home != null) {
            TextView home = (TextView) v.findViewById(R.id.based_at);
            home.setText(projectInfo.home);
        } else {
            LinearLayout wrapper = (LinearLayout) v.findViewById(R.id.based_at_wrapper);
            wrapper.setVisibility(View.GONE);
        }

        // load slideshow
        new UpdateSlideshowImagesAsync().execute();
    }

    private void getCurrentProjectData() {
        try {
            ArrayList<Project> allProjects = (ArrayList<Project>) BOINCActivity.monitor.getProjects();
            for (Project tmpP : allProjects) {
                if (tmpP.master_url.equals(url))
                    this.project = tmpP;
            }
            this.projectInfo = BOINCActivity.monitor.getProjectInfo(url);
        } catch (Exception e) {
            if (Logging.ERROR)
                Log.e(Logging.TAG, "ProjectDetailsFragment getCurrentProjectData could not retrieve project list");
        }
        if (this.project == null)
            if (Logging.WARNING)
                Log.w(Logging.TAG,
                        "ProjectDetailsFragment getCurrentProjectData could not find project for URL: " + url);
        if (this.projectInfo == null)
            if (Logging.DEBUG)
                Log.d(Logging.TAG,
                        "ProjectDetailsFragment getCurrentProjectData could not find project attach list for URL: "
                                + url);
    }

    private void updateChangingItems(View v) {
        try {
            // status
            String newStatus = BOINCActivity.monitor.getProjectStatus(project.master_url);
            LinearLayout wrapper = (LinearLayout) v.findViewById(R.id.status_wrapper);
            if (!newStatus.isEmpty()) {
                wrapper.setVisibility(View.VISIBLE);
                TextView statusT = (TextView) v.findViewById(R.id.status_text);
                statusT.setText(newStatus);
            } else {
                wrapper.setVisibility(View.GONE);
            }

        } catch (Exception e) {
        }
    }

    // executes project operations in new thread
    private final class ProjectOperationAsync extends AsyncTask<Object, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Object... params) {
            if (Logging.DEBUG)
                Log.d(Logging.TAG, "ProjectOperationAsync doInBackground");
            try {
                Integer operation = (Integer) params[0];
                return BOINCActivity.monitor.projectOp(operation, project.master_url);
            } catch (Exception e) {
                if (Logging.WARNING)
                    Log.w(Logging.TAG, "ProjectOperationAsync error in do in background", e);
            }
            return false;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            if (success)
                try {
                    BOINCActivity.monitor.forceRefresh();
                } catch (RemoteException e) {
                }
            else if (Logging.WARNING)
                Log.w(Logging.TAG, "ProjectOperationAsync failed.");
        }
    }

    private final class UpdateSlideshowImagesAsync extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... params) {
            if (Logging.DEBUG)
                Log.d(Logging.TAG,
                        "UpdateSlideshowImagesAsync updating images in new thread. project: " + project.master_url);
            try {
                //status  = Monitor.getClientStatus();
                slideshowImages = (ArrayList<ImageWrapper>) BOINCActivity.monitor
                        .getSlideshowForProject(project.master_url);
            } catch (Exception e) {
                if (Logging.WARNING)
                    Log.w(Logging.TAG,
                            "UpdateSlideshowImagesAsync: Could not load data, clientStatus not initialized.");
                return false;
            }
            // load slideshow images
            //         slideshowImages = status.getSlideshowForProject(project.master_url);
            if (slideshowImages == null || slideshowImages.size() == 0)
                return false;
            return true;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            if (Logging.DEBUG)
                Log.d(Logging.TAG,
                        "UpdateSlideshowImagesAsync success: " + success + " images: " + slideshowImages.size());

            if (success && slideshowImages.size() > 0) {
                slideshowLoading.setVisibility(View.GONE);
                for (ImageWrapper image : slideshowImages) {
                    ImageView iv = (ImageView) li.inflate(R.layout.project_details_slideshow_image_layout, null);
                    Bitmap bitmap = image.image;
                    if (scaleImages(bitmap.getHeight(), bitmap.getWidth()))
                        bitmap = Bitmap.createScaledBitmap(image.image, image.image.getWidth() * 2,
                                image.image.getHeight() * 2, false);
                    iv.setImageBitmap(bitmap);
                    slideshowHook.addView(iv);
                }
            } else {
                slideshowWrapper.setVisibility(View.GONE);
            }
        }

        private boolean scaleImages(int imageHeight, int imageWidth) {
            return (height >= imageHeight * 2 && width >= imageWidth * 2);
        }
    }
}