package ca.ualberta.cs.cmput301f14t14.questionapp; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.UUID; import ca.ualberta.cs.cmput301f14t14.questionapp.data.Callback; import ca.ualberta.cs.cmput301f14t14.questionapp.data.ClientData; import ca.ualberta.cs.cmput301f14t14.questionapp.data.DataManager; import ca.ualberta.cs.cmput301f14t14.questionapp.model.Answer; import ca.ualberta.cs.cmput301f14t14.questionapp.model.Comment; import ca.ualberta.cs.cmput301f14t14.questionapp.model.Image; import ca.ualberta.cs.cmput301f14t14.questionapp.model.Question; import ca.ualberta.cs.cmput301f14t14.questionapp.view.AddAnswerDialogFragment; import ca.ualberta.cs.cmput301f14t14.questionapp.view.AddCommentDialogFragment; import ca.ualberta.cs.cmput301f14t14.questionapp.view.AddImage; import ca.ualberta.cs.cmput301f14t14.questionapp.view.AnswerListAdapter; import ca.ualberta.cs.cmput301f14t14.questionapp.view.CommentListAdapter; import ca.ualberta.cs.cmput301f14t14.questionapp.view.ViewCommentDialogFragment; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.location.Location; import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.TabHost; import android.widget.TextView; import android.widget.Toast; public class QuestionActivity extends Activity implements AddCommentDialogFragment.AddCommentDialogCallback { public static final String ARG_QUESTION_ID = "QUESTION_UUID"; static final String TAB_ANSWERS = "answer"; static final String TAB_COMMENTS = "comment"; private AnswerListAdapter aListAdapter = null; private CommentListAdapter<Question> cListAdapter = null; private UUID questionId = null; private Question question; private TabHost tabs; private DataManager dataManager; private ClientData clientData; private List<Comment<Question>> commentList; private List<Answer> answerList; private AddImage AI = new AddImage(); private static final int CAMERA = 1; private static final int ADD_IMAGE = 2; public Image img; private long MAX_SIZE = 64000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_question); tabs = (TabHost) findViewById(android.R.id.tabhost); tabs.setup(); Intent intent = getIntent(); dataManager = DataManager.getInstance(getApplicationContext()); clientData = new ClientData(this); String qId = intent.getStringExtra(ARG_QUESTION_ID); if (qId != null) { // we have a Question, grab it from dataManager questionId = UUID.fromString(qId); } else { // no Question, toss er back to the main screen Toast.makeText(getApplicationContext(), "Could not open specified question.", Toast.LENGTH_LONG).show(); finish(); } // Set up lists and adapters answerList = new ArrayList<Answer>(); commentList = new ArrayList<Comment<Question>>(); aListAdapter = new AnswerListAdapter(this, R.layout.list_answer, answerList); cListAdapter = new CommentListAdapter<Question>(this, R.layout.list_comment, commentList); // Set up list views ListView answerView = (ListView) findViewById(R.id.answerSummaryList); answerView.setAdapter(aListAdapter); ListView commentView = (ListView) findViewById(R.id.commentList); commentView.setAdapter(cListAdapter); TabHost.TabSpec aTab = tabs.newTabSpec(TAB_ANSWERS); aTab.setContent(R.id.answerSummaryList); aTab.setIndicator(String.format("%s (%d)", getString(R.string.tab_answers), aListAdapter.getCount())); tabs.addTab(aTab); TabHost.TabSpec cTab = tabs.newTabSpec(TAB_COMMENTS); cTab.setContent(R.id.commentList); cTab.setIndicator(getString(R.string.tab_comments)); tabs.addTab(cTab); // when clicking an answer item, view the answer in a separate activity answerView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Answer a = aListAdapter.getItem(position); UUID qId = question.getId(); Intent intent = new Intent(getBaseContext(), AnswerViewActivity.class); intent.putExtra(ARG_QUESTION_ID, qId.toString()); intent.putExtra("ANSWER_UUID", a.getId().toString()); startActivity(intent); } }); commentView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Comment<Question> c = cListAdapter.getItem(position); //Need questionId, commentId UUID qId = question.getId(); UUID cId = c.getId(); ViewCommentDialogFragment vcdf = new ViewCommentDialogFragment(); Bundle argbundle = new Bundle(); argbundle.putString("questionId", qId.toString()); argbundle.putString("commentId", cId.toString()); vcdf.setArguments(argbundle); vcdf.show(getFragmentManager(), "QuestionActivityViewCommentDF"); } }); } @Override public void onResume(){ super.onResume(); // Get question data dataManager.getQuestion(questionId, new QuestionUpdateCallback()); sortAnswers(); aListAdapter.update(); } public void sortAnswers(){ Collections.sort(answerList, new Comparator<Answer>(){ @Override public int compare(Answer lhs, Answer rhs) { if(lhs.getUpvotes().equals(rhs.getUpvotes())){ return lhs.getDate().compareTo(rhs.getDate()); } return lhs.getUpvotes()-rhs.getUpvotes(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.question, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); switch(id) { case R.id.action_settings: return true; case R.id.action_add_answer: addAnswer(null); break; case R.id.action_add_comment: addComment(null); break; } return super.onOptionsItemSelected(item); } /** * Handler for the add answer button * * Opens a new dialog in which to create an answer * * @param view */ public void addAnswer(View view) { AddAnswerDialogFragment dialogFragment = new AddAnswerDialogFragment(); dialogFragment.show(getFragmentManager(), "addanswerdialogfragmentlayout"); } public void addAnswerCallback(String body, Image img, Location location) { ClientData cd = new ClientData(this); Answer answer = null; try { answer = new Answer(question.getId(), body, cd.getUsername(), img); if(location != null){ answer.setLocation(location); } } catch (IllegalArgumentException e) { Toast.makeText(getApplicationContext(), R.string.add_answer_err_invalid, Toast.LENGTH_SHORT).show(); } dataManager.addAnswer(answer); question.addAnswer(answer.getId()); dataManager.addQuestion(question, null); updateQuestion(question); } /** * Handler for the add comment button * * Opens a new dialog in which to create a comment * * @param view */ public void addComment(View view) { AddCommentDialogFragment dialogFragment = new AddCommentDialogFragment(); dialogFragment.show(getFragmentManager(), "AVAaddcommentDF"); } @Override public void addCommentCallback(String text, Location loc) { ClientData cd = new ClientData(this); Comment<Question> comment = null; try { comment = new Comment<Question>(question.getId(), text, cd.getUsername()); if(loc != null){ comment.setLocation(loc); } } catch (IllegalArgumentException e) { Toast.makeText(getApplicationContext(), R.string.add_comment_err_invalid, Toast.LENGTH_SHORT).show(); } dataManager.addQuestionComment(comment); question.addComment(comment.getId()); dataManager.addQuestion(question, null); updateQuestion(question); } public void updateQuestion(Question q) { new QuestionUpdateCallback().run(q); } public void upvoteQuestion(View v) { // Adds upvotes and updates textview to show number of upvotes if (question.getAuthor().equals(clientData.getUsername())) { Toast.makeText(this, "Unable to upvote your own question", Toast.LENGTH_SHORT).show(); return; } if (clientData.isItemUpvoted(question.getId())) { Toast.makeText(this, "Cannot upvote a question more than once", Toast.LENGTH_SHORT).show(); return; } question.addUpvote(); TextView upvotes = (TextView) findViewById(R.id.upvotes); upvotes.setText(question.getUpvotes().toString()); DataManager.getInstance(this).addQuestion(question, null); clientData.markItemUpvoted(question.getId()); } public void favQuestion(View v){ //Need to change icon //Perhaps have a HashMap holding whether the question //is favorited or not. ImageButton Favbutton = (ImageButton)findViewById(R.id.question_view_fav_button); Favbutton.setImageResource(R.drawable.ic_fav_highlighted); ClientData cd = new ClientData(this); if (cd.getFavorites().contains(question.getId())) { //Question is already favorited. List<UUID> favq = cd.getFavorites(); favq.remove(question.getId()); cd.saveFavorites(favq); Favbutton.setImageResource(R.drawable.ic_fav_reg); } else { List<UUID> favq = cd.getFavorites(); favq.add(question.getId()); cd.saveFavorites(favq); Favbutton.setImageResource(R.drawable.ic_fav_highlighted); } } private class QuestionUpdateCallback implements Callback<Question> { @Override public void run(Question q) { question = q; TextView qTitle = (TextView) findViewById(R.id.questionTitle); qTitle.setText(question.getTitle()); TextView qBody = (TextView) findViewById(R.id.questionBody); qBody.setText(question.getBody()); TextView qUser = (TextView) findViewById(R.id.questionUser); qUser.setText(question.getAuthor()); TextView upvotes = (TextView) findViewById(R.id.upvotes); upvotes.setText(question.getUpvotes().toString()); TextView date = (TextView) findViewById(R.id.questionDate); date.setText(question.getDate().toString()); dataManager.getAnswerList(question, new AnswerListUpdateCallback()); dataManager.getCommentList(question, new CommentListUpdateCallback()); if(q.getImage() != null){ ImageView imgV = (ImageView) findViewById(R.id.questionImage); imgV.setImageBitmap(q.getImage().getBitmap()); } // Set status of favorite button ClientData cd = new ClientData(getApplicationContext()); if (cd.getFavorites().contains(question.getId())) { //Question is already favorited. //Set the star to be highlighted on create. ImageButton Favbutton = (ImageButton)findViewById(R.id.question_view_fav_button); Favbutton.setImageResource(R.drawable.ic_fav_highlighted); } else { //Question is not favorited. ImageButton Favbutton = (ImageButton)findViewById(R.id.question_view_fav_button); Favbutton.setImageResource(R.drawable.ic_fav_reg); } } } private class AnswerListUpdateCallback implements Callback<List<Answer>> { @Override public void run(List<Answer> list) { answerList.clear(); answerList.addAll(list); aListAdapter.update(); // Update count on answer tab TextView aTabLabel = (TextView) tabs.getTabWidget().getChildAt(0) .findViewById(android.R.id.title); aTabLabel.setText(String.format("%s (%d)", getString(R.string.tab_answers), aListAdapter.getCount())); } } private class CommentListUpdateCallback implements Callback<List<Comment<Question>>> { @Override public void run(List<Comment<Question>> list) { commentList.clear(); commentList.addAll(list); cListAdapter.update(); cListAdapter.sort(new Comparator<Comment<Question>>() { @Override public int compare(Comment<Question> c1, Comment<Question> c2) { return c2.getDate().compareTo(c1.getDate()); } }); } } public void takeAPhoto(View v){ Intent intent = AI.takeAPhoto(); startActivityForResult(intent, CAMERA); } public void addImage(View v){ Intent intent = AI.addPhoto(); startActivityForResult(intent.createChooser(intent, "Select Image"), ADD_IMAGE); } public void onActivityResult(int requestCode, int resultCode, Intent data){ super.onActivityResult(requestCode, resultCode, data); if(resultCode == Activity.RESULT_OK){ if (requestCode == CAMERA){ img = new Image(this, AI.getImgUri()); } else if(requestCode == ADD_IMAGE){ Uri uri = data.getData(); img = new Image(this, uri); } } while(img.getSize() > MAX_SIZE){ img.setImageData(img.compress(img.getBitmap())); } } }