/**
Copyright 2012 Fahad Al-Khameesi, Madeleine Appert, Niklas Logren, Arild Matsson and Jonathan Orrö.
This file is part of Bibbla.
Bibbla is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bibbla 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bibbla. If not, see <http://www.gnu.org/licenses/>.
**/
package dat255.grupp06.bibbla.fragments;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
import dat255.grupp06.bibbla.R;
import dat255.grupp06.bibbla.backend.Backend;
import dat255.grupp06.bibbla.backend.BackendFactory;
import dat255.grupp06.bibbla.model.Book;
import dat255.grupp06.bibbla.utils.Callback;
import dat255.grupp06.bibbla.utils.Message;
/**
* A fragment that holds the search bar, button
* and a ListFragment that displays search results
*
* @author Jonathan Orrö
*/
public class SearchFragment extends SherlockFragment {
SearchListFragment listFragment;
EditText searchEdit;
Button searchButton;
ProgressBar searchProgress;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if(listFragment == null) {
listFragment = new SearchListFragment();
fragmentTransaction.add(R.id.list_container, listFragment);
} else {
fragmentTransaction.attach(listFragment);
}
fragmentTransaction.commit();
return inflater.inflate(R.layout.fragment_search, container, false);
}
@Override
public void onDestroyView() {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.detach(listFragment);
fragmentTransaction.commit();
super.onDestroyView();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Get our GUI elements.
searchButton = (Button)getSherlockActivity().findViewById(R.id.button_search);
searchEdit = (EditText)getSherlockActivity().findViewById(R.id.edit_search);
searchEdit.setTextColor(0xfff0641e);
searchProgress = (ProgressBar)getSherlockActivity().findViewById(R.id.progress_search);
// Create a listener for keyboard "enter" button.
OnEditorActionListener listener = new OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// Simulate click on the search button.
searchButton.performClick();
return true;
}
return false;
}
};
// Add our newly created listener to the text field.
searchEdit.setOnEditorActionListener(listener);
}
/**
* Starts searching procedure in backend.
*/
public void searchClicked() {
// Convert search string to UTF-8.
String searchString = searchEdit.getText().toString();
try {
searchString = URLEncoder.encode(searchString, "UTF-8");
} catch (UnsupportedEncodingException e) {}
// Display progress bar.
setProgressBarVisibility(true);
// No input? No need to search.
if("".equals(searchString)) {
listFragment.updateList(new ArrayList<Book>());
return;
}
// Create a new callback object, which refers to our searchDone().
Callback c = new Callback() {
public void handleMessage(Message msg) {
SearchFragment.this.searchDone(msg);
}
};
// Call backend search.
BackendFactory.getBackend().search(searchString, 0, c);
listFragment.setLastSearchString(searchString);
}
/**
* Is used to get more search results after the first page has already been
* fetched.
* @param page - What page do you want?
* @param searchString - What are you searching for?
*/
public void getMoreSearchResults(int page, String searchString) {
setProgressBarVisibility(true);
// Create a new callback object, which refers to our searchDone().
Callback c = new Callback() {
public void handleMessage(Message msg) {
SearchFragment.this.moreSearchDone(msg);
}
};
// Call backend search.
Log.d("Jonis", "searching..... on page "+page);
BackendFactory.getBackend().search(searchString, page, c);
}
/**
* Is called from a callback object when backend searching is done.
* @param msg - Message object that contains all the books that searchJob
* finds. Also the occasional error message.
*/
public void searchDone(Message msg) {
// Hide progress bar.
setProgressBarVisibility(false);
// Did the job fail?
if (msg.error != null) {
// Log,
Log.e("searching", "Searching failed: "+msg.error);
// And toast user.
Toast.makeText(getSherlockActivity().getApplicationContext(), "Searching failed: "+msg.error, Toast.LENGTH_LONG).show();
return;
}
// Convert results to ArrayList<Book>.
@SuppressWarnings("unchecked")
ArrayList<Book> books = (ArrayList<Book>) msg.obj;
// Did we get no results?
if (books.size() == 0) {
Toast.makeText(getSherlockActivity().getApplicationContext(), "No results found.", Toast.LENGTH_LONG).show();
}
// Update list with titles (empty or not).
listFragment.updateList(books);
}
/**
* Is called from a callback object when backend searching is done.
* It is different from searchDone since we want to append the search
* results to the current list instead of replacing it.
* @param msg - Contains the books found by the search job and also
* an error message if there was an error.
*/
public void moreSearchDone(Message msg) {
// Hide progress bar.
setProgressBarVisibility(false);
// Did the job fail?
if (msg.error != null) {
// Log,
Log.e("searching", "Searching failed: "+msg.error);
// And toast user.
Toast.makeText(getSherlockActivity().getApplicationContext(), "Searching failed: "+msg.error, Toast.LENGTH_LONG).show();
return;
}
// Convert results to List<Book>.
@SuppressWarnings("unchecked")
ArrayList<Book> books = (ArrayList<Book>) msg.obj;
// Did we get no results?
if (books.size() == 0) {
Toast.makeText(getSherlockActivity().getApplicationContext(), "No results found.", Toast.LENGTH_LONG).show();
}
// Update list with titles (empty or not).
listFragment.appendList(books);
}
/**
* Changes the visibility of the progress bar.
* @param visible - should we show or hide the progress bar?
*/
private void setProgressBarVisibility(boolean visible) {
// Do only this if searchProgress exists.
if (searchProgress != null) {
// setVisibility takes an int.
int visibilityCode = (visible) ? View.VISIBLE : View.GONE;
searchProgress.setVisibility(visibilityCode);
}
}
}