Merge tag 'android_beta_111' into android_release

new release
This commit is contained in:
Eric House 2016-10-25 08:34:50 -07:00
commit c80665bf41
33 changed files with 252 additions and 157 deletions

View file

@ -48,3 +48,4 @@ chat_row.xml
fragact.xml fragact.xml
main.xml main.xml
dualcontainer.xml dualcontainer.xml
dict_browser_list.xml

View file

@ -22,7 +22,7 @@
to come from a domain that you own or have control over. --> to come from a domain that you own or have control over. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.eehouse.android.xw4" package="org.eehouse.android.xw4"
android:versionCode="105" android:versionCode="106"
android:versionName="@string/app_version" android:versionName="@string/app_version"
> >

View file

@ -2014,7 +2014,6 @@ XLATE-ME
/** <string name="data_gsm_only">SMS Data is only available on GSM phones.</string> /** <string name="data_gsm_only">SMS Data is only available on GSM phones.</string>
*/ */
public static final int data_gsm_only=0x7f05029b; public static final int data_gsm_only=0x7f05029b;
public static final int db_enabled_toast=0x7f050351;
/** <string name="db_store_done">SD card write complete.</string> /** <string name="db_store_done">SD card write complete.</string>
*/ */
public static final int db_store_done=0x7f05032d; public static final int db_store_done=0x7f05032d;

View file

