/* * Copyright (C) 2009 Virgil Dobjanschi, Jeff Sharkey * * 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 no.java.schedule.activities.tabs; import android.app.ListActivity; import android.app.SearchManager; import android.content.ContentUris; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.BaseColumns; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.StyleSpan; import android.view.View; import android.view.ViewGroup; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.ResourceCursorAdapter; import android.widget.TextView; import no.java.schedule.R; import no.java.schedule.activities.fullscreen.SessionDetailsActivity; import no.java.schedule.provider.SessionsContract.SearchColumns; import no.java.schedule.provider.SessionsContract.Sessions; import no.java.schedule.provider.SessionsContract.SessionsColumns; import no.java.schedule.provider.SessionsContract.TracksColumns; import no.java.schedule.provider.SessionsProvider; /** * Activity to show search results as requested by {@link SearchManager}. */ public class SearchActivity extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.titled_session_view); onNewIntent(getIntent()); } @Override public void onNewIntent(Intent intent) { // Pull search query string from extras final String query = intent.getStringExtra(SearchManager.QUERY); // Set the title ((TextView)findViewById(R.id.title_text)).setText(getString(R.string.title_search, query)); //setTitle( getString(R.string.title_search, query)); // Push off search query to backend provider Uri searchUri = Uri.withAppendedPath(Sessions.CONTENT_SEARCH_URI, Uri.encode(query)); Cursor cursor = this.managedQuery(searchUri, Projections.PROJ_SESSIONS, null, null, null); // Prepare list adapter from cursor of results ListAdapter adapter = new SearchSessionsAdapter(this, cursor); this.setListAdapter(adapter); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { // Start details activity for selected item Uri sessionUri = ContentUris.withAppendedId(Sessions.CONTENT_URI, id); Intent intent = new Intent(this, SessionDetailsActivity.class); intent.setData(sessionUri); startActivity(intent); } /** * List adapter that shows {@link Sessions#CONTENT_SEARCH_URI} search * results, including formatting {@link SearchColumns#SNIPPET} snippets in * bold where marked. */ private static class SearchSessionsAdapter extends ResourceCursorAdapter { private static final int ROW_RESOURCE = R.layout.session_row_snippet; public SearchSessionsAdapter(Context context, Cursor c) { super(context, ROW_RESOURCE, c); } /** * Holder for an inflated view. */ private static class ChildHolder { View color; TextView title; TextView snippet; long sessionId; long trackId; long blockId; } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { final View view = super.newView(context, cursor, parent); ChildHolder holder = new ChildHolder(); holder.color = view.findViewById(R.id.session_color); holder.title = (TextView)view.findViewById(R.id.session_title); holder.snippet = (TextView)view.findViewById(R.id.snippet); view.setTag(holder); return view; } @Override public void bindView(View view, Context context, Cursor cursor) { final ChildHolder holder = (ChildHolder)view.getTag(); holder.color.setBackgroundColor(cursor.getInt(Projections.COL_COLOR) | 0xff000000); holder.title.setText(cursor.getString(Projections.COL_TITLE)); // Format snippet text final String snippet = cursor.getString(Projections.COL_SNIPPET); Spannable styledSnippet = buildStyledSnippet(snippet); holder.snippet.setText(styledSnippet); holder.sessionId = cursor.getInt(Projections.COL_ID); holder.trackId = cursor.getInt(Projections.COL_TRACK_ID); holder.blockId = cursor.getInt(Projections.COL_BLOCK_ID); } private StyleSpan mBoldSpan = new StyleSpan(android.graphics.Typeface.BOLD); /** * Given a snippet string with matching segments surrounded by curly * braces, turn those areas into bold spans, removing the curly braces. */ private Spannable buildStyledSnippet(String snippet) { SpannableStringBuilder builder = new SpannableStringBuilder(snippet); // Walk through string, inserting bold snippet spans int startIndex = -1, endIndex = -1, delta = 0; while ((startIndex = snippet.indexOf('{', endIndex)) != -1) { endIndex = snippet.indexOf('}', startIndex); // Remove braces from both sides builder.delete(startIndex - delta, startIndex - delta + 1); builder.delete(endIndex - delta - 1, endIndex - delta); // Insert bold style builder.setSpan(mBoldSpan, startIndex - delta, endIndex - delta - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); delta += 2; } return builder; } } /** * Various projections and static columns for querying into * {@link SessionsProvider} tables. */ public static interface Projections { public static final String[] PROJ_SESSIONS = new String[] { BaseColumns._ID, SessionsColumns.TRACK_ID, TracksColumns.COLOR, SessionsColumns.BLOCK_ID, SessionsColumns.TITLE, SessionsColumns.STARRED, SearchColumns.SNIPPET, }; public static final int COL_ID = 0; public static final int COL_TRACK_ID = 1; public static final int COL_COLOR = 2; public static final int COL_BLOCK_ID = 3; public static final int COL_TITLE = 4; public static final int COL_STARRED = 5; public static final int COL_SNIPPET = 6; } }