add thumbnail: save scaled-down image when closing board, store it in

summaries db, and display as part of game list item.  Preference
governs whether saved/displayed and the scale.
This commit is contained in:
Eric House 2013-10-25 21:08:37 -07:00
parent e3c99595b1
commit 2c9cd311a5
11 changed files with 148 additions and 24 deletions

View file

@ -38,6 +38,15 @@
android:paddingRight="8dip" android:paddingRight="8dip"
/> />
<ImageView android:id="@+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:paddingRight="2dip"
android:paddingTop="2dip"
android:paddingBottom="2dip"
/>
<!-- this layout is vertical, holds everything but the status <!-- this layout is vertical, holds everything but the status
icon[s] (plural later) --> icon[s] (plural later) -->
<LinearLayout android:orientation="vertical" <LinearLayout android:orientation="vertical"

View file

@ -57,6 +57,7 @@
<string name="key_notify_vibrate">key_notify_vibrate</string> <string name="key_notify_vibrate">key_notify_vibrate</string>
<string name="key_enable_sms">key_enable_sms</string> <string name="key_enable_sms">key_enable_sms</string>
<string name="key_keep_screenon">key_keep_screenon</string> <string name="key_keep_screenon">key_keep_screenon</string>
<string name="key_thumbsize">key_thumbsize</string>
<string name="key_summary_field">key_summary_field</string> <string name="key_summary_field">key_summary_field</string>
<string name="key_default_loc">key_default_loc</string> <string name="key_default_loc">key_default_loc</string>
@ -135,6 +136,12 @@
<string name="gamel_menu_storedb">Write DB to SD card</string> <string name="gamel_menu_storedb">Write DB to SD card</string>
<string name="gamel_menu_loaddb">Load DB from SD card</string> <string name="gamel_menu_loaddb">Load DB from SD card</string>
<string name="game_thumb_off">Off</string>
<string name="game_thumb_third">1/3</string>
<string name="game_thumb_quarter">1/4</string>
<string name="game_thumb_fifth">1/5</string>
<string name="game_thumb_sixth">1/6</string>
<!--string name="dict_url">http://10.0.2.2/~eehouse/and_dicts</string--> <!--string name="dict_url">http://10.0.2.2/~eehouse/and_dicts</string-->
<string-array name="board_sizes"> <string-array name="board_sizes">
@ -281,4 +288,12 @@
<item>@string/confirm_sms_willpay</item> <item>@string/confirm_sms_willpay</item>
</string-array> </string-array>
<string-array name="game_thumb_values">
<item>@string/game_thumb_off</item>
<item>@string/game_thumb_third</item>
<item>@string/game_thumb_quarter</item>
<item>@string/game_thumb_fifth</item>
<item>@string/game_thumb_sixth</item>
</string-array>
</resources> </resources>

View file

@ -2173,4 +2173,6 @@
<string name="sel_gamesf">Games: %d"</string> <string name="sel_gamesf">Games: %d"</string>
<string name="sel_groupsf">Groups: %d"</string> <string name="sel_groupsf">Groups: %d"</string>
<string name="summary_thumbsize">Thumbnail size</string>
</resources> </resources>

View file

@ -138,6 +138,14 @@
android:defaultValue="false" android:defaultValue="false"
/> />
<org.eehouse.android.xw4.XWListPreference
android:key="@string/key_thumbsize"
android:title="@string/summary_thumbsize"
android:entries="@array/game_thumb_values"
android:entryValues="@array/game_thumb_values"
android:defaultValue="@string/game_thumb_off"
/>
<PreferenceScreen android:title="@string/prefs_colors" <PreferenceScreen android:title="@string/prefs_colors"
android:summary="@string/prefs_colors_summary" android:summary="@string/prefs_colors_summary"
> >

View file

@ -21,34 +21,39 @@
package org.eehouse.android.xw4; package org.eehouse.android.xw4;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface.OnDismissListener;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuInflater;
import android.view.KeyEvent;
import android.view.Window;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.content.Intent;
import java.util.concurrent.Semaphore; import android.text.TextUtils;
import java.util.ArrayList; import android.view.KeyEvent;
import java.util.Iterator; import android.view.Menu;
import android.app.Dialog; import android.view.MenuInflater;
import android.app.AlertDialog; import android.view.MenuItem;
import android.app.ProgressDialog; import android.view.View;
import android.content.DialogInterface; import android.view.Window;
import android.content.DialogInterface.OnDismissListener;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.Semaphore;
import junit.framework.Assert; import junit.framework.Assert;
import android.content.res.Configuration;
import android.content.pm.ActivityInfo;
import org.eehouse.android.xw4.jni.*; import org.eehouse.android.xw4.jni.*;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType; import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
@ -2028,7 +2033,8 @@ public class BoardActivity extends XWActivity
interruptBlockingThread(); interruptBlockingThread();
if ( null != m_jniThread ) { if ( null != m_jniThread ) {
m_jniThread.waitToStop( save ); Bitmap thumb = m_view.getScaledBoard();
m_jniThread.waitToStop( save, thumb );
m_jniThread = null; m_jniThread = null;
} }

View file

@ -937,6 +937,19 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
} }
} }
public Bitmap getScaledBoard()
{
Bitmap result = null;
int divisor = XWPrefs.getThumbScale( m_context );
if ( 0 < divisor ) {
result = Bitmap.createScaledBitmap( s_bitmap,
m_layoutWidth / divisor,
m_layoutHeight / divisor,
false );
}
return result;
}
private void drawTileImpl( Rect rect, String text, int val, private void drawTileImpl( Rect rect, String text, int val,
int flags, boolean clearBack ) int flags, boolean clearBack )
{ {

View file

@ -25,15 +25,21 @@ import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.os.Environment; import android.os.Environment;
import android.text.TextUtils; import android.text.TextUtils;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@ -41,7 +47,6 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import junit.framework.Assert; import junit.framework.Assert;
import org.eehouse.android.xw4.jni.*; import org.eehouse.android.xw4.jni.*;
@ -132,7 +137,7 @@ public class DBUtils {
DBHelper.DICTLANG, DBHelper.GAMEID, DBHelper.DICTLANG, DBHelper.GAMEID,
DBHelper.SCORES, DBHelper.HASMSGS, DBHelper.SCORES, DBHelper.HASMSGS,
DBHelper.LASTPLAY_TIME, DBHelper.REMOTEDEVS, DBHelper.LASTPLAY_TIME, DBHelper.REMOTEDEVS,
DBHelper.LASTMOVE DBHelper.LASTMOVE, DBHelper.THUMBNAIL
}; };
String selection = String.format( ROW_ID_FMT, lock.getRowid() ); String selection = String.format( ROW_ID_FMT, lock.getRowid() );
@ -179,6 +184,14 @@ public class DBUtils {
summary.lastMoveTime = summary.lastMoveTime =
cursor.getInt(cursor.getColumnIndex(DBHelper.LASTMOVE)); cursor.getInt(cursor.getColumnIndex(DBHelper.LASTMOVE));
byte[] data =
cursor.getBlob( cursor.getColumnIndex(DBHelper.THUMBNAIL));
if ( null != data ) {
Bitmap thumb = BitmapFactory.decodeByteArray( data, 0,
data.length );
summary.setThumbnail( thumb );
}
String scoresStr = String scoresStr =
cursor.getString( cursor.getColumnIndex(DBHelper.SCORES)); cursor.getString( cursor.getColumnIndex(DBHelper.SCORES));
int[] scores = new int[summary.nPlayers]; int[] scores = new int[summary.nPlayers];
@ -308,6 +321,17 @@ public class DBUtils {
break; break;
} }
} }
Bitmap thumb = summary.getThumbnail();
if ( null == thumb ) {
values.putNull( DBHelper.THUMBNAIL );
} else {
ByteArrayOutputStream bas = new ByteArrayOutputStream();
thumb.compress( CompressFormat.PNG, 0 , bas );
byte[] data = bas.toByteArray();
values.put( DBHelper.THUMBNAIL, data );
}
values.put( DBHelper.SERVERROLE, summary.serverRole.ordinal() ); values.put( DBHelper.SERVERROLE, summary.serverRole.ordinal() );
long result = db.update( DBHelper.TABLE_NAME_SUM, long result = db.update( DBHelper.TABLE_NAME_SUM,

View file

@ -21,6 +21,7 @@
package org.eehouse.android.xw4; package org.eehouse.android.xw4;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@ -51,6 +52,7 @@ public class GameListItem extends LinearLayout
private boolean m_loaded; private boolean m_loaded;
private long m_rowid; private long m_rowid;
private View m_hideable; private View m_hideable;
private ImageView m_thumb;
private ExpiringTextView m_name; private ExpiringTextView m_name;
private boolean m_expanded, m_haveTurn, m_haveTurnLocal; private boolean m_expanded, m_haveTurn, m_haveTurnLocal;
private long m_lastMoveTime; private long m_lastMoveTime;
@ -185,6 +187,7 @@ public class GameListItem extends LinearLayout
R.drawable.expander_ic_maximized : R.drawable.expander_ic_maximized :
R.drawable.expander_ic_minimized); R.drawable.expander_ic_minimized);
m_hideable.setVisibility( m_expanded? View.VISIBLE : View.GONE ); m_hideable.setVisibility( m_expanded? View.VISIBLE : View.GONE );
m_thumb.setVisibility( m_expanded? View.VISIBLE : View.GONE );
m_name.setBackgroundColor( android.R.color.transparent ); m_name.setBackgroundColor( android.R.color.transparent );
m_name.setPct( m_handler, m_haveTurn && !m_expanded, m_name.setPct( m_handler, m_haveTurn && !m_expanded,
@ -292,6 +295,14 @@ public class GameListItem extends LinearLayout
} }
} ); } );
m_thumb = (ImageView)findViewById( R.id.thumbnail );
Bitmap bmp = summary.getThumbnail();
if ( null == bmp ) {
m_thumb.setVisibility( View.GONE );
} else {
m_thumb.setImageBitmap( bmp );
}
tview = (TextView)findViewById( R.id.role ); tview = (TextView)findViewById( R.id.role );
String roleSummary = summary.summarizeRole(); String roleSummary = summary.summarizeRole();
if ( null != roleSummary ) { if ( null != roleSummary ) {

View file

@ -328,6 +328,24 @@ public class XWPrefs {
return posns; return posns;
} }
public static int getThumbScale( Context context )
{
String scale = getPrefsString( context, R.string.key_thumbsize );
int result = -1;
if ( context.getString(R.string.game_thumb_off).equals(scale) ) {
result = 0;
} else if ( context.getString(R.string.game_thumb_third).equals(scale) ) {
result = 3;
} else if ( context.getString(R.string.game_thumb_quarter).equals(scale) ) {
result = 4;
} else if ( context.getString(R.string.game_thumb_fifth).equals(scale) ) {
result = 5;
} else if ( context.getString(R.string.game_thumb_sixth).equals(scale) ) {
result = 6;
}
return result;
}
protected static String getPrefsString( Context context, int keyID ) protected static String getPrefsString( Context context, int keyID )
{ {
String key = context.getString( keyID ); String key = context.getString( keyID );

View file

@ -21,11 +21,14 @@
package org.eehouse.android.xw4.jni; package org.eehouse.android.xw4.jni;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils; import android.text.TextUtils;
import junit.framework.Assert; import junit.framework.Assert;
import org.eehouse.android.xw4.DbgUtils;
import org.eehouse.android.xw4.R; import org.eehouse.android.xw4.R;
import org.eehouse.android.xw4.Utils; import org.eehouse.android.xw4.Utils;
import org.eehouse.android.xw4.DbgUtils;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType; import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole; import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
@ -66,6 +69,7 @@ public class GameSummary {
private CurGameInfo m_gi; private CurGameInfo m_gi;
private Context m_context; private Context m_context;
private String[] m_remotePhones; private String[] m_remotePhones;
private Bitmap m_thumb;
private GameSummary() {} private GameSummary() {}
@ -85,6 +89,16 @@ public class GameSummary {
m_gi = gi; m_gi = gi;
} }
public void setThumbnail( Bitmap thumb )
{
m_thumb = thumb;
}
public Bitmap getThumbnail()
{
return m_thumb;
}
public boolean inNetworkGame() public boolean inNetworkGame()
{ {
return null != relayID; return null != relayID;

View file

@ -22,6 +22,7 @@
package org.eehouse.android.xw4.jni; package org.eehouse.android.xw4.jni;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Handler; import android.os.Handler;
@ -132,6 +133,7 @@ public class JNIThread extends Thread {
private static final int kMinDivWidth = 10; private static final int kMinDivWidth = 10;
private int m_connsIconID = 0; private int m_connsIconID = 0;
private String m_newDict = null; private String m_newDict = null;
private Bitmap m_thumbnail;
LinkedBlockingQueue<QueueElem> m_queue; LinkedBlockingQueue<QueueElem> m_queue;
@ -160,11 +162,12 @@ public class JNIThread extends Thread {
m_queue = new LinkedBlockingQueue<QueueElem>(); m_queue = new LinkedBlockingQueue<QueueElem>();
} }
public void waitToStop( boolean save ) public void waitToStop( boolean save, Bitmap thumb )
{ {
synchronized ( this ) { synchronized ( this ) {
m_stopped = true; m_stopped = true;
m_saveOnStop = save; m_saveOnStop = save;
m_thumbnail = thumb;
} }
handle( JNICmd.CMD_NONE ); // tickle it handle( JNICmd.CMD_NONE ); // tickle it
try { try {
@ -298,6 +301,7 @@ public class JNIThread extends Thread {
// DbgUtils.logf( "no change in game; can skip saving" ); // DbgUtils.logf( "no change in game; can skip saving" );
} else { } else {
GameSummary summary = new GameSummary( m_context, m_gi ); GameSummary summary = new GameSummary( m_context, m_gi );
summary.setThumbnail( m_thumbnail );
XwJNI.game_summarize( m_jniGamePtr, summary ); XwJNI.game_summarize( m_jniGamePtr, summary );
DBUtils.saveGame( m_context, m_lock, state, false ); DBUtils.saveGame( m_context, m_lock, state, false );
DBUtils.saveSummary( m_context, m_lock, summary ); DBUtils.saveSummary( m_context, m_lock, summary );