@ -13,11 +13,12 @@
</style> </style>
</head> </head>
<body> <body>
<h2>Crosswords 4.4.110 release</h2> <h2>Crosswords 4.4.111 release</h2>
<p>This release fixes a couple of rare crashes added by the last <p>This release changes the display order of games in the main
release. That release's experimental support for side-by-side screen, placing those in which it's your turn at the top and games
views on tablets remains the focus.</p> that have ended at the bottom. And it fixes an occasional crash in
side-by-side mode.</p>
<div id="survey"> <div id="survey">
<p>Please <a href="https://www.surveymonkey.com/s/GX3XLHR">take <p>Please <a href="https://www.surveymonkey.com/s/GX3XLHR">take
@ -27,20 +28,12 @@
<h3>New with this release</h3> <h3>New with this release</h3>
<ul> <ul>
<li>Add side-by-side mode for tablets. For now, it's an option <li>Display at the top of the list games in which it's the local
tablet owners will be encouraged to enable. Later it'll always player's turn</li>
be on.</li>
<li>Improve board snapshots</li> <li>Display at the bottom of the list games that have ended</li>
<li>Make alerts' content scrollable (for very small screens)</li> <li>Fix crash launching app in side-by-side mode</li>
<li>Move "Play sound" preference</li>
<li>Remove old ways of zooming board (since modern phones have
multi-touch screens)</li>
<li>Fix invitations creating unclosable games</li>
</ul> </ul>
<p>(The full changelog <p>(The full changelog

View file

@ -1661,8 +1661,10 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1summarize
setInt( env, jsummary, "nMoves", nMoves ); setInt( env, jsummary, "nMoves", nMoves );
XP_Bool gameOver = server_getGameIsOver( state->game.server ); XP_Bool gameOver = server_getGameIsOver( state->game.server );
setBool( env, jsummary, "gameOver", gameOver ); setBool( env, jsummary, "gameOver", gameOver );
XP_Bool isLocal;
setInt( env, jsummary, "turn", setInt( env, jsummary, "turn",
server_getCurrentTurn( state->game.server ) ); server_getCurrentTurn( state->game.server, &isLocal ) );
setBool( env, jsummary, "turnIsLocal", isLocal );
setInt( env, jsummary, "lastMoveTime", setInt( env, jsummary, "lastMoveTime",
server_getLastMoveTime(state->game.server) ); server_getLastMoveTime(state->game.server) );

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_version">4.4.110</string> <string name="app_version">4.4.111</string>
</resources> </resources>

View file

@ -2694,5 +2694,4 @@
<string name="dualpane_restart">Exiting app…</string> <string name="dualpane_restart">Exiting app…</string>
<string name="after_restart">This change will not take effect until <string name="after_restart">This change will not take effect until
you restart Crosswords.</string> you restart Crosswords.</string>
<string name="db_enabled_toast">Side-by-side mode ENABLED</string>
</resources> </resources>

View file

@ -2302,5 +2302,4 @@
<string name="dualpane_restart">Gnitixe ppa…</string> <string name="dualpane_restart">Gnitixe ppa…</string>
<string name="after_restart">Siht egnahc lliw ton ekat tceffe litnu <string name="after_restart">Siht egnahc lliw ton ekat tceffe litnu
uoy tratser Sdrowssorc.</string> uoy tratser Sdrowssorc.</string>
<string name="db_enabled_toast">Edis-yb-edis edom DELBANE</string>
</resources> </resources>

View file

@ -2302,5 +2302,4 @@
<string name="dualpane_restart">EXITING APP…</string> <string name="dualpane_restart">EXITING APP…</string>
<string name="after_restart">THIS CHANGE WILL NOT TAKE EFFECT UNTIL <string name="after_restart">THIS CHANGE WILL NOT TAKE EFFECT UNTIL
YOU RESTART CROSSWORDS.</string> YOU RESTART CROSSWORDS.</string>
<string name="db_enabled_toast">SIDE-BY-SIDE MODE ENABLED</string>
</resources> </resources>

View file

@ -77,7 +77,9 @@ public class BoardContainer extends ViewGroup {
if ( 0 != width || 0 != height ) { if ( 0 != width || 0 != height ) {
setForPortrait( width, height ); setForPortrait( width, height );
figureBounds( 0, 0, width, height ); // Add a margin of half a percent of the lesser of width,height
int padding = (Math.min( width, height ) * 5) / 1000;
figureBounds( padding, padding, width-(padding*2), height-(padding*2) );
// Measure any toolbar first so we can take extra space for the // Measure any toolbar first so we can take extra space for the
// board // board

View file

@ -67,7 +67,6 @@ public class ChatDelegate extends DelegateBase {
@Override @Override
protected void init( Bundle savedInstanceState ) protected void init( Bundle savedInstanceState )
{ {
DbgUtils.logf( "ChatDelegate.init()" );
m_edit = (EditText)findViewById( R.id.chat_edit ); m_edit = (EditText)findViewById( R.id.chat_edit );
m_edit.addTextChangedListener( new TextWatcher() { m_edit.addTextChangedListener( new TextWatcher() {
public void afterTextChanged( Editable s ) { public void afterTextChanged( Editable s ) {

View file

@ -46,12 +46,13 @@ public class DBHelper extends SQLiteOpenHelper {
public static final String TABLE_NAME_CHAT = "chat"; public static final String TABLE_NAME_CHAT = "chat";
public static final String TABLE_NAME_LOGS = "logs"; public static final String TABLE_NAME_LOGS = "logs";
private static final String DB_NAME = "xwdb"; private static final String DB_NAME = "xwdb";
private static final int DB_VERSION = 27; private static final int DB_VERSION = 28;
public static final String GAME_NAME = "GAME_NAME"; public static final String GAME_NAME = "GAME_NAME";
public static final String VISID = "VISID"; public static final String VISID = "VISID";
public static final String NUM_MOVES = "NUM_MOVES"; public static final String NUM_MOVES = "NUM_MOVES";
public static final String TURN = "TURN"; public static final String TURN = "TURN";
public static final String TURN_LOCAL = "TURN_LOCAL";
public static final String GIFLAGS = "GIFLAGS"; public static final String GIFLAGS = "GIFLAGS";
public static final String PLAYERS = "PLAYERS"; public static final String PLAYERS = "PLAYERS";
@ -126,6 +127,7 @@ public class DBHelper extends SQLiteOpenHelper {
,{ GAME_NAME, "TEXT" } ,{ GAME_NAME, "TEXT" }
,{ NUM_MOVES, "INTEGER" } ,{ NUM_MOVES, "INTEGER" }
,{ TURN, "INTEGER" } ,{ TURN, "INTEGER" }
,{ TURN_LOCAL, "INTEGER" }
,{ GIFLAGS, "INTEGER" } ,{ GIFLAGS, "INTEGER" }
,{ NUM_PLAYERS, "INTEGER" } ,{ NUM_PLAYERS, "INTEGER" }
,{ MISSINGPLYRS,"INTEGER" } ,{ MISSINGPLYRS,"INTEGER" }
@ -322,6 +324,10 @@ public class DBHelper extends SQLiteOpenHelper {
createChatsTable( db ); createChatsTable( db );
case 26: case 26:
createLogsTable( db ); createLogsTable( db );
case 27:
if ( !madeSumTable ) {
addSumColumn( db, TURN_LOCAL );
}
break; break;
default: default:

View file

@ -125,7 +125,7 @@ public class DBUtils {
DBHelper.NUM_MOVES, DBHelper.NUM_PLAYERS, DBHelper.NUM_MOVES, DBHelper.NUM_PLAYERS,
DBHelper.MISSINGPLYRS, DBHelper.MISSINGPLYRS,
DBHelper.GAME_OVER, DBHelper.PLAYERS, DBHelper.GAME_OVER, DBHelper.PLAYERS,
DBHelper.TURN, DBHelper.GIFLAGS, DBHelper.TURN, DBHelper.TURN_LOCAL, DBHelper.GIFLAGS,
DBHelper.CONTYPE, DBHelper.SERVERROLE, DBHelper.CONTYPE, DBHelper.SERVERROLE,
DBHelper.ROOMNAME, DBHelper.RELAYID, DBHelper.ROOMNAME, DBHelper.RELAYID,
/*DBHelper.SMSPHONE,*/ DBHelper.SEED, /*DBHelper.SMSPHONE,*/ DBHelper.SEED,
@ -159,6 +159,8 @@ public class DBUtils {
summary.turn = summary.turn =
cursor.getInt(cursor. cursor.getInt(cursor.
getColumnIndex(DBHelper.TURN)); getColumnIndex(DBHelper.TURN));
summary.turnIsLocal = 0 != cursor.getInt(cursor.
getColumnIndex(DBHelper.TURN_LOCAL));
summary. summary.
setGiFlags( cursor.getInt(cursor. setGiFlags( cursor.getInt(cursor.
getColumnIndex(DBHelper.GIFLAGS)) getColumnIndex(DBHelper.GIFLAGS))
@ -269,6 +271,7 @@ public class DBUtils {
values.put( DBHelper.NUM_PLAYERS, summary.nPlayers ); values.put( DBHelper.NUM_PLAYERS, summary.nPlayers );
values.put( DBHelper.MISSINGPLYRS, summary.missingPlayers ); values.put( DBHelper.MISSINGPLYRS, summary.missingPlayers );
values.put( DBHelper.TURN, summary.turn ); values.put( DBHelper.TURN, summary.turn );
values.put( DBHelper.TURN_LOCAL, summary.turnIsLocal? 1 : 0 );
values.put( DBHelper.GIFLAGS, summary.giflags() ); values.put( DBHelper.GIFLAGS, summary.giflags() );
values.put( DBHelper.PLAYERS, values.put( DBHelper.PLAYERS,
summary.summarizePlayers() ); summary.summarizePlayers() );
@ -1627,7 +1630,8 @@ public class DBUtils {
initDB( context ); initDB( context );
String[] columns = { ROW_ID }; String[] columns = { ROW_ID };
String selection = String.format( "%s=%d", DBHelper.GROUPID, groupID ); String selection = String.format( "%s=%d", DBHelper.GROUPID, groupID );
String orderBy = DBHelper.CREATE_TIME + " DESC"; String orderBy = String.format( "%s,%s DESC,%s DESC", DBHelper.GAME_OVER,
DBHelper.TURN_LOCAL, DBHelper.LASTMOVE );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase(); SQLiteDatabase db = s_dbHelper.getReadableDatabase();
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns, Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,

View file

@ -124,11 +124,12 @@ public class DelegateBase implements DlgClickNotify,
protected void onStart() protected void onStart()
{ {
if ( s_instances.containsKey(getClass()) ) { Class clazz = getClass();
if ( s_instances.containsKey( clazz ) ) {
DbgUtils.logdf( "%s.onStart(): replacing curThis", DbgUtils.logdf( "%s.onStart(): replacing curThis",
getClass().getSimpleName() ); clazz.getSimpleName() );
} }
s_instances.put( getClass(), new WeakReference<DelegateBase>(this) ); s_instances.put( clazz, new WeakReference<DelegateBase>(this) );
} }
protected void onResume() protected void onResume()
@ -569,10 +570,16 @@ public class DelegateBase implements DlgClickNotify,
protected boolean isVisible() { return m_isVisible; } protected boolean isVisible() { return m_isVisible; }
protected boolean handleNewIntent( Intent intent ) { protected boolean canHandleNewIntent( Intent intent )
DbgUtils.logf( "%s.handleNewIntent(%s): not handling", {
getClass().getSimpleName(), intent.toString() ); DbgUtils.logdf( "%s.canHandleNewIntent() => false",
return false; // not handled getClass().getSimpleName(), intent.toString() );
return false;
}
protected void handleNewIntent( Intent intent ) {
DbgUtils.logdf( "%s.handleNewIntent(%s): not handling",
getClass().getSimpleName(), intent.toString() );
} }
protected void runWhenActive( Runnable proc ) protected void runWhenActive( Runnable proc )

View file

@ -965,9 +965,11 @@ public class DlgDelegate {
Dialog result = null; Dialog result = null;
DlgID dlgID = DlgID.values()[id]; DlgID dlgID = DlgID.values()[id];
WeakReference<DelegateBase> ref = s_pendings.get( dlgID ); WeakReference<DelegateBase> ref = s_pendings.get( dlgID );
DelegateBase dlgt = ref.get(); if ( null != ref ) {
if ( null != dlgt ) { DelegateBase dlgt = ref.get();
result = dlgt.onCreateDialog( id ); if ( null != dlgt ) {
result = dlgt.onCreateDialog( id );
}
} }
return result; return result;
} }

View file

@ -56,12 +56,11 @@ public class DualpaneDelegate extends DelegateBase {
} }
@Override @Override
protected boolean handleNewIntent( Intent intent ) protected void handleNewIntent( Intent intent )
{ {
MainActivity main = (MainActivity)m_activity; MainActivity main = (MainActivity)m_activity;
boolean handled = main.dispatchNewIntent( intent ); main.dispatchNewIntent( intent );
DbgUtils.logf( "DualpaneDelegate.handleNewIntent() => %b", handled ); DbgUtils.logf( "DualpaneDelegate.handleNewIntent()" );
return handled;
} }
@Override @Override

View file

@ -958,7 +958,6 @@ public class GameUtils {
CommsAddrRec ret, MultiMsgSink sink, CommsAddrRec ret, MultiMsgSink sink,
BackMoveResult bmr, boolean[] isLocalOut ) BackMoveResult bmr, boolean[] isLocalOut )
{ {
DbgUtils.logf( "GameUtils.feedMessage()" );
Assert.assertTrue( DBUtils.ROWID_NOTFOUND != rowid ); Assert.assertTrue( DBUtils.ROWID_NOTFOUND != rowid );
boolean draw = false; boolean draw = false;
Assert.assertTrue( -1 != rowid ); Assert.assertTrue( -1 != rowid );

View file

@ -400,14 +400,9 @@ public class GamesListDelegate extends ListDelegateBase
private List<Object> makeChildren( long groupID ) private List<Object> makeChildren( long groupID )
{ {
List<Object> alist = new ArrayList<Object>();
long[] rows = DBUtils.getGroupGames( m_activity, groupID ); long[] rows = DBUtils.getGroupGames( m_activity, groupID );
List<Object> alist = new ArrayList<Object>( rows.length );
for ( long row : rows ) { for ( long row : rows ) {
if ( false && BuildConfig.DEBUG ) {
GameUtils.BackMoveResult bmr = new GameUtils.BackMoveResult();
bmr.m_lmi = new LastMoveInfo();
GameUtils.postMoveNotification( m_activity, row, bmr, false );
}
alist.add( new GameRec( row ) ); alist.add( new GameRec( row ) );
} }
// DbgUtils.logf( "GamesListDelegate.makeChildren(%d) => %d kids", groupID, alist.size() ); // DbgUtils.logf( "GamesListDelegate.makeChildren(%d) => %d kids", groupID, alist.size() );
@ -988,17 +983,19 @@ public class GamesListDelegate extends ListDelegateBase
} // init } // init
@Override @Override
protected boolean handleNewIntent( Intent intent ) protected boolean canHandleNewIntent( Intent intent )
{ {
DbgUtils.logf( "GamesListDelegate.handleNewIntent(%s)", return true;
intent.toString() ); }
@Override
protected void handleNewIntent( Intent intent )
{
m_launchedGames.clear(); m_launchedGames.clear();
Assert.assertNotNull( intent ); Assert.assertNotNull( intent );
invalRelayIDs( intent.getStringArrayExtra( RELAYIDS_EXTRA ) ); invalRelayIDs( intent.getStringArrayExtra( RELAYIDS_EXTRA ) );
reloadGame( intent.getLongExtra( ROWID_EXTRA, -1 ) ); reloadGame( intent.getLongExtra( ROWID_EXTRA, -1 ) );
tryStartsFromIntent( intent ); tryStartsFromIntent( intent );
return true; // handled it
} }
@Override @Override
@ -1114,6 +1111,11 @@ public class GamesListDelegate extends ListDelegateBase
mkListAdapter(); mkListAdapter();
} else { } else {
reloadGame( rowid ); reloadGame( rowid );
if ( m_adapter.inExpandedGroup( rowid ) ) {
long groupID = DBUtils.getGroupForGame( m_activity, rowid );
m_adapter.setExpanded( groupID, false );
m_adapter.setExpanded( groupID, true );
}
} }
break; break;
case GAME_CREATED: case GAME_CREATED:
@ -1660,6 +1662,7 @@ public class GamesListDelegate extends ListDelegateBase
final boolean success ) final boolean success )
{ {
runWhenActive( new Runnable() { runWhenActive( new Runnable() {
@Override
public void run() { public void run() {
boolean madeGame = false; boolean madeGame = false;
if ( success ) { if ( success ) {

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */ /* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/* /*
* Copyright 2009 - 2014 by Eric House (xwords@eehouse.org). All * Copyright 2009 - 2016 by Eric House (xwords@eehouse.org). All
* rights reserved. * rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -37,6 +37,7 @@ import android.widget.LinearLayout;
import junit.framework.Assert; import junit.framework.Assert;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -54,7 +55,8 @@ public class MainActivity extends XWActivity
private int m_nextID = 0x00FFFFFF; private int m_nextID = 0x00FFFFFF;
private Boolean m_isPortrait; private Boolean m_isPortrait;
private boolean m_safeToCommit; private boolean m_safeToCommit;
private Runnable m_runWhenSafe; private ArrayList<Runnable> m_runWhenSafe = new ArrayList<Runnable>();
private Intent m_newIntent; // work in progress...
// for tracking launchForResult callback recipients // for tracking launchForResult callback recipients
private Map<RequestCode, WeakReference<DelegateBase>> m_pendingCodes private Map<RequestCode, WeakReference<DelegateBase>> m_pendingCodes
@ -64,9 +66,6 @@ public class MainActivity extends XWActivity
protected void onCreate( Bundle savedInstanceState ) protected void onCreate( Bundle savedInstanceState )
{ {
m_dpEnabled = XWPrefs.dualpaneEnabled( this ); m_dpEnabled = XWPrefs.dualpaneEnabled( this );
if ( m_dpEnabled ) {
Utils.showToast( this, R.string.db_enabled_toast );
}
m_dlgt = m_dpEnabled ? new DualpaneDelegate( this, savedInstanceState ) m_dlgt = m_dpEnabled ? new DualpaneDelegate( this, savedInstanceState )
: new GamesListDelegate( this, savedInstanceState ); : new GamesListDelegate( this, savedInstanceState );
@ -141,52 +140,89 @@ public class MainActivity extends XWActivity
super.onConfigurationChanged( newConfig ); super.onConfigurationChanged( newConfig );
} }
/** /* Sometimes I'm getting crashes because views don't have fragments
* Run down the list of fragments until one handles the intent. If no * associated yet. I suspect that's because adding them's been postponed
* visible one does, pop hidden ones into view until one of them * via the m_runWhenSafe mechanism. So: postpone handling intents too.
* does. Yes, this will take us back to GamesList being visible even if *
* nothing handles the intent, but at least now all are handled by * This postponing thing won't scale, and makes me suspect there's
* GamesList anyway. * something I'm doing wrong w.r.t. fragments. Should be revisited. In
* this particular case there might be a better way to get to the Delegate
* on which I need to call handleNewIntent().
*/ */
protected boolean dispatchNewIntent( Intent intent ) protected boolean dispatchNewIntent( final Intent intent )
{
boolean handled;
if ( m_safeToCommit ) {
handled = dispatchNewIntentImpl( intent );
} else {
m_runWhenSafe.add( new Runnable() {
@Override
public void run() {
dispatchNewIntentImpl( intent );
}
} );
if ( BuildConfig.DEBUG ) {
DbgUtils.showf( this, "Putting off handling intent; %d waiting",
m_runWhenSafe.size() );
}
handled = true;
}
return handled;
}
private void popIntoView( XWFragment newTopFrag )
{
FragmentManager fm = getSupportFragmentManager();
for ( ; ; ) {
int top = m_root.getChildCount() - 1;
if ( top < 0 ) {
break;
}
View child = m_root.getChildAt( top );
XWFragment frag = (XWFragment)fm.findFragmentById( child.getId() );
if ( frag == newTopFrag ) {
break;
}
String name = frag.getClass().getSimpleName();
DbgUtils.logdf( "MainActivity.popIntoView(): popping %d: %s", top, name );
fm.popBackStackImmediate();
DbgUtils.logdf( "MainActivity.popIntoView(): DONE popping %s",
name );
}
}
/**
* Run down the list of fragments until one can handle the intent. If
* necessary, pop fragments above it until it comes into view. Then send
* it the event.
*/
private boolean dispatchNewIntentImpl( Intent intent )
{ {
boolean handled = false; boolean handled = false;
FragmentManager fm = getSupportFragmentManager(); FragmentManager fm = getSupportFragmentManager();
// First try non-left-most fragments, if any. Once we've eliminated for ( int ii = m_root.getChildCount() - 1; !handled && ii >= 0; --ii ) {
// them we can just iterate on the leftmost fragment. View child = m_root.getChildAt( ii );
int nNonLeft = m_maxPanes - 1; XWFragment frag = (XWFragment)fm.findFragmentById( child.getId() );
// include paged-to-left invisible views if ( null != frag ) {
int viewCount = m_root.getChildCount(); handled = frag.getDelegate().canHandleNewIntent( intent );
for ( int ii = nNonLeft; !handled && 0 < ii; --ii ) {
View child = m_root.getChildAt( viewCount - ii );
Fragment frag = fm.findFragmentById( child.getId() );
handled = ((XWFragment)frag).getDelegate().handleNewIntent( intent );
}
while ( !handled ) {
// Now iterate on the leftmost, popping if necessary to page new
// ones into place
int childCount = m_root.getChildCount();
int hiddenCount = Math.max( 0, childCount - m_maxPanes );
for ( int ii = hiddenCount; ii >= 0; --ii ) {
View child = m_root.getChildAt( ii );
Fragment frag = fm.findFragmentById( child.getId() );
// DbgUtils.logf( "left-most case (child %d): %s", hiddenCount,
// frag.getClass().getSimpleName() );
handled = ((XWFragment)frag).getDelegate()
.handleNewIntent( intent );
if ( handled ) { if ( handled ) {
break; popIntoView( frag );
} else if ( ii > 0 ) { frag.getDelegate().handleNewIntent( intent );
DbgUtils.logf( "popping %s",
frag.getClass().getSimpleName() );
fm.popBackStackImmediate(); // callback removes view
} }
} else {
DbgUtils.logdf( "no fragment for child %s indx %d",
child.getClass().getSimpleName(), ii );
} }
} }
if ( BuildConfig.DEBUG && !handled ) {
// DbgUtils.showf( this, "dropping intent %s", intent.toString() );
DbgUtils.logdf( "dropping intent %s", intent.toString() );
// DbgUtils.printStack();
// setIntent( intent ); -- look at handling this in onPostResume()?
m_newIntent = intent;
}
return handled; return handled;
} }
@ -335,9 +371,12 @@ public class MainActivity extends XWActivity
private XWFragment getTopFragment() private XWFragment getTopFragment()
{ {
XWFragment frag = null;
View child = m_root.getChildAt( m_root.getChildCount() - 1 ); View child = m_root.getChildAt( m_root.getChildCount() - 1 );
XWFragment frag = (XWFragment)getSupportFragmentManager() if ( null != child ) {
.findFragmentById( child.getId() ); frag = (XWFragment)getSupportFragmentManager()
.findFragmentById( child.getId() );
}
return frag; return frag;
} }
@ -438,15 +477,15 @@ public class MainActivity extends XWActivity
if ( m_safeToCommit ) { if ( m_safeToCommit ) {
safeAddFragment( fragment, parentName ); safeAddFragment( fragment, parentName );
} else { } else {
Assert.assertNull( m_runWhenSafe ); m_runWhenSafe.add( new Runnable() {
m_runWhenSafe = new Runnable() {
@Override @Override
public void run() { public void run() {
safeAddFragment( fragment, parentName ); safeAddFragment( fragment, parentName );
} }
}; } );
if ( BuildConfig.DEBUG ) { if ( BuildConfig.DEBUG ) {
DbgUtils.showf( this, "Putting off fragment construction" ); DbgUtils.showf( this, "Putting off fragment construction; %d waiting",
m_runWhenSafe.size() );
} }
} }
} }
@ -517,9 +556,9 @@ public class MainActivity extends XWActivity
private void setSafeToRun() private void setSafeToRun()
{ {
m_safeToCommit = true; m_safeToCommit = true;
if ( null != m_runWhenSafe ) { for ( Runnable proc : m_runWhenSafe ) {
m_runWhenSafe.run(); proc.run();
m_runWhenSafe = null;
} }
m_runWhenSafe.clear();
} }
} }

View file

@ -163,7 +163,6 @@ public class Toolbar implements BoardContainer.SizeChangeListener {
private void doShowHide() private void doShowHide()
{ {
boolean isPortrait = BoardContainer.getIsPortrait(); boolean isPortrait = BoardContainer.getIsPortrait();
DbgUtils.logdf( "Toolbar.doShowHide(): isPortrait: %b", isPortrait );
if ( null == m_layout ) { if ( null == m_layout ) {
m_layout = (LinearLayout)LocUtils.inflate( m_activity, R.layout.toolbar ); m_layout = (LinearLayout)LocUtils.inflate( m_activity, R.layout.toolbar );

View file

@ -1,6 +1,7 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */ /* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/* /*
* Copyright 2014 by Eric House (xwords@eehouse.org). All rights reserved. * Copyright 2014-2016 by Eric House (xwords@eehouse.org). All rights
* reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@ -85,6 +86,16 @@ public class XWActivity extends FragmentActivity implements Delegator {
m_dlgt.onResume(); m_dlgt.onResume();
} }
@Override
protected void onPostResume()
{
if ( XWApp.LOG_LIFECYLE ) {
DbgUtils.logf( "%s.onPostResume(this=%H)",
getClass().getSimpleName(), this );
}
super.onPostResume();
}
@Override @Override
protected void onStart() protected void onStart()
{ {

View file

@ -50,9 +50,10 @@ public class GameSummary {
public static final int MSG_FLAGS_GAMEOVER = 4; public static final int MSG_FLAGS_GAMEOVER = 4;
public static final int MSG_FLAGS_ALL = 7; public static final int MSG_FLAGS_ALL = 7;
public int lastMoveTime; public int lastMoveTime; // set by jni's server.c on move receipt
public int nMoves; public int nMoves;
public int turn; public int turn;
public boolean turnIsLocal;
public int nPlayers; public int nPlayers;
public int missingPlayers; public int missingPlayers;
public int[] scores; public int[] scores;

View file

@ -8,12 +8,12 @@ declare -A PACKAGES=()
declare -A SERIALS=() declare -A SERIALS=()
INDEX='' INDEX=''
DRYRUN='' DRYRUN=''
ALL='' ALL_DEVS=''
AAPT='' AAPT=''
usage() { usage() {
[ $# -gt 0 ] && echo "ERROR: $1" [ $# -gt 0 ] && echo "ERROR: $1"
echo "usage: $0 [--dry-run] [--help] " echo "usage: $0 [--dry-run] [--help] [--all-devs]"
echo " [--apk <path/to/apk>] # default is to use package names of all known apks" echo " [--apk <path/to/apk>] # default is to use package names of all known apks"
echo " [--pkg-name tld.whatever.more] # explicit package name" echo " [--pkg-name tld.whatever.more] # explicit package name"
echo " [--serial <serial>] # default is to use all attached devices" echo " [--serial <serial>] # default is to use all attached devices"
@ -65,6 +65,9 @@ while [ $# -ge 1 ]; do
--dry-run) --dry-run)
DRYRUN=1 DRYRUN=1
;; ;;
--all-devs)
ALL_DEVS=1
;;
--help) --help)
usage usage
;; ;;
@ -88,6 +91,12 @@ if [ 0 = "${#SERIALS[*]}" ]; then
for DEV in $(adb devices | grep '\sdevice$' | awk '{print $1}'); do for DEV in $(adb devices | grep '\sdevice$' | awk '{print $1}'); do
SERIALS[$DEV]=1 SERIALS[$DEV]=1
done done
if [ 0 = "${#SERIALS[*]}" ]; then
usage "no devices found"
elif [ 1 -lt "${#SERIALS[*]}" -a -z "$ALL_DEVS" ]; then
usage "More than one device found. Be specific, or use --all-devs"
fi
fi fi
for PACKAGE in "${!PACKAGES[@]}"; do for PACKAGE in "${!PACKAGES[@]}"; do

View file

@ -792,7 +792,7 @@ board_canShuffle( const BoardCtxt* board )
XP_Bool XP_Bool
board_canHideRack( const BoardCtxt* board ) board_canHideRack( const BoardCtxt* board )
{ {
XP_Bool result = 0 <= server_getCurrentTurn( board->server ) XP_Bool result = 0 <= server_getCurrentTurn( board->server, NULL )
&& (board->boardObscuresTray || !board->gameOver); && (board->boardObscuresTray || !board->gameOver);
return result; return result;
} }
@ -988,7 +988,7 @@ warnBadWords( const XP_UCHAR* word, XP_Bool isLegal,
if ( !isLegal ) { if ( !isLegal ) {
BadWordInfo bwi = {0}; BadWordInfo bwi = {0};
BoardCtxt* board = (BoardCtxt*)closure; BoardCtxt* board = (BoardCtxt*)closure;
XP_S16 turn = server_getCurrentTurn( board->server ); XP_S16 turn = server_getCurrentTurn( board->server, NULL );
bwi.nWords = 1; bwi.nWords = 1;
bwi.words[0] = word; bwi.words[0] = word;
@ -1019,7 +1019,7 @@ XP_Bool
board_commitTurn( BoardCtxt* board ) board_commitTurn( BoardCtxt* board )
{ {
XP_Bool result = XP_FALSE; XP_Bool result = XP_FALSE;
const XP_S16 turn = server_getCurrentTurn( board->server ); const XP_S16 turn = server_getCurrentTurn( board->server, NULL );
PerTurnInfo* pti = board->pti + turn; PerTurnInfo* pti = board->pti + turn;
if ( board->gameOver || turn < 0 ) { if ( board->gameOver || turn < 0 ) {
@ -1110,15 +1110,15 @@ static void
selectPlayerImpl( BoardCtxt* board, XP_U16 newPlayer, XP_Bool reveal, selectPlayerImpl( BoardCtxt* board, XP_U16 newPlayer, XP_Bool reveal,
XP_Bool canPeek ) XP_Bool canPeek )
{ {
XP_S16 curTurn = server_getCurrentTurn(board->server); XP_Bool isLocal;
XP_S16 curTurn = server_getCurrentTurn( board->server, &isLocal );
if ( !board->gameOver && curTurn < 0 ) { if ( !board->gameOver && curTurn < 0 ) {
/* game not started yet; do nothing */ /* game not started yet; do nothing */
} else if ( board->selPlayer == newPlayer ) { } else if ( board->selPlayer == newPlayer ) {
if ( reveal ) { if ( reveal ) {
checkRevealTray( board ); checkRevealTray( board );
} }
} else if ( canPeek || ((newPlayer == curTurn) } else if ( canPeek || ((newPlayer == curTurn) && isLocal)) {
&& LP_IS_LOCAL( &board->gi->players[newPlayer]))) {
PerTurnInfo* newInfo = &board->pti[newPlayer]; PerTurnInfo* newInfo = &board->pti[newPlayer];
XP_U16 oldPlayer = board->selPlayer; XP_U16 oldPlayer = board->selPlayer;
model_foreachPendingCell( board->model, newPlayer, model_foreachPendingCell( board->model, newPlayer,
@ -1318,7 +1318,7 @@ timerFiredForTimer( BoardCtxt* board )
{ {
board->timerPending = XP_FALSE; board->timerPending = XP_FALSE;
if ( !board->gameOver ) { if ( !board->gameOver ) {
XP_S16 turn = server_getCurrentTurn( board->server ); XP_S16 turn = server_getCurrentTurn( board->server, NULL );
if ( turn >= 0 ) { if ( turn >= 0 ) {
++board->gi->players[turn].secondsUsed; ++board->gi->players[turn].secondsUsed;
@ -1365,7 +1365,8 @@ board_pushTimerSave( BoardCtxt* board )
if ( board->timerSaveCount++ == 0 ) { if ( board->timerSaveCount++ == 0 ) {
board->timerStoppedTime = util_getCurSeconds( board->util ); board->timerStoppedTime = util_getCurSeconds( board->util );
#ifdef DEBUG #ifdef DEBUG
board->timerStoppedTurn = server_getCurrentTurn( board->server ); board->timerStoppedTurn = server_getCurrentTurn( board->server,
NULL );
#endif #endif
} }
} }
@ -1380,7 +1381,7 @@ board_popTimerSave( BoardCtxt* board )
between calls to board_pushTimerSave and this call, as can happen on between calls to board_pushTimerSave and this call, as can happen on
franklin. So that's not an error. */ franklin. So that's not an error. */
if ( board->timerSaveCount > 0 ) { if ( board->timerSaveCount > 0 ) {
XP_S16 turn = server_getCurrentTurn( board->server ); XP_S16 turn = server_getCurrentTurn( board->server, NULL );
XP_ASSERT( board->timerStoppedTurn == turn ); XP_ASSERT( board->timerStoppedTurn == turn );
@ -1769,7 +1770,7 @@ chooseBestSelPlayer( BoardCtxt* board )
return board->selPlayer; return board->selPlayer;
} else { } else {
XP_S16 curTurn = server_getCurrentTurn( server ); XP_S16 curTurn = server_getCurrentTurn( server, NULL );
if ( curTurn >= 0 ) { if ( curTurn >= 0 ) {
XP_U16 nPlayers = board->gi->nPlayers; XP_U16 nPlayers = board->gi->nPlayers;
@ -2001,7 +2002,7 @@ static XP_Bool
preflight( BoardCtxt* board, XP_Bool reveal ) preflight( BoardCtxt* board, XP_Bool reveal )
{ {
return !board->gameOver return !board->gameOver
&& server_getCurrentTurn(board->server) >= 0 && server_getCurrentTurn(board->server, NULL) >= 0
&& ( !reveal || checkRevealTray( board ) ) && ( !reveal || checkRevealTray( board ) )
&& !TRADE_IN_PROGRESS(board); && !TRADE_IN_PROGRESS(board);
} /* preflight */ } /* preflight */
@ -2581,7 +2582,7 @@ askRevealTray( BoardCtxt* board )
if ( board->gameOver ) { if ( board->gameOver ) {
revealed = XP_TRUE; revealed = XP_TRUE;
} else if ( server_getCurrentTurn( board->server ) < 0 ) { } else if ( server_getCurrentTurn( board->server, NULL ) < 0 ) {
revealed = XP_FALSE; revealed = XP_FALSE;
#ifndef XWFEATURE_STANDALONE_ONLY #ifndef XWFEATURE_STANDALONE_ONLY
} else if ( !lp->isLocal ) { } else if ( !lp->isLocal ) {

View file

@ -240,7 +240,7 @@ struct BoardCtxt {
# define valHintMiniWindowActive( board ) \ # define valHintMiniWindowActive( board ) \
((XP_Bool)((board)->miniWindowStuff[MINIWINDOW_VALHINT].text != NULL)) ((XP_Bool)((board)->miniWindowStuff[MINIWINDOW_VALHINT].text != NULL))
#endif #endif
#define MY_TURN(b) ((b)->selPlayer == server_getCurrentTurn( (b)->server )) #define MY_TURN(b) ((b)->selPlayer == server_getCurrentTurn( (b)->server, NULL ))
#define TRADE_IN_PROGRESS(b) ((b)->selInfo->tradeInProgress==XP_TRUE) #define TRADE_IN_PROGRESS(b) ((b)->selInfo->tradeInProgress==XP_TRUE)
/* tray-related functions */ /* tray-related functions */

View file

@ -176,7 +176,7 @@ drawScoreBoard( BoardCtxt* board )
XP_ASSERT( nPlayers <= MAX_NUM_PLAYERS ); XP_ASSERT( nPlayers <= MAX_NUM_PLAYERS );
if ( nPlayers > 0 ) { if ( nPlayers > 0 ) {
ModelCtxt* model = board->model; ModelCtxt* model = board->model;
XP_S16 curTurn = server_getCurrentTurn( board->server ); XP_S16 curTurn = server_getCurrentTurn( board->server, NULL );
XP_U16 selPlayer = board->selPlayer; XP_U16 selPlayer = board->selPlayer;
XP_S16 nTilesInPool = server_countTilesInPool( board->server ); XP_S16 nTilesInPool = server_countTilesInPool( board->server );
XP_Rect scoreRect = board->scoreBdBounds; XP_Rect scoreRect = board->scoreBdBounds;

View file

@ -2435,9 +2435,13 @@ server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles )
} /* server_commitTrade */ } /* server_commitTrade */
XP_S16 XP_S16
server_getCurrentTurn( ServerCtxt* server ) server_getCurrentTurn( ServerCtxt* server, XP_Bool* isLocal )
{ {
return server->nv.currentTurn; XP_S16 turn = server->nv.currentTurn;
if ( NULL != isLocal && turn >= 0 ) {
*isLocal = server->vol.gi->players[turn].isLocal;
}
return turn;
} /* server_getCurrentTurn */ } /* server_getCurrentTurn */
XP_Bool XP_Bool

View file

@ -94,7 +94,7 @@ XP_U16 server_secondsUsedBy( ServerCtxt* server, XP_U16 playerNum );
XP_Bool server_handleUndo( ServerCtxt* server, XP_U16 limit ); XP_Bool server_handleUndo( ServerCtxt* server, XP_U16 limit );
/* signed because negative number means nobody's turn yet */ /* signed because negative number means nobody's turn yet */
XP_S16 server_getCurrentTurn( ServerCtxt* server ); XP_S16 server_getCurrentTurn( ServerCtxt* server, XP_Bool* isLocal );
XP_Bool server_getGameIsOver( ServerCtxt* server ); XP_Bool server_getGameIsOver( ServerCtxt* server );
/* return bitvector marking players still not arrived in networked game */ /* return bitvector marking players still not arrived in networked game */
XP_U16 server_getMissingPlayers( const ServerCtxt* server ); XP_U16 server_getMissingPlayers( const ServerCtxt* server );

View file

@ -339,7 +339,7 @@ drawPendingScore( BoardCtxt* board, XP_S16 turnScore, XP_Bool hasCursor )
/* Draw the pending score down in the last tray's rect */ /* Draw the pending score down in the last tray's rect */
if ( countTilesToShow( board ) < MAX_TRAY_TILES ) { if ( countTilesToShow( board ) < MAX_TRAY_TILES ) {
XP_U16 selPlayer = board->selPlayer; XP_U16 selPlayer = board->selPlayer;
XP_S16 curTurn = server_getCurrentTurn( board->server ); XP_S16 curTurn = server_getCurrentTurn( board->server, NULL );
XP_Rect lastTileR; XP_Rect lastTileR;
figureTrayTileRect( board, MAX_TRAY_TILES-1, &lastTileR ); figureTrayTileRect( board, MAX_TRAY_TILES-1, &lastTileR );

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */ /* -*- compile-command: "make MEMDEBUG=TRUE -j5"; -*- */
/* /*
* Copyright 2000-2013 by Eric House (xwords@eehouse.org). All rights * Copyright 2000 - 2016 by Eric House (xwords@eehouse.org). All rights
* reserved. * reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -54,6 +54,7 @@ openGamesDB( const char* dbName )
",connvia VARCHAR(32)" ",connvia VARCHAR(32)"
",ended INT(1)" ",ended INT(1)"
",turn INT(2)" ",turn INT(2)"
",local INT(1)"
",nmoves INT" ",nmoves INT"
",seed INT" ",seed INT"
",gameid INT" ",gameid INT"
@ -197,7 +198,8 @@ summarize( CommonGlobals* cGlobals )
{ {
XP_S16 nMoves = model_getNMoves( cGlobals->game.model ); XP_S16 nMoves = model_getNMoves( cGlobals->game.model );
XP_Bool gameOver = server_getGameIsOver( cGlobals->game.server ); XP_Bool gameOver = server_getGameIsOver( cGlobals->game.server );
XP_S16 turn = server_getCurrentTurn( cGlobals->game.server ); XP_Bool isLocal;
XP_S16 turn = server_getCurrentTurn( cGlobals->game.server, &isLocal );
XP_U32 lastMoveTime = server_getLastMoveTime( cGlobals->game.server ); XP_U32 lastMoveTime = server_getLastMoveTime( cGlobals->game.server );
XP_U16 seed = 0; XP_U16 seed = 0;
XP_S16 nMissing = 0; XP_S16 nMissing = 0;
@ -243,12 +245,13 @@ summarize( CommonGlobals* cGlobals )
} }
const char* fmt = "UPDATE games " const char* fmt = "UPDATE games "
" SET room='%s', ended=%d, turn=%d, ntotal=%d, nmissing=%d, nmoves=%d, seed=%d, " " SET room='%s', ended=%d, turn=%d, local=%d, ntotal=%d, nmissing=%d, "
" gameid=%d, connvia='%s', lastMoveTime=%d" " nmoves=%d, seed=%d, gameid=%d, connvia='%s', lastMoveTime=%d"
" WHERE rowid=%lld"; " WHERE rowid=%lld";
XP_UCHAR buf[256]; XP_UCHAR buf[256];
snprintf( buf, sizeof(buf), fmt, room, gameOver?1:0, turn, nTotal, nMissing, snprintf( buf, sizeof(buf), fmt, room, gameOver?1:0, turn, isLocal?1:0,
nMoves, seed, gameID, connvia, lastMoveTime, cGlobals->selRow ); nTotal, nMissing, nMoves, seed, gameID, connvia, lastMoveTime,
cGlobals->selRow );
XP_LOGF( "query: %s", buf ); XP_LOGF( "query: %s", buf );
sqlite3_stmt* stmt = NULL; sqlite3_stmt* stmt = NULL;
int result = sqlite3_prepare_v2( cGlobals->pDb, buf, -1, &stmt, NULL ); int result = sqlite3_prepare_v2( cGlobals->pDb, buf, -1, &stmt, NULL );
@ -301,7 +304,7 @@ XP_Bool
getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib ) getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
{ {
XP_Bool success = XP_FALSE; XP_Bool success = XP_FALSE;
const char* fmt = "SELECT room, ended, turn, nmoves, ntotal, nmissing, " const char* fmt = "SELECT room, ended, turn, local, nmoves, ntotal, nmissing, "
"seed, connvia, gameid, lastMoveTime, snap " "seed, connvia, gameid, lastMoveTime, snap "
"FROM games WHERE rowid = %lld"; "FROM games WHERE rowid = %lld";
XP_UCHAR query[256]; XP_UCHAR query[256];
@ -316,20 +319,21 @@ getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
getColumnText( ppStmt, 0, gib->room, sizeof(gib->room) ); getColumnText( ppStmt, 0, gib->room, sizeof(gib->room) );
gib->gameOver = 1 == sqlite3_column_int( ppStmt, 1 ); gib->gameOver = 1 == sqlite3_column_int( ppStmt, 1 );
gib->turn = sqlite3_column_int( ppStmt, 2 ); gib->turn = sqlite3_column_int( ppStmt, 2 );
gib->nMoves = sqlite3_column_int( ppStmt, 3 ); gib->turnLocal = 1 == sqlite3_column_int( ppStmt, 3 );
gib->nTotal = sqlite3_column_int( ppStmt, 4 ); gib->nMoves = sqlite3_column_int( ppStmt, 4 );
gib->nMissing = sqlite3_column_int( ppStmt, 5 ); gib->nTotal = sqlite3_column_int( ppStmt, 5 );
gib->seed = sqlite3_column_int( ppStmt, 6 ); gib->nMissing = sqlite3_column_int( ppStmt, 6 );
getColumnText( ppStmt, 7, gib->conn, sizeof(gib->conn) ); gib->seed = sqlite3_column_int( ppStmt, 7 );
gib->gameID = sqlite3_column_int( ppStmt, 8 ); getColumnText( ppStmt, 8, gib->conn, sizeof(gib->conn) );
gib->lastMoveTime = sqlite3_column_int( ppStmt, 9 ); gib->gameID = sqlite3_column_int( ppStmt, 9 );
gib->lastMoveTime = sqlite3_column_int( ppStmt, 10 );
snprintf( gib->name, sizeof(gib->name), "Game %lld", rowid ); snprintf( gib->name, sizeof(gib->name), "Game %lld", rowid );
/* Load the snapshot */ /* Load the snapshot */
GdkPixbuf* snap = NULL; GdkPixbuf* snap = NULL;
const XP_U8* ptr = sqlite3_column_blob( ppStmt, 10 ); const XP_U8* ptr = sqlite3_column_blob( ppStmt, 11 );
if ( !!ptr ) { if ( !!ptr ) {
int size = sqlite3_column_bytes( ppStmt, 10 ); int size = sqlite3_column_bytes( ppStmt, 11 );
/* Skip the version that's written in */ /* Skip the version that's written in */
ptr += sizeof(XP_U16); size -= sizeof(XP_U16); ptr += sizeof(XP_U16); size -= sizeof(XP_U16);
GInputStream* istr = g_memory_input_stream_new_from_data( ptr, size, NULL ); GInputStream* istr = g_memory_input_stream_new_from_data( ptr, size, NULL );

View file

@ -1,6 +1,6 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE -j3"; -*- */ /* -*- compile-command: "make MEMDEBUG=TRUE -j5"; -*- */
/* /*
* Copyright 2000-2012 by Eric House (xwords@eehouse.org). All rights * Copyright 2000 - 2016 by Eric House (xwords@eehouse.org). All rights
* reserved. * reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -35,6 +35,7 @@ typedef struct _GameInfo {
XP_U32 gameID; XP_U32 gameID;
XP_S16 nMoves; XP_S16 nMoves;
XP_Bool gameOver; XP_Bool gameOver;
XP_Bool turnLocal;
XP_S16 turn; XP_S16 turn;
XP_U16 nTotal; XP_U16 nTotal;
XP_S16 nMissing; XP_S16 nMissing;

View file

@ -2695,7 +2695,7 @@ initGlobals( GtkGameGlobals* globals, LaunchParams* params, CurGameInfo* gi )
g_signal_connect( globals->adjustment, "value_changed", g_signal_connect( globals->adjustment, "value_changed",
G_CALLBACK(scroll_value_changed), globals ); G_CALLBACK(scroll_value_changed), globals );
gtk_widget_show( vscrollbar ); gtk_widget_show( vscrollbar );
gtk_box_pack_start( GTK_BOX(hbox), vscrollbar, TRUE, TRUE, 0 ); gtk_box_pack_start( GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0 );
gtk_box_pack_start( GTK_BOX (hbox), gtk_box_pack_start( GTK_BOX (hbox),
makeVerticalBar( globals, window ), makeVerticalBar( globals, window ),

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */ /* -*- compile-command: "make MEMDEBUG=TRUE -j5"; -*- */
/* /*
* Copyright 2000-2013 by Eric House (xwords@eehouse.org). All rights * Copyright 2000 - 2016 by Eric House (xwords@eehouse.org). All rights
* reserved. * reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -76,8 +76,8 @@ findOpenGame( const GtkAppGlobals* apg, sqlite3_int64 rowid )
} }
enum { ROW_ITEM, ROW_THUMB, NAME_ITEM, ROOM_ITEM, GAMEID_ITEM, SEED_ITEM, enum { ROW_ITEM, ROW_THUMB, NAME_ITEM, ROOM_ITEM, GAMEID_ITEM, SEED_ITEM,
CONN_ITEM, OVER_ITEM, TURN_ITEM, NMOVES_ITEM, NTOTAL_ITEM, MISSING_ITEM, CONN_ITEM, OVER_ITEM, TURN_ITEM, LOCAL_ITEM, NMOVES_ITEM, NTOTAL_ITEM,
LASTTURN_ITEM, N_ITEMS }; MISSING_ITEM, LASTTURN_ITEM, N_ITEMS };
static void static void
foreachProc( GtkTreeModel* model, GtkTreePath* XP_UNUSED(path), foreachProc( GtkTreeModel* model, GtkTreePath* XP_UNUSED(path),
@ -169,6 +169,7 @@ init_games_list( GtkAppGlobals* apg )
addTextColumn( list, "Conn. via", CONN_ITEM ); addTextColumn( list, "Conn. via", CONN_ITEM );
addTextColumn( list, "Ended", OVER_ITEM ); addTextColumn( list, "Ended", OVER_ITEM );
addTextColumn( list, "Turn", TURN_ITEM ); addTextColumn( list, "Turn", TURN_ITEM );
addTextColumn( list, "Local", LOCAL_ITEM );
addTextColumn( list, "NMoves", NMOVES_ITEM ); addTextColumn( list, "NMoves", NMOVES_ITEM );
addTextColumn( list, "NTotal", NTOTAL_ITEM ); addTextColumn( list, "NTotal", NTOTAL_ITEM );
addTextColumn( list, "NMissing", MISSING_ITEM ); addTextColumn( list, "NMissing", MISSING_ITEM );
@ -184,10 +185,11 @@ init_games_list( GtkAppGlobals* apg )
G_TYPE_STRING, /* CONN_ITEM */ G_TYPE_STRING, /* CONN_ITEM */
G_TYPE_BOOLEAN, /* OVER_ITEM */ G_TYPE_BOOLEAN, /* OVER_ITEM */
G_TYPE_INT, /* TURN_ITEM */ G_TYPE_INT, /* TURN_ITEM */
G_TYPE_STRING, /* LOCAL_ITEM */
G_TYPE_INT, /* NMOVES_ITEM */ G_TYPE_INT, /* NMOVES_ITEM */
G_TYPE_INT, /* NTOTAL_ITEM */ G_TYPE_INT, /* NTOTAL_ITEM */
G_TYPE_INT, /* MISSING_ITEM */ G_TYPE_INT, /* MISSING_ITEM */
G_TYPE_INT /* LASTTURN_ITEM */ G_TYPE_STRING /* LASTTURN_ITEM */
); );
gtk_tree_view_set_model( GTK_TREE_VIEW(list), GTK_TREE_MODEL(store) ); gtk_tree_view_set_model( GTK_TREE_VIEW(list), GTK_TREE_MODEL(store) );
g_object_unref( store ); g_object_unref( store );
@ -224,6 +226,11 @@ add_to_list( GtkWidget* list, sqlite3_int64 rowid, XP_Bool isNew,
} }
} }
} }
gchar* localString = 0 <= gib->turn ? gib->turnLocal ? "YES"
: "NO" : "";
GTimeVal timeval = { tv_sec: gib->lastMoveTime, tv_usec: 0 };
gchar* timeStr = g_time_val_to_iso8601( &timeval );
gtk_list_store_set( store, &iter, gtk_list_store_set( store, &iter,
ROW_ITEM, rowid, ROW_ITEM, rowid,
ROW_THUMB, gib->snap, ROW_THUMB, gib->snap,
@ -232,13 +239,15 @@ add_to_list( GtkWidget* list, sqlite3_int64 rowid, XP_Bool isNew,
GAMEID_ITEM, gib->gameID, GAMEID_ITEM, gib->gameID,
SEED_ITEM, gib->seed, SEED_ITEM, gib->seed,
CONN_ITEM, gib->conn, CONN_ITEM, gib->conn,
OVER_ITEM, gib->gameOver,
TURN_ITEM, gib->turn, TURN_ITEM, gib->turn,
OVER_ITEM, gib->gameOver,
LOCAL_ITEM, localString,
NMOVES_ITEM, gib->nMoves, NMOVES_ITEM, gib->nMoves,
NTOTAL_ITEM, gib->nTotal, NTOTAL_ITEM, gib->nTotal,
MISSING_ITEM, gib->nMissing, MISSING_ITEM, gib->nMissing,
LASTTURN_ITEM, gib->lastMoveTime, LASTTURN_ITEM, timeStr,
-1 ); -1 );
g_free( timeStr );
XP_LOGF( "DONE adding" ); XP_LOGF( "DONE adding" );
} }
@ -483,14 +492,18 @@ setWindowTitle( GtkAppGlobals* apg )
static void static void
trySetWinConfig( GtkAppGlobals* apg ) trySetWinConfig( GtkAppGlobals* apg )
{ {
int xx = 20; /* defaults */
int yy = 20;
int width = 600;
int height = 400;
gchar buf[64]; gchar buf[64];
if ( db_fetch( apg->params->pDb, KEY_WIN_LOC, buf, sizeof(buf)) ) { if ( db_fetch( apg->params->pDb, KEY_WIN_LOC, buf, sizeof(buf)) ) {
int xx, yy, width, height;
sscanf( buf, "%d:%d:%d:%d", &xx, &yy, &width, &height ); sscanf( buf, "%d:%d:%d:%d", &xx, &yy, &width, &height );
gtk_window_resize( GTK_WINDOW(apg->window), width, height );
gtk_window_move (GTK_WINDOW(apg->window), xx, yy );
} }
gtk_window_resize( GTK_WINDOW(apg->window), width, height );
gtk_window_move (GTK_WINDOW(apg->window), xx, yy );
} }
static void static void