Merge branch 'android_branch' of ssh://xwords.git.sourceforge.net/gitroot/xwords/xwords into android_branch

This commit is contained in:
Eric House 2010-08-25 10:15:39 -07:00
commit 33f6ad510e
24 changed files with 341 additions and 108 deletions

View file

@ -21,8 +21,8 @@
to come from a domain that you own or have control over. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.eehouse.android.xw4"
android:versionCode="6"
android:versionName="4.4 beta 13"
android:versionCode="7"
android:versionName="4.4 beta 14"
>
<uses-permission android:name="android.permission.INTERNET" />

View file

@ -1,29 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView android:id="@+id/version_string"
style="@style/about_items"
/>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView style="@style/about_items"
android:text="@string/about_copyright"
/>
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView style="@style/about_items"
android:text="@string/about_web"
android:autoLink="all"
/>
<TextView android:id="@+id/version_string"
style="@style/about_items"
/>
<TextView android:id="@+id/about_xlator"
style="@style/about_items"
/>
<TextView style="@style/about_items"
android:text="@string/about_copyright"
/>
<TextView style="@style/about_items"
android:text="@string/about_credits"
/>
<TextView style="@style/about_items"
android:text="@string/about_web"
android:autoLink="all"
/>
</LinearLayout>
<TextView android:id="@+id/about_xlator"
style="@style/about_items"
/>
<TextView style="@style/about_items"
android:text="@string/about_credits"
/>
</LinearLayout>
</ScrollView>

View file

@ -0,0 +1,34 @@
<html>
<head>
<style type="text/css">
body {font-size: smaller;}
</style>
</head>
<body>
<b>Crosswords 4.4 beta 14 release</b>
<ul>New features:
<li>This spiffy per-release dialog</li>
</ul>
<ul>Bugs fixed:
<li>Crash exiting board view</li>
<li>Hang searching for robot move</li>
<li>Crash putting up progress dialog after board hidden</li>
</ul>
<ul>Coming soon:
<li>builtin hints and help</li>
<li>rewrite of gameplay via relay to make connecting easier and allow closed game to receive moves.</li>
</ul>
<p>Please remember that this is beta software. Letting me know (at
eehouse@eehouse.org) what's broken and what features you'd most like
to see is the best way to help get this to release quality
quickly.</p>
<p>Thanks!<br>--Eric</p>
</body>
</html>

View file

@ -361,5 +361,7 @@
<string name="initial_player_minutes">Timer minutes per player</string>
<string name="git_rev_title">Source version id</string>
<string name="changes_title">Recent changes</string>
<string name="changes_button">Recent changes</string>
</resources>

View file

@ -592,7 +592,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
m_handler.post( new Runnable() {
public void run() {
if ( null != m_jniThread ) {
m_jniThread.handle( JNIThread.JNICmd.CMD_DO );
m_jniThread.handle( JNIThread.JNICmd.CMD_DO, false );
}
}
} );

View file

@ -445,8 +445,8 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
}
}
public boolean drawCell( Rect rect, String text, int tile, int owner,
int bonus, int hintAtts, int flags )
public boolean drawCell( final Rect rect, String text, int tile, int owner,
int bonus, int hintAtts, final int flags )
{
int backColor;
boolean empty = 0 != (flags & (CELL_DRAGSRC|CELL_ISEMPTY));
@ -500,6 +500,8 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
}
// frame the cell
m_canvas.drawRect( rect, m_strokePaint );
drawCrosshairs( rect, flags );
return true;
} // drawCell
@ -779,6 +781,21 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
}
}
private void drawCrosshairs( final Rect rect, final int flags )
{
int color = m_otherColors[CommonPrefs.COLOR_FOCUS];
if ( 0 != (flags & CELL_CROSSHOR) ) {
Rect hairRect = new Rect( rect );
hairRect.inset( 0, hairRect.height() / 3 );
fillRect( hairRect, color );
}
if ( 0 != (flags & CELL_CROSSVERT) ) {
Rect hairRect = new Rect( rect );
hairRect.inset( hairRect.width() / 3, 0 );
fillRect( hairRect, color );
}
}
private void fillRect( Rect rect, int color )
{
m_fillPaint.setColor( color );

View file

@ -115,7 +115,6 @@ public class DBUtils {
if ( null != summary.conType ) {
values.put( DBHelper.CONTYPE, summary.conType.ordinal() );
Utils.logf( "wrote CONTYPE" );
values.put( DBHelper.ROOMNAME, summary.roomName );
values.put( DBHelper.SMSPHONE, summary.smsPhone );
}

View file

@ -0,0 +1,123 @@
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
/*
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program 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 2 of the
* License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageInfo;
import android.app.AlertDialog;
import android.webkit.WebView;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
/* Put up a dialog greeting user after every upgrade. Based on
* similar feature in OpenSudoku, to whose author "Thanks".
*/
public class FirstRunDialog {
private static final String HIDDEN_PREFS = "xwprefs_hidden";
private static final String SHOWN_VERSION_KEY = "SHOWN_VERSION_KEY";
static void show( Context context, boolean skipCheck )
{
int thisVersion = 0;
int shownVersion = 0;
if ( !skipCheck ) {
try {
thisVersion = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0)
.versionCode;
Utils.logf( "versionCode: %d", thisVersion );
} catch ( Exception e ) {
}
}
SharedPreferences prefs = null;
if ( thisVersion > 0 ) {
prefs = context.getSharedPreferences( HIDDEN_PREFS,
Context.MODE_PRIVATE );
shownVersion = prefs.getInt( SHOWN_VERSION_KEY, 0 );
}
if ( skipCheck || shownVersion < thisVersion ) {
showDialog( context );
if ( !skipCheck ) {
Editor editor = prefs.edit();
editor.putInt( SHOWN_VERSION_KEY, thisVersion );
editor.commit();
}
}
}
private static void showDialog( Context context )
{
String page = null;
InputStream inputStream = null;
try {
inputStream = context.getResources()
.openRawResource(R.raw.changes);
final char[] buf = new char[0x1000];
StringBuilder stringBuilder = new StringBuilder();
Reader reader = new InputStreamReader( inputStream, "UTF-8" );
int nRead;
do {
nRead = reader.read( buf, 0, buf.length );
if ( nRead > 0 ) {
stringBuilder.append( buf, 0, nRead );
}
} while ( nRead >= 0 );
page = stringBuilder.toString();
}
catch ( IOException ioe ) {
Utils.logf( ioe.toString() );
}
finally {
// could just catch NPE....
if ( null != inputStream ) {
try {
inputStream.close();
} catch ( IOException ioe ) {
Utils.logf( ioe.toString() );
}
}
}
// This won't support e.g mailto refs. Probably want to
// launch the browser with an intent eventually.
WebView view = new WebView( context );
view.loadData( page, "text/html", "utf-8" );
AlertDialog dialog = new AlertDialog.Builder( context )
.setIcon(android.R.drawable.ic_menu_info_details)
.setTitle( R.string.changes_title )
.setView( view )
.setPositiveButton( R.string.button_ok, null)
.create();
dialog.show();
}
}

View file

@ -62,13 +62,13 @@ public class GameListAdapter extends XWListAdapter {
public Object getItem( int position )
{
String path = GameUtils.gamesList(m_context)[position];
final String path = GameUtils.gamesList(m_context)[position];
View layout = m_viewsCache.get( path );
if ( null == layout ) {
Utils.logf( "creating new list elem for %s", path );
layout = m_factory.inflate( m_layoutId, null );
byte[] stream = open( path );
byte[] stream = GameUtils.savedGame( m_context, path );
if ( null != stream ) {
CurGameInfo gi = new CurGameInfo( m_context );
XwJNI.gi_from_stream( gi, stream );
@ -103,24 +103,6 @@ public class GameListAdapter extends XWListAdapter {
return (View)getItem( position );
}
private byte[] open( String file )
{
byte[] stream = null;
try {
FileInputStream in = m_context.openFileInput( file );
int len = in.available();
stream = new byte[len];
in.read( stream, 0, len );
in.close();
} catch ( java.io.FileNotFoundException ex ) {
Utils.logf( "got FileNotFoundException: " + ex.toString() );
} catch ( java.io.IOException ex ) {
Utils.logf( "got IOException: " + ex.toString() );
}
return stream;
}
public void inval( String key )
{
m_viewsCache.remove( key );

View file

@ -31,15 +31,19 @@ import org.eehouse.android.xw4.jni.*;
public class GameUtils {
private static Object s_syncObj = new Object();
public static byte[] savedGame( Context context, String path )
{
byte[] stream = null;
try {
FileInputStream in = context.openFileInput( path );
int len = in.available();
stream = new byte[len];
in.read( stream, 0, len );
in.close();
synchronized( s_syncObj ) {
FileInputStream in = context.openFileInput( path );
int len = in.available();
stream = new byte[len];
in.read( stream, 0, len );
in.close();
}
} catch ( java.io.FileNotFoundException fnf ) {
Utils.logf( fnf.toString() );
stream = null;
@ -109,6 +113,7 @@ public class GameUtils {
public static void deleteGame( Context context, String path )
{
// does this need to be synchronized?
context.deleteFile( path );
DBUtils.saveSummary( path, null );
}
@ -147,10 +152,12 @@ public class GameUtils {
public static void saveGame( Context context, byte[] bytes, String path )
{
try {
FileOutputStream out = context.openFileOutput( path,
Context.MODE_PRIVATE );
out.write( bytes );
out.close();
synchronized( s_syncObj ) {
FileOutputStream out =
context.openFileOutput( path, Context.MODE_PRIVATE );
out.write( bytes );
out.close();
}
} catch ( java.io.IOException ex ) {
Utils.logf( "got IOException: " + ex.toString() );
}

View file

@ -127,6 +127,8 @@ public class GamesList extends ListActivity {
m_adapter = new GameListAdapter( this );
setListAdapter( m_adapter );
FirstRunDialog.show( this, false );
}
@Override

View file

@ -25,6 +25,7 @@ import java.lang.Thread;
import android.widget.Toast;
import android.content.Context;
import android.content.Intent;
import android.content.DialogInterface;
import android.widget.CheckBox;
import android.app.Activity;
import android.app.Dialog;
@ -54,7 +55,7 @@ public class Utils {
public static void logf( String msg )
{
s_time.setToNow();
String time = s_time.format("%H:%M:%S");
String time = s_time.format("[%H:%M:%S]");
long id = Thread.currentThread().getId();
Log.d( TAG, time + "-" + id + "-" + msg );
} // logf
@ -71,7 +72,7 @@ public class Utils {
Toast.makeText( context, text, Toast.LENGTH_SHORT).show();
}
static Dialog onCreateDialog( Context context, int id )
static Dialog onCreateDialog( final Context context, int id )
{
Assert.assertTrue( DIALOG_ABOUT == id );
LayoutInflater factory = LayoutInflater.from( context );
@ -93,6 +94,15 @@ public class Utils {
.setIcon( R.drawable.icon48x48 )
.setTitle( R.string.app_name )
.setView( view )
.setPositiveButton( R.string.changes_button,
new DialogInterface.OnClickListener() {
@Override
public void onClick( DialogInterface dlg,
int which )
{
FirstRunDialog.show( context, true );
}
} )
.create();
}

View file

@ -23,5 +23,5 @@ package org.eehouse.android.xw4;
public interface XWConstants {
public static final String GAME_EXTN = ".xwg";
public static final String DICT_EXTN = ".xwd";
public static final String VERSION_STR = "4.4 beta 13";
public static final String VERSION_STR = "4.4 beta 14";
}

View file

@ -31,7 +31,9 @@ public interface DrawCtx {
static final int CELL_VALHIDDEN = 0x20; /* show letter only, not value */
static final int CELL_DRAGSRC = 0x40; /* where drag originated */
static final int CELL_DRAGCUR = 0x80; /* where drag is now */
static final int CELL_ALL = 0xFF;
static final int CELL_CROSSVERT = 0x100;
static final int CELL_CROSSHOR = 0x200;
static final int CELL_ALL = 0x3FF;
/* BoardObjectType */
static final int OBJ_NONE = 0;

View file

@ -20,20 +20,6 @@
package org.eehouse.android.xw4.jni;
public class DrawScoreInfo {
public static final int CELL_NONE = 0x00;
public static final int CELL_ISBLANK = 0x01;
public static final int CELL_HIGHLIGHT = 0x02;
public static final int CELL_ISSTAR = 0x04;
public static final int CELL_ISCURSOR = 0x08;
public static final int CELL_ISEMPTY = 0x10; /* of a tray tile slot */
public static final int CELL_VALHIDDEN = 0x20; /* show letter only, not value */
public static final int CELL_DRAGSRC = 0x40; /* where drag originated */
public static final int CELL_DRAGCUR = 0x80; /* where drag is now */
public static final int CELL_ALL = 0xFF;
// LastScoreCallback lsc;
// void* lscClosure;
public String name;
public int playerNum;
public int totalScore;

View file

@ -25,6 +25,7 @@ import org.eehouse.android.xw4.Utils;
import android.content.Context;
import java.lang.InterruptedException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Iterator;
import android.os.Handler;
import android.os.Message;
import android.graphics.Paint;
@ -99,10 +100,11 @@ public class JNIThread extends Thread {
LinkedBlockingQueue<QueueElem> m_queue;
private class QueueElem {
protected QueueElem( JNICmd cmd, Object[] args )
protected QueueElem( JNICmd cmd, boolean isUI, Object[] args )
{
m_cmd = cmd; m_args = args;
m_cmd = cmd; m_isUIEvent = isUI; m_args = args;
}
boolean m_isUIEvent;
JNICmd m_cmd;
Object[] m_args;
}
@ -132,8 +134,15 @@ public class JNIThread extends Thread {
public boolean busy()
{ // synchronize this!!!
int siz = m_queue.size();
return siz > 0;
boolean result = false;
Iterator<QueueElem> iter = m_queue.iterator();
while ( iter.hasNext() ) {
if ( iter.next().m_isUIEvent ) {
result = true;
break;
}
}
return result;
}
public void setInBackground( boolean inBack )
@ -488,11 +497,16 @@ public class JNIThread extends Thread {
Utils.logf( "run exiting" );
} // run
public void handle( JNICmd cmd, Object... args )
public void handle( JNICmd cmd, boolean isUI, Object... args )
{
QueueElem elem = new QueueElem( cmd, args );
QueueElem elem = new QueueElem( cmd, isUI, args );
// Utils.logf( "adding: " + cmd.toString() );
m_queue.add( elem );
}
public void handle( JNICmd cmd, Object... args )
{
handle( cmd, true, args );
}
}

View file

@ -231,6 +231,23 @@ makeMiniWindowForTrade( BoardCtxt* board )
makeMiniWindowForText( board, text, MINIWINDOW_TRADING );
} /* makeMiniWindowForTrade */
#ifdef XWFEATURE_CROSSHAIRS
static CellFlags
flagsForCrosshairs( const BoardCtxt* board, XP_U16 col, XP_U16 row )
{
CellFlags flags = 0;
XP_Bool inHor, inVert;
dragDropInCrosshairs( board, col, row, &inHor, &inVert );
if ( inHor ) {
flags |= CELL_CROSSHOR;
}
if ( inVert ) {
flags |= CELL_CROSSVERT;
}
return flags;
}
#endif
static void
drawBoard( BoardCtxt* board )
{
@ -310,16 +327,14 @@ drawBoard( BoardCtxt* board )
CellFlags flags = CELL_NONE;
bonus = util_getSquareBonus( board->util, model, col, row );
hintAtts = figureHintAtts( board, col, row );
if ( 0 ) {
#ifdef KEYBOARD_NAV
} else if ( cellFocused( board, col, row ) ) {
if ( cellFocused( board, col, row ) ) {
flags |= CELL_ISCURSOR;
}
#endif
#ifdef XWFEATURE_CROSSHAIRS
} else if ( dragDropInCrosshairs( board, col, row ) ) {
flags |= CELL_ISCURSOR;
flags |= flagsForCrosshairs( board, col, row );
#endif
}
draw_drawBoardArrow( board->draw, &arrowRect, bonus,
arrow->vert, hintAtts, flags );
@ -433,9 +448,7 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks )
}
#endif
#ifdef XWFEATURE_CROSSHAIRS
if ( dragDropInCrosshairs( board, col, row ) ) {
flags |= CELL_ISCURSOR;
}
flags |= flagsForCrosshairs( board, col, row );
#endif
success = draw_drawCell( board->draw, &cellRect, textP, bptr,

View file

@ -1070,13 +1070,17 @@ relayCmdToStr( XWRELAY_Cmd cmd )
CASESTR( XWRELAY_CONNECT_RESP );
CASESTR( XWRELAY_RECONNECT_RESP );
CASESTR( XWRELAY_ALLHERE );
CASESTR( XWRELAY_ALLBACK );
CASESTR( XWRELAY_DISCONNECT_YOU );
CASESTR( XWRELAY_DISCONNECT_OTHER );
CASESTR( XWRELAY_CONNECTDENIED );
CASESTR( XWRELAY_HEARTBEAT );
CASESTR( XWRELAY_MSG_FROMRELAY );
CASESTR( XWRELAY_MSG_TORELAY );
default: return "<unknown>";
default:
XP_LOGF( "%s: unknown cmd: %d", __func__, cmd );
XP_ASSERT( 0 );
return "<unknown>";
}
}
# endif

View file

@ -659,16 +659,18 @@ startScrollTimerIf( BoardCtxt* board )
} /* startScrollTimerIf */
#ifdef XWFEATURE_CROSSHAIRS
XP_Bool
dragDropInCrosshairs( const BoardCtxt* board, XP_U16 col, XP_U16 row )
void
dragDropInCrosshairs( const BoardCtxt* board, XP_U16 col, XP_U16 row,
XP_Bool* inHor, XP_Bool* inVert )
{
XP_Bool result = dragDropInProgress( board );
if ( result ) {
if ( dragDropInProgress( board ) ) {
const DragState* ds = &board->dragState;
result = ds->crosshairs.col == col
|| ds->crosshairs.row == row;
*inHor = ds->crosshairs.row == row;
*inVert = ds->crosshairs.col == col;
} else {
*inHor = *inVert = XP_FALSE;
}
return result;
} /* dragDropInCrosshairs */
static void

View file

@ -58,7 +58,9 @@ XP_Bool dragDropGetHintLimits( const BoardCtxt* board, BdHintLimits* limits );
void dragDropTileInfo( const BoardCtxt* board, Tile* tile, XP_Bool* isBlank );
#ifdef XWFEATURE_CROSSHAIRS
XP_Bool dragDropInCrosshairs( const BoardCtxt* board, XP_U16 col, XP_U16 row );
void dragDropInCrosshairs( const BoardCtxt* board, XP_U16 col, XP_U16 row,
XP_Bool* inHor, XP_Bool* inVert );
#endif
#ifdef CPLUS

View file

@ -41,7 +41,9 @@ typedef enum {
, CELL_VALHIDDEN = 0x20 /* show letter only, not value */
, CELL_DRAGSRC = 0x40 /* where drag originated */
, CELL_DRAGCUR = 0x80 /* where drag is now */
, CELL_ALL = 0xFF
, CELL_CROSSVERT = 0x100 /* vertical component of crosshair */
, CELL_CROSSHOR = 0x200 /* horizontal component of crosshair */
, CELL_ALL = 0x3FF
} CellFlags;
typedef struct DrawScoreInfo {

View file

@ -513,11 +513,13 @@ engine_findMove( EngineCtxt* engine, const ModelCtxt* model,
result = XP_FALSE;
} else {
PossibleMove* move;
result = chooseMove( engine, &move );
if ( result ) {
if ( chooseMove( engine, &move ) ) {
XP_ASSERT( !!newMove );
XP_MEMCPY( newMove, &move->moveInfo, sizeof(*newMove) );
} else {
newMove->nTiles = 0;
}
result = XP_TRUE;
}
util_engineStopping( engine->util );

View file

@ -642,7 +642,7 @@ static XP_Bool
makeRobotMove( ServerCtxt* server )
{
XP_Bool result = XP_FALSE;
XP_Bool finished;
XP_Bool searchComplete;
XP_S16 turn;
const TrayTileSet* tileSet;
MoveInfo newMove;
@ -674,14 +674,14 @@ makeRobotMove( ServerCtxt* server )
}
XP_ASSERT( !!server_getEngineFor( server, turn ) );
finished = engine_findMove( server_getEngineFor( server, turn ),
model, model_getDictionary( model ),
tileSet->tiles, tileSet->nTiles, XP_FALSE,
searchComplete = engine_findMove( server_getEngineFor( server, turn ),
model, model_getDictionary( model ),
tileSet->tiles, tileSet->nTiles, XP_FALSE,
#ifdef XWFEATURE_SEARCHLIMIT
NULL, XP_FALSE,
NULL, XP_FALSE,
#endif
targetScore, &canMove, &newMove );
if ( finished ) {
targetScore, &canMove, &newMove );
if ( searchComplete ) {
const XP_UCHAR* str;
XWStreamCtxt* stream = NULL;

View file

@ -420,6 +420,28 @@ drawHintBorders( GtkDrawCtx* dctx, const XP_Rect* rect, HintAtts hintAtts)
}
}
#ifdef XWFEATURE_CROSSHAIRS
static void
drawCrosshairs( GtkDrawCtx* dctx, const XP_Rect* rect, CellFlags flags )
{
XP_Rect hairRect;
if ( 0 != (flags & CELL_CROSSHOR) ) {
hairRect = *rect;
hairRect.height /= 3;
hairRect.top += hairRect.height;
gtkFillRect( dctx, &hairRect, &dctx->cursor );
}
if ( 0 != (flags & CELL_CROSSVERT) ) {
hairRect = *rect;
hairRect.width /= 3;
hairRect.left += hairRect.width;
gtkFillRect( dctx, &hairRect, &dctx->cursor );
}
}
#else
# define drawCrosshairs( a, b, c )
#endif
static XP_Bool
gtk_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter,
const XP_Bitmaps* bitmaps, Tile XP_UNUSED(tile),
@ -504,6 +526,7 @@ gtk_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter,
}
drawHintBorders( dctx, rect, hintAtts );
drawCrosshairs( dctx, rect, flags );
return XP_TRUE;
} /* gtk_draw_drawCell */