Merge branch 'android_branch' into android_translate

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
This commit is contained in:
Eric House 2016-07-29 08:51:16 -07:00
commit 1addd34e95
167 changed files with 4659 additions and 3829 deletions

1
.gitignore vendored
View file

@ -8,3 +8,4 @@ core*
xwords_4.4.0.0* xwords_4.4.0.0*
gcm_loop.shelf gcm_loop.shelf
nohup.out nohup.out
/xwords4/android/XWords4-dbg/src/xw4dbg/assets/gitvers.txt

View file

@ -57,7 +57,7 @@
android:debuggable="false" android:debuggable="false"
> >
<activity android:name="GamesListActivity" <activity android:name="MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="standard" android:launchMode="standard"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"

View file

@ -63,7 +63,7 @@
<antcall target="my-pre-clean" /> <antcall target="my-pre-clean" />
</target> </target>
<target name="-pre-build" depends="my-copy-src"> <target name="-pre-build" depends="my-copy-src, my-check-props">
<antcall target="my-pre-build"> <antcall target="my-pre-build">
<param name="VARIANT_NAME" value="${VARIANT_NAME}"/> <param name="VARIANT_NAME" value="${VARIANT_NAME}"/>
<param name="APP_NAME" value="${APP_NAME}"/> <param name="APP_NAME" value="${APP_NAME}"/>

View file

@ -0,0 +1 @@
values-??/strings.xml

View file

@ -47,3 +47,4 @@ toolbar.xml
chat_row.xml chat_row.xml
fragact.xml fragact.xml
main.xml main.xml
dualcontainer.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -86,7 +86,6 @@ XWSumListPreference.java
XWThumbListPreference.java XWThumbListPreference.java
DelegateBase.java DelegateBase.java
DlgID.java DlgID.java
GamesListActivity.java
GamesListDelegate.java GamesListDelegate.java
LookupAlert.java LookupAlert.java
BoardDelegate.java BoardDelegate.java
@ -137,3 +136,6 @@ StudyListFrag.java
XWFragment.java XWFragment.java
ConfirmingCheckBoxPreference.java ConfirmingCheckBoxPreference.java
RelayCheckBoxPreference.java RelayCheckBoxPreference.java
MainActivity.java
DictsFrag.java
DualpaneDelegate.java

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="101" android:versionCode="103"
android:versionName="@string/app_version" android:versionName="@string/app_version"
> >
@ -69,7 +69,7 @@
android:name=".XWApp" android:name=".XWApp"
> >
<activity android:name="GamesListActivity" <activity android:name="MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="standard" android:launchMode="standard"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"

View file

@ -134,7 +134,7 @@ dependencies {
task genVers(type: Exec) { task genVers(type: Exec) {
workingDir '../' workingDir '../'
commandLine '../scripts/genvers.sh', '--variant', VARIANT_NAME, commandLine '../scripts/genvers.sh', '--variant', VARIANT_NAME,
'--client-vers', INITIAL_CLIENT_VERS, '--chat-enabled', CHAT_ENABLED, '--client-vers', INITIAL_CLIENT_VERS,
'--thumbnail-enabled', THUMBNAIL_ENABLED, '--thumbnail-enabled', THUMBNAIL_ENABLED,
'--vers-outfile', "assets/gitvers.txt" '--vers-outfile', "assets/gitvers.txt"
} }

File diff suppressed because it is too large Load diff

View file

@ -13,10 +13,10 @@
</style> </style>
</head> </head>
<body> <body>
<h2>Crosswords 4.4.107 release</h2> <h2>Crosswords 4.4.108 release</h2>
<p>This version, for F-droid release only, fixes build problems that <p>This release fixes a nasty bug in invitations on older Android
caused a number of crashes and other issues.</p> and improves in-game chat functionality.</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
@ -26,7 +26,18 @@
<h3>New with this release</h3> <h3>New with this release</h3>
<ul> <ul>
<li>Force release builds to be done with ant rather than gradle</li> <li>Fix problem with invitations on older Android versions
(e.g. 4.2 and 4.3)</li>
<li>Chat fixes: send without closing the window, expand for
longer messages, smart editing, etc.</li>
<li>Fix so Bluetooth finds tablets as well as phones</li>
<li>Add ability to disable relay play (to save battery for users
who play standalone only)</li>
<li>Improvements to French and Japanese translations</li>
</ul> </ul>
<p>(The full changelog <p>(The full changelog
@ -34,8 +45,8 @@
<h3>Next up</h3> <h3>Next up</h3>
<ul> <ul>
<li>More chat improvements, especially allowing to send and <li>Working on dual-pane mode (so e.g. board and chat can be
receive without closing the chat window</li> side-by-side on tablets)</li>
<li>Take advantage of Marshmallow's new permissions model (where <li>Take advantage of Marshmallow's new permissions model (where
the app only asks for them when it needs them.) the app only asks for them when it needs them.)
</ul> </ul>

View file

@ -5,7 +5,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.1.0' classpath 'com.android.tools.build:gradle:2.1.2'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View file

@ -58,12 +58,13 @@
<property name="INITIAL_CLIENT_VERS" value="8"/> <property name="INITIAL_CLIENT_VERS" value="8"/>
<property name="VARIANT_NAME" value="xw4"/> <property name="VARIANT_NAME" value="xw4"/>
<property name="APP_NAME" value="Crosswords"/> <property name="APP_NAME" value="Crosswords"/>
<property name="SKIP_LANGS" value="values-de"/>
<target name="-pre-clean"> <target name="-pre-clean">
<antcall target="my-pre-clean" /> <antcall target="my-pre-clean" />
</target> </target>
<target name="-pre-build" depends="my-copy-src"> <target name="-pre-build" depends="my-copy-src, my-check-props">
<antcall target="my-pre-build"> <antcall target="my-pre-build">
<param name="VARIANT_NAME" value="${VARIANT_NAME}"/> <param name="VARIANT_NAME" value="${VARIANT_NAME}"/>
<param name="APP_NAME" value="${APP_NAME}"/> <param name="APP_NAME" value="${APP_NAME}"/>

View file

@ -38,6 +38,7 @@ LOCAL_DEFINES += \
-DHASH_STREAM \ -DHASH_STREAM \
-DXWFEATURE_BASE64 \ -DXWFEATURE_BASE64 \
-DXWFEATURE_DEVID \ -DXWFEATURE_DEVID \
-DXWFEATURE_CHAT \
-DCOMMON_LAYOUT \ -DCOMMON_LAYOUT \
-DNATIVE_NLI \ -DNATIVE_NLI \
-DCOMMS_VERSION=1 \ -DCOMMS_VERSION=1 \
@ -46,10 +47,6 @@ LOCAL_DEFINES += \
-DRELAY_ROOM_DEFAULT=\"\" \ -DRELAY_ROOM_DEFAULT=\"\" \
-D__LITTLE_ENDIAN \ -D__LITTLE_ENDIAN \
ifeq ($(CHAT_ENABLED),true)
LOCAL_DEFINES += -DXWFEATURE_CHAT
endif
# -DXWFEATURE_SCOREONEPASS \ # -DXWFEATURE_SCOREONEPASS \
LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += \

View file

@ -62,6 +62,8 @@ typedef struct _JNIGlobalState {
MPSLOT MPSLOT
} JNIGlobalState; } JNIGlobalState;
// #define LOG_MAPPING
#define GAMEPTR_IS_OBJECT #define GAMEPTR_IS_OBJECT
#ifdef GAMEPTR_IS_OBJECT #ifdef GAMEPTR_IS_OBJECT
typedef jobject GamePtrType; typedef jobject GamePtrType;
@ -69,6 +71,22 @@ typedef jobject GamePtrType;
typedef int GamePtrType; typedef int GamePtrType;
#endif #endif
#ifdef LOG_MAPPING
static int
countUsed(const EnvThreadInfo* ti)
{
int count = 0;
for ( int ii = 0; ii < ti->nEntries; ++ii ) {
EnvThreadEntry* entry = &ti->entries[ii];
if ( 0 != entry->owner ) {
XP_LOGF( "%s(): ii=%d; owner: %x", __func__, ii, (unsigned int)entry->owner );
++count;
}
}
return count;
}
#endif
static void static void
map_thread( EnvThreadInfo* ti, JNIEnv* env ) map_thread( EnvThreadInfo* ti, JNIEnv* env )
{ {
@ -100,17 +118,20 @@ map_thread( EnvThreadInfo* ti, JNIEnv* env )
if ( !firstEmpty ) { /* out of slots */ if ( !firstEmpty ) { /* out of slots */
if ( 0 == nEntries ) { /* first time */ if ( 0 == nEntries ) { /* first time */
nEntries = 2; nEntries = 2;
ti->entries = XP_ASSERT( !ti->entries );
XP_MALLOC( ti->mpool, nEntries * sizeof(*ti->entries) );
} else { } else {
nEntries *= 2; nEntries *= 2;
ti->entries = XP_REALLOC( ti->mpool, ti->entries,
nEntries * sizeof(*ti->entries) );
} }
// XP_LOGF( "%s: num env entries now %d", __func__, nEntries ); EnvThreadEntry* entries = XP_CALLOC( ti->mpool, nEntries * sizeof(*entries) );
firstEmpty = &ti->entries[ti->nEntries]; /* first new entry */ if ( !!ti->entries ) {
XP_MEMSET( firstEmpty, 0, nEntries - ti->nEntries ); XP_MEMCPY( entries, ti->entries, ti->nEntries * sizeof(*ti->entries) );
}
firstEmpty = &entries[ti->nEntries]; /* first new entry */
ti->entries = entries;
ti->nEntries = nEntries; ti->nEntries = nEntries;
#ifdef LOG_MAPPING
XP_LOGF( "%s: num env entries now %d", __func__, nEntries );
#endif
} }
XP_ASSERT( !!firstEmpty ); XP_ASSERT( !!firstEmpty );
@ -119,6 +140,7 @@ map_thread( EnvThreadInfo* ti, JNIEnv* env )
#ifdef LOG_MAPPING #ifdef LOG_MAPPING
XP_LOGF( "%s: entry %d: mapped env %p to thread %x", __func__, XP_LOGF( "%s: entry %d: mapped env %p to thread %x", __func__,
firstEmpty - ti->entries, env, (int)self ); firstEmpty - ti->entries, env, (int)self );
XP_LOGF( "%s: num entries USED now %d", __func__, countUsed(ti) );
#endif #endif
} }
@ -150,6 +172,9 @@ map_remove( EnvThreadInfo* ti, JNIEnv* env )
#endif #endif
ti->entries[ii].env = NULL; ti->entries[ii].env = NULL;
ti->entries[ii].owner = 0; ti->entries[ii].owner = 0;
#ifdef LOG_MAPPING
XP_LOGF( "%s: %d entries left", __func__, countUsed( ti ) );
#endif
} }
} }
pthread_mutex_unlock( &ti->mtxThreads ); pthread_mutex_unlock( &ti->mtxThreads );
@ -1261,6 +1286,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_server_1do
{ {
jboolean result; jboolean result;
XWJNI_START(); XWJNI_START();
XP_ASSERT( !!state->game.server );
result = server_do( state->game.server ); result = server_do( state->game.server );
XWJNI_END(); XWJNI_END();
return result; return result;

View file

@ -0,0 +1 @@
values-??/strings.xml

View file

@ -21,14 +21,26 @@
</ScrollView> </ScrollView>
<EditText android:id="@+id/chat_edit" <LinearLayout
android:layout_width="fill_parent" android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<EditText android:id="@+id/chat_edit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="false"
android:inputType="textCapSentences|textMultiLine"
android:layout_weight="1"
android:scrollHorizontally="false"
android:hint="@string/chat_hint"
/>
<Button android:id="@+id/chat_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:singleLine="false" android:text="@string/chat_send"
android:inputType="textCapSentences|textMultiLine" android:layout_gravity="center_vertical"
android:layout_weight="0"
android:scrollHorizontally="false"
android:hint="@string/chat_hint"
/> />
</LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1,2 +0,0 @@
/strings.xml
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

View file

@ -1 +0,0 @@
strings.xml

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.107</string> <string name="app_version">4.4.108</string>
</resources> </resources>

View file

@ -67,7 +67,7 @@
<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>
<string name="key_force_tablet">key_force_tablet</string> <string name="key_force_tablet">key_force_tablet</string>
<!-- <string name="key_enable_dualpane">key_enable_dualpane</string> --> <string name="key_enable_dualpane">key_enable_dualpane</string>
<string name="key_force_radio">key_force_radio</string> <string name="key_force_radio">key_force_radio</string>
<string name="key_addrs_pref">key_addrs_pref</string> <string name="key_addrs_pref">key_addrs_pref</string>

View file

@ -1095,7 +1095,8 @@
tapping. --> tapping. -->
<string name="hide_crosshairs">Disable crosshairs</string> <string name="hide_crosshairs">Disable crosshairs</string>
<!-- explanation of the above --> <!-- explanation of the above -->
<string name="hide_crosshairs_summary">Do not visually indicate which board cell is touched</string> <string name="hide_crosshairs_summary">Do not show which board
cell is touched</string>
<string name="network_behavior">Network game settings</string> <string name="network_behavior">Network game settings</string>
<!-- explanation of the above --> <!-- explanation of the above -->
@ -2396,8 +2397,8 @@
<string name="force_tablet_title">Force tablet layout</string> <string name="force_tablet_title">Force tablet layout</string>
<string name="force_tablet_summary">Even if my screen is too small</string> <string name="force_tablet_summary">Even if my screen is too small</string>
<!-- <string name="enable_dualpane_title">Enable dualpane</string> --> <string name="enable_dualpane_title">Enable dualpane</string>
<!-- <string name="enable_dualpane_summary">Side-by-side views, very experimental!</string> --> <string name="enable_dualpane_summary">Side-by-side views, very experimental!</string>
<!-- Nagging: title of notification reminder message --> <!-- Nagging: title of notification reminder message -->
<string name="nag_title">Reminder: It\'s your turn</string> <string name="nag_title">Reminder: It\'s your turn</string>
@ -2596,7 +2597,7 @@
<string name="pref_group_relay_title">Relay Stuff</string> <string name="pref_group_relay_title">Relay Stuff</string>
<string name="pref_group_relay_summary">Prefs related to play via internet/relay</string> <string name="pref_group_relay_summary">Prefs related to play via internet/relay</string>
<string name="pref_group_l10n_title">Localization Stuff</string> <string name="pref_group_l10n_title">Localization Stuff</string>
<!-- <string name="pref_group_tablets_title">Tablets Stuff</string> --> <string name="pref_group_tablets_title">Tablets Stuff</string>
<string name="pref_group_l10n_summary">Prefs related to in-app localization</string> <string name="pref_group_l10n_summary">Prefs related to in-app localization</string>
<string name="pref_item_update_title">Update between releases</string> <string name="pref_item_update_title">Update between releases</string>
<string name="pref_item_update_summary">Get intermediate builds</string> <string name="pref_item_update_summary">Get intermediate builds</string>

View file

@ -423,19 +423,19 @@
/> />
</PreferenceScreen> </PreferenceScreen>
<!-- <PreferenceScreen android:title="@string/pref_group_tablets_title" --> <PreferenceScreen android:title="@string/pref_group_tablets_title"
<!-- > --> >
<!-- <CheckBoxPreference android:key="@string/key_enable_dualpane" --> <CheckBoxPreference android:key="@string/key_enable_dualpane"
<!-- android:title="@string/enable_dualpane_title" --> android:title="@string/enable_dualpane_title"
<!-- android:summary="@string/enable_dualpane_summary" --> android:summary="@string/enable_dualpane_summary"
<!-- android:defaultValue="false" --> android:defaultValue="false"
<!-- /> --> />
<!-- <CheckBoxPreference android:key="@string/key_force_tablet" --> <CheckBoxPreference android:key="@string/key_force_tablet"
<!-- android:title="@string/force_tablet_title" --> android:title="@string/force_tablet_title"
<!-- android:summary="@string/force_tablet_summary" --> android:summary="@string/force_tablet_summary"
<!-- android:defaultValue="false" --> android:defaultValue="false"
<!-- /> --> />
<!-- </PreferenceScreen> --> </PreferenceScreen>
<PreferenceScreen android:title="@string/pref_group_l10n_title" <PreferenceScreen android:title="@string/pref_group_l10n_title"
android:summary="@string/pref_group_l10n_summary" android:summary="@string/pref_group_l10n_summary"

View file

@ -943,7 +943,8 @@
tapping. --> tapping. -->
<string name="hide_crosshairs">Elbasid sriahssorc</string> <string name="hide_crosshairs">Elbasid sriahssorc</string>
<!-- explanation of the above --> <!-- explanation of the above -->
<string name="hide_crosshairs_summary">Od ton yllausiv etacidni hcihw draob llec si dehcuot</string> <string name="hide_crosshairs_summary">Od ton wohs hcihw draob
llec si dehcuot</string>
<string name="network_behavior">Krowten emag sgnittes</string> <string name="network_behavior">Krowten emag sgnittes</string>
<!-- explanation of the above --> <!-- explanation of the above -->
<string name="network_behavior_summary">Sgnittes taht ylppa ot <string name="network_behavior_summary">Sgnittes taht ylppa ot
@ -2057,8 +2058,8 @@
tahw\'s elbaliava.</string> tahw\'s elbaliava.</string>
<string name="force_tablet_title">Ecrof telbat tuoyal</string> <string name="force_tablet_title">Ecrof telbat tuoyal</string>
<string name="force_tablet_summary">Neve fi ym neercs si oot llams</string> <string name="force_tablet_summary">Neve fi ym neercs si oot llams</string>
<!-- <string name="enable_dualpane_title">Enable dualpane</string> --> <string name="enable_dualpane_title">Elbane enaplaud</string>
<!-- <string name="enable_dualpane_summary">Side-by-side views, very experimental!</string> --> <string name="enable_dualpane_summary">Edis-yb-edis ,sweiv yrev !latnemirepxe</string>
<!-- Nagging: title of notification reminder message --> <!-- Nagging: title of notification reminder message -->
<string name="nag_title">Rednimer: Ti\'s ruoy nrut</string> <string name="nag_title">Rednimer: Ti\'s ruoy nrut</string>
<!-- body of warning notification reminder message. First three <!-- body of warning notification reminder message. First three
@ -2227,7 +2228,7 @@
<string name="pref_group_relay_title">Yaler Ffuts</string> <string name="pref_group_relay_title">Yaler Ffuts</string>
<string name="pref_group_relay_summary">Sferp detaler ot yalp aiv yaler/tenretni</string> <string name="pref_group_relay_summary">Sferp detaler ot yalp aiv yaler/tenretni</string>
<string name="pref_group_l10n_title">Noitazilacol Ffuts</string> <string name="pref_group_l10n_title">Noitazilacol Ffuts</string>
<!-- <string name="pref_group_tablets_title">Tablets Stuff</string> --> <string name="pref_group_tablets_title">Stelbat Ffuts</string>
<string name="pref_group_l10n_summary">Sferp detaler ot ppa-ni noitazilacol</string> <string name="pref_group_l10n_summary">Sferp detaler ot ppa-ni noitazilacol</string>
<string name="pref_item_update_title">Etadpu neewteb sesaeler</string> <string name="pref_item_update_title">Etadpu neewteb sesaeler</string>
<string name="pref_item_update_summary">Teg etaidemretni sdliub</string> <string name="pref_item_update_summary">Teg etaidemretni sdliub</string>

View file

@ -943,7 +943,8 @@
tapping. --> tapping. -->
<string name="hide_crosshairs">DISABLE CROSSHAIRS</string> <string name="hide_crosshairs">DISABLE CROSSHAIRS</string>
<!-- explanation of the above --> <!-- explanation of the above -->
<string name="hide_crosshairs_summary">DO NOT VISUALLY INDICATE WHICH BOARD CELL IS TOUCHED</string> <string name="hide_crosshairs_summary">DO NOT SHOW WHICH BOARD
CELL IS TOUCHED</string>
<string name="network_behavior">NETWORK GAME SETTINGS</string> <string name="network_behavior">NETWORK GAME SETTINGS</string>
<!-- explanation of the above --> <!-- explanation of the above -->
<string name="network_behavior_summary">SETTINGS THAT APPLY TO <string name="network_behavior_summary">SETTINGS THAT APPLY TO
@ -2057,8 +2058,8 @@
WHAT\'S AVAILABLE.</string> WHAT\'S AVAILABLE.</string>
<string name="force_tablet_title">FORCE TABLET LAYOUT</string> <string name="force_tablet_title">FORCE TABLET LAYOUT</string>
<string name="force_tablet_summary">EVEN IF MY SCREEN IS TOO SMALL</string> <string name="force_tablet_summary">EVEN IF MY SCREEN IS TOO SMALL</string>
<!-- <string name="enable_dualpane_title">Enable dualpane</string> --> <string name="enable_dualpane_title">ENABLE DUALPANE</string>
<!-- <string name="enable_dualpane_summary">Side-by-side views, very experimental!</string> --> <string name="enable_dualpane_summary">SIDE-BY-SIDE VIEWS, VERY EXPERIMENTAL!</string>
<!-- Nagging: title of notification reminder message --> <!-- Nagging: title of notification reminder message -->
<string name="nag_title">REMINDER: IT\'S YOUR TURN</string> <string name="nag_title">REMINDER: IT\'S YOUR TURN</string>
<!-- body of warning notification reminder message. First three <!-- body of warning notification reminder message. First three
@ -2227,7 +2228,7 @@
<string name="pref_group_relay_title">RELAY STUFF</string> <string name="pref_group_relay_title">RELAY STUFF</string>
<string name="pref_group_relay_summary">PREFS RELATED TO PLAY VIA INTERNET/RELAY</string> <string name="pref_group_relay_summary">PREFS RELATED TO PLAY VIA INTERNET/RELAY</string>
<string name="pref_group_l10n_title">LOCALIZATION STUFF</string> <string name="pref_group_l10n_title">LOCALIZATION STUFF</string>
<!-- <string name="pref_group_tablets_title">Tablets Stuff</string> --> <string name="pref_group_tablets_title">TABLETS STUFF</string>
<string name="pref_group_l10n_summary">PREFS RELATED TO IN-APP LOCALIZATION</string> <string name="pref_group_l10n_summary">PREFS RELATED TO IN-APP LOCALIZATION</string>
<string name="pref_item_update_title">UPDATE BETWEEN RELEASES</string> <string name="pref_item_update_title">UPDATE BETWEEN RELEASES</string>
<string name="pref_item_update_summary">GET INTERMEDIATE BUILDS</string> <string name="pref_item_update_summary">GET INTERMEDIATE BUILDS</string>

View file

@ -53,7 +53,6 @@ import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
import org.eehouse.android.xw4.jni.CommsAddrRec; import org.eehouse.android.xw4.jni.CommsAddrRec;
import org.eehouse.android.xw4.jni.LastMoveInfo; import org.eehouse.android.xw4.jni.LastMoveInfo;
import org.eehouse.android.xw4.jni.XwJNI; import org.eehouse.android.xw4.jni.XwJNI;
import org.eehouse.android.xw4.jni.JNIThread;
import org.eehouse.android.xw4.loc.LocUtils; import org.eehouse.android.xw4.loc.LocUtils;
import org.eehouse.android.xw4.XWService.ReceiveResult; import org.eehouse.android.xw4.XWService.ReceiveResult;

View file

@ -141,6 +141,7 @@ public class BoardDelegate extends DelegateBase
private int m_nGuestDevs = -1; private int m_nGuestDevs = -1;
private boolean m_haveInvited = false; private boolean m_haveInvited = false;
private boolean m_overNotShown; private boolean m_overNotShown;
private boolean m_dropOnDismiss;
public class TimerRunnable implements Runnable { public class TimerRunnable implements Runnable {
private int m_why; private int m_why;
@ -180,7 +181,7 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int whichButton ) { int whichButton ) {
handleViaThread( JNICmd.CMD_RESET ); curThis().handleViaThread( JNICmd.CMD_RESET );
} }
}; };
ab.setNegativeButton( R.string.button_retry, lstnr ); ab.setNegativeButton( R.string.button_retry, lstnr );
@ -189,7 +190,7 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int whichButton ) { int whichButton ) {
doRematchIf(); curThis().doRematchIf();
} }
}; };
ab.setNegativeButton( R.string.button_rematch, lstnr ); ab.setNegativeButton( R.string.button_rematch, lstnr );
@ -214,14 +215,14 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int whichButton ) { int whichButton ) {
BoardDelegate self = curThis();
if ( DlgID.DLG_USEDICT == dlgID ) { if ( DlgID.DLG_USEDICT == dlgID ) {
setGotGameDict( m_getDict ); self.setGotGameDict( m_getDict );
} else { } else {
DwnldDelegate DwnldDelegate
.downloadDictInBack( m_activity, .downloadDictInBack( self.m_activity,
m_gi.dictLang, self.m_gi.dictLang,
m_getDict, self.m_getDict, self );
BoardDelegate.this );
} }
} }
}; };
@ -240,7 +241,7 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int whichButton ) { int whichButton ) {
deleteAndClose(); curThis().deleteAndClose();
} }
}; };
ab.setNegativeButton( R.string.button_delete, lstnr ); ab.setNegativeButton( R.string.button_delete, lstnr );
@ -258,7 +259,7 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int whichButton ) { int whichButton ) {
m_resultCode = 1; curThis().m_resultCode = 1;
} }
}; };
ab.setPositiveButton( DlgID.QUERY_REQUEST_BLK == dlgID ? ab.setPositiveButton( DlgID.QUERY_REQUEST_BLK == dlgID ?
@ -268,7 +269,7 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int whichButton ) { int whichButton ) {
m_resultCode = 0; curThis().m_resultCode = 0;
} }
}; };
ab.setNegativeButton( R.string.button_no, lstnr ); ab.setNegativeButton( R.string.button_no, lstnr );
@ -289,10 +290,11 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int whichButton ) { int whichButton ) {
showNotAgainDlgThen( R.string.not_again_lookup, curThis().
R.string. showNotAgainDlgThen( R.string.not_again_lookup,
key_na_lookup, R.string.
Action.LOOKUP_ACTION ); key_na_lookup,
Action.LOOKUP_ACTION );
} }
}; };
ab.setNegativeButton( buttonTxt, lstnr ); ab.setNegativeButton( buttonTxt, lstnr );
@ -308,7 +310,7 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int item ) { int item ) {
m_resultCode = item; curThis().m_resultCode = item;
} }
}; };
ab.setItems( m_texts, lstnr ); ab.setItems( m_texts, lstnr );
@ -321,8 +323,9 @@ public class BoardDelegate extends DelegateBase
OnClickListener undoClicked = new OnClickListener() { OnClickListener undoClicked = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int whichButton ) { int whichButton ) {
m_resultCode = UtilCtxt.PICKER_BACKUP; BoardDelegate self = curThis();
removeDialog( dlgID ); self.m_resultCode = UtilCtxt.PICKER_BACKUP;
self.removeDialog( dlgID );
} }
}; };
ab.setPositiveButton( R.string.tilepick_undo, ab.setPositiveButton( R.string.tilepick_undo,
@ -331,8 +334,9 @@ public class BoardDelegate extends DelegateBase
OnClickListener doAllClicked = new OnClickListener() { OnClickListener doAllClicked = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int whichButton ) { int whichButton ) {
m_resultCode = UtilCtxt.PICKER_PICKALL; BoardDelegate self = curThis();
removeDialog( dlgID ); self.m_resultCode = UtilCtxt.PICKER_PICKALL;
self.removeDialog( dlgID );
} }
}; };
ab.setNegativeButton( R.string.tilepick_all, doAllClicked ); ab.setNegativeButton( R.string.tilepick_all, doAllClicked );
@ -378,32 +382,34 @@ public class BoardDelegate extends DelegateBase
break; break;
case DLG_INVITE: case DLG_INVITE:
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog, int item ){
int item ) { BoardDelegate self = curThis();
if ( !m_relayMissing || if ( !self.m_relayMissing ||
! m_connTypes.contains(CommsConnType.COMMS_CONN_RELAY) ) { ! self.m_connTypes.contains(CommsConnType.COMMS_CONN_RELAY) ) {
Assert.assertTrue( 0 < m_nMissing ); Assert.assertTrue( 0 < self.m_nMissing );
if ( m_summary.hasRematchInfo() ) { if ( self.m_summary.hasRematchInfo() ) {
tryRematchInvites( true ); self.tryRematchInvites( true );
} else { } else {
showInviteChoicesThen( Action.LAUNCH_INVITE_ACTION, self.showInviteChoicesThen( Action.LAUNCH_INVITE_ACTION,
m_sentInfo ); self.m_sentInfo );
} }
} else { } else {
askDropRelay(); self.askDropRelay();
} }
} }
}; };
OnClickListener lstnrWait = new OnClickListener() { OnClickListener lstnrWait = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int item ) { int item ) {
finish(); curThis().finish();
} }
}; };
OnClickListener lstnrMore = new OnClickListener() { OnClickListener lstnrMore = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int item ) { int item ) {
showOKOnlyDialog( m_sentInfo.getAsText( m_activity ) ); BoardDelegate self = curThis();
self.showOKOnlyDialog( self.m_sentInfo
.getAsText( self.m_activity ) );
} }
}; };
@ -534,9 +540,7 @@ public class BoardDelegate extends DelegateBase
{ {
getBundledData( savedInstanceState ); getBundledData( savedInstanceState );
if ( BuildConstants.CHAT_SUPPORTED ) { m_pendingChats = new ArrayList<String>();
m_pendingChats = new ArrayList<String>();
}
m_utils = new BoardUtilCtxt(); m_utils = new BoardUtilCtxt();
m_jniu = JNIUtilsImpl.get( m_activity ); m_jniu = JNIUtilsImpl.get( m_activity );
@ -563,53 +567,7 @@ public class BoardDelegate extends DelegateBase
m_haveInvited = args.getBoolean( GameUtils.INVITED, false ); m_haveInvited = args.getBoolean( GameUtils.INVITED, false );
m_overNotShown = true; m_overNotShown = true;
Handler handler = new Handler() { m_jniThreadRef = JNIThread.getRetained( m_rowid, true );
public void handleMessage( Message msg ) {
switch( msg.what ) {
case JNIThread.DIALOG:
m_dlgBytes = (String)msg.obj;
m_dlgTitle = msg.arg1;
showDialog( DlgID.DLG_OKONLY );
break;
case JNIThread.QUERY_ENDGAME:
showDialog( DlgID.QUERY_ENDGAME );
break;
case JNIThread.TOOLBAR_STATES:
if ( null != m_jniThread ) {
m_gsi =
m_jniThread.getGameStateInfo();
updateToolbar();
if ( m_inTrade != m_gsi.inTrade ) {
m_inTrade = m_gsi.inTrade;
}
m_view.setInTrade( m_inTrade );
adjustTradeVisibility();
invalidateOptionsMenuIf();
}
break;
case JNIThread.GOT_WORDS:
CurGameInfo gi = m_jniThreadRef.getGI();
launchLookup( wordsToArray((String)msg.obj),
gi.dictLang );
break;
case JNIThread.GAME_OVER:
m_dlgBytes = (String)msg.obj;
m_dlgTitle = msg.arg1;
showDialog( DlgID.GAME_OVER );
break;
case JNIThread.MSGS_SENT:
int nSent = (Integer)msg.obj;
showToast( getQuantityString( R.plurals.resent_msgs_fmt,
nSent, nSent ) );
break;
}
}
};
m_jniThreadRef = JNIThread.getRetained( m_rowid, true ).
configure( m_activity, m_view, m_utils, this, handler );
m_jniGamePtr = m_jniThreadRef.getGamePtr();
Assert.assertNotNull( m_jniGamePtr );
// see http://stackoverflow.com/questions/680180/where-to-stop- \ // see http://stackoverflow.com/questions/680180/where-to-stop- \
// destroy-threads-in-android-service-class // destroy-threads-in-android-service-class
@ -701,15 +659,6 @@ public class BoardDelegate extends DelegateBase
if ( Activity.RESULT_CANCELED != resultCode ) { if ( Activity.RESULT_CANCELED != resultCode ) {
InviteMeans missingMeans = null; InviteMeans missingMeans = null;
switch ( requestCode ) { switch ( requestCode ) {
case CHAT_REQUEST:
if ( BuildConstants.CHAT_SUPPORTED ) {
String msg = data.getStringExtra( INTENT_KEY_CHAT );
if ( null != msg && msg.length() > 0 ) {
m_pendingChats.add( msg );
trySendChats();
}
}
break;
case BT_INVITE_RESULT: case BT_INVITE_RESULT:
missingMeans = InviteMeans.BLUETOOTH; missingMeans = InviteMeans.BLUETOOTH;
break; break;
@ -743,10 +692,6 @@ public class BoardDelegate extends DelegateBase
// in case of change... // in case of change...
setBackgroundColor(); setBackgroundColor();
setKeepScreenOn(); setKeepScreenOn();
} else if ( ! isFinishing() ) {
if ( m_relayMissing || 0 < m_nMissing ) {
showDialog( DlgID.DLG_INVITE );
}
} }
} }
} }
@ -841,8 +786,7 @@ public class BoardDelegate extends DelegateBase
Utils.setItemVisible( menu, R.id.board_menu_hint_next, Utils.setItemVisible( menu, R.id.board_menu_hint_next,
m_gsi.canHint ); m_gsi.canHint );
Utils.setItemVisible( menu, R.id.board_menu_chat, Utils.setItemVisible( menu, R.id.board_menu_chat,
BuildConstants.CHAT_SUPPORTED m_gsi.canChat );
&& m_gsi.canChat );
Utils.setItemVisible( menu, R.id.board_menu_tray, Utils.setItemVisible( menu, R.id.board_menu_tray,
!inTrade && m_gsi.canHideRack ); !inTrade && m_gsi.canHideRack );
Utils.setItemVisible( menu, R.id.board_menu_trade, Utils.setItemVisible( menu, R.id.board_menu_trade,
@ -853,8 +797,7 @@ public class BoardDelegate extends DelegateBase
Utils.setItemVisible( menu, R.id.board_menu_trade_cancel, inTrade ); Utils.setItemVisible( menu, R.id.board_menu_trade_cancel, inTrade );
Utils.setItemVisible( menu, R.id.board_menu_trade_commit, Utils.setItemVisible( menu, R.id.board_menu_trade_commit,
inTrade && m_gsi.tradeTilesSelected inTrade && m_gsi.tradeTilesSelected );
&& m_gsi.curTurnSelected );
Utils.setItemVisible( menu, R.id.board_menu_game_resign, !inTrade ); Utils.setItemVisible( menu, R.id.board_menu_game_resign, !inTrade );
if ( !inTrade ) { if ( !inTrade ) {
@ -1036,14 +979,15 @@ public class BoardDelegate extends DelegateBase
{ {
boolean handled = false; boolean handled = false;
boolean positive = AlertDialog.BUTTON_POSITIVE == which; boolean positive = AlertDialog.BUTTON_POSITIVE == which;
DbgUtils.logf("BoardDelegate.dlgButtonClicked(%s, %b)", action.toString(), positive ); DbgUtils.logdf("BoardDelegate.dlgButtonClicked(%s, %b)", action.toString(), positive );
if ( Action.ENABLE_RELAY_DO == action ) { if ( Action.ENABLE_RELAY_DO_OR == action ) {
handled = true; handled = true;
if ( positive ) { if ( positive ) {
RelayService.setEnabled( m_activity, true ); RelayService.setEnabled( m_activity, true );
} else { } else if ( AlertDialog.BUTTON_NEGATIVE == which ) {
// Things get very confused if askDropRelay() is called here. m_dropOnDismiss = true;
} else if ( DlgDelegate.DISMISS_BUTTON == which && m_dropOnDismiss ) {
postDelayed( new Runnable() { postDelayed( new Runnable() {
public void run() { public void run() {
askDropRelay(); askDropRelay();
@ -1442,6 +1386,12 @@ public class BoardDelegate extends DelegateBase
return m_handler; return m_handler;
} }
@Override
protected BoardDelegate curThis()
{
return (BoardDelegate)super.curThis();
}
private void deleteAndClose() private void deleteAndClose()
{ {
GameUtils.deleteGame( m_activity, m_gameLock, false ); GameUtils.deleteGame( m_activity, m_gameLock, false );
@ -1568,7 +1518,7 @@ public class BoardDelegate extends DelegateBase
private void handleConndMessage( String room, int devOrder, // <- hostID private void handleConndMessage( String room, int devOrder, // <- hostID
boolean allHere, int nMissing ) boolean allHere, int nMissing )
{ {
dismissInviteAlert( nMissing, true ); boolean skipDismiss = false;
int naMsg = 0; int naMsg = 0;
int naKey = 0; int naKey = 0;
@ -1596,6 +1546,7 @@ public class BoardDelegate extends DelegateBase
m_room = room; m_room = room;
showDialog( DlgID.DLG_INVITE ); showDialog( DlgID.DLG_INVITE );
invalidateOptionsMenuIf(); invalidateOptionsMenuIf();
skipDismiss = true;
} else { } else {
toastStr = getQuantityString( R.plurals.msg_relay_waiting_fmt, nMissing, toastStr = getQuantityString( R.plurals.msg_relay_waiting_fmt, nMissing,
devOrder, room, nMissing ); devOrder, room, nMissing );
@ -1620,6 +1571,10 @@ public class BoardDelegate extends DelegateBase
} }
} }
if ( !skipDismiss ) {
dismissInviteAlert( nMissing, true ); // NO!!!
}
invalidateOptionsMenuIf(); invalidateOptionsMenuIf();
} // handleConndMessage } // handleConndMessage
@ -1798,6 +1753,7 @@ public class BoardDelegate extends DelegateBase
} }
} ); } );
handleViaThread( JNICmd. CMD_ZOOM, -8 ); handleViaThread( JNICmd. CMD_ZOOM, -8 );
handleViaThread( JNICmd.CMD_SAVE );
} }
} }
@ -1924,26 +1880,30 @@ public class BoardDelegate extends DelegateBase
public void informMissing( boolean isServer, CommsConnTypeSet connTypes, public void informMissing( boolean isServer, CommsConnTypeSet connTypes,
int nDevs, final int nMissing ) int nDevs, final int nMissing )
{ {
boolean doDismiss = true;
m_connTypes = connTypes; m_connTypes = connTypes;
Assert.assertTrue( isServer || 0 == nMissing ); Assert.assertTrue( isServer || 0 == nMissing );
// DbgUtils.logf( "BoardDelegate.informMissing(isServer=%b, nDevs=%d, nMissing=%d)", // DbgUtils.logf( "BoardDelegate.informMissing(isServer=%b, nDevs=%d, nMissing=%d)",
// isServer, nDevs, nMissing ); // isServer, nDevs, nMissing );
m_nGuestDevs = nDevs; m_nGuestDevs = nDevs;
// If we might have put up an alert earlier, take it down
dismissInviteAlert( nMissing, !m_relayMissing );
m_nMissing = nMissing; // will be 0 unless isServer is true m_nMissing = nMissing; // will be 0 unless isServer is true
if ( null != connTypes && 0 == connTypes.size() ) { if ( null != connTypes && 0 == connTypes.size() ) {
askNoAddrsDelete(); askNoAddrsDelete();
} else if ( 0 < nMissing && isServer && !m_haveInvited ) { } else if ( 0 < nMissing && isServer && !m_haveInvited ) {
doDismiss = false;
post( new Runnable() { post( new Runnable() {
public void run() { public void run() {
showDialog( DlgID.DLG_INVITE ); showDialog( DlgID.DLG_INVITE );
} }
} ); } );
} }
// If we might have put up an alert earlier, take it down
if ( doDismiss ) {
dismissInviteAlert( nMissing, !m_relayMissing );
}
} }
@Override @Override
@ -2050,18 +2010,16 @@ public class BoardDelegate extends DelegateBase
public void showChat( final String msg, final int fromIndx, public void showChat( final String msg, final int fromIndx,
String fromPlayer ) String fromPlayer )
{ {
if ( BuildConstants.CHAT_SUPPORTED ) { runOnUiThread( new Runnable() {
runOnUiThread( new Runnable() { public void run() {
public void run() { DBUtils.appendChatHistory( m_activity, m_rowid, msg,
DBUtils.appendChatHistory( m_activity, m_rowid, msg, fromIndx );
fromIndx ); if ( ! ChatDelegate.append( m_rowid, msg,
if ( ! ChatDelegate.append( m_rowid, msg, fromIndx ) ) {
fromIndx ) ) { startChatActivity();
startChatActivity();
}
} }
} ); }
} } );
} }
} // class BoardUtilCtxt } // class BoardUtilCtxt
@ -2071,6 +2029,11 @@ public class BoardDelegate extends DelegateBase
if ( firstStart ) { if ( firstStart ) {
m_handler = new Handler(); m_handler = new Handler();
m_blockingDlgID = DlgID.NONE; m_blockingDlgID = DlgID.NONE;
m_jniThreadRef.configure( m_activity, m_view, m_utils, this,
makeJNIHandler() );
m_jniGamePtr = m_jniThreadRef.getGamePtr();
Assert.assertNotNull( m_jniGamePtr );
} }
try { try {
@ -2084,6 +2047,53 @@ public class BoardDelegate extends DelegateBase
} }
} }
private Handler makeJNIHandler()
{
Handler handler = new Handler() {
public void handleMessage( Message msg ) {
switch( msg.what ) {
case JNIThread.DIALOG:
m_dlgBytes = (String)msg.obj;
m_dlgTitle = msg.arg1;
showDialog( DlgID.DLG_OKONLY );
break;
case JNIThread.QUERY_ENDGAME:
showDialog( DlgID.QUERY_ENDGAME );
break;
case JNIThread.TOOLBAR_STATES:
if ( null != m_jniThread ) {
m_gsi =
m_jniThread.getGameStateInfo();
updateToolbar();
if ( m_inTrade != m_gsi.inTrade ) {
m_inTrade = m_gsi.inTrade;
}
m_view.setInTrade( m_inTrade );
adjustTradeVisibility();
invalidateOptionsMenuIf();
}
break;
case JNIThread.GOT_WORDS:
CurGameInfo gi = m_jniThreadRef.getGI();
launchLookup( wordsToArray((String)msg.obj),
gi.dictLang );
break;
case JNIThread.GAME_OVER:
m_dlgBytes = (String)msg.obj;
m_dlgTitle = msg.arg1;
showDialog( DlgID.GAME_OVER );
break;
case JNIThread.MSGS_SENT:
int nSent = (Integer)msg.obj;
showToast( getQuantityString( R.plurals.resent_msgs_fmt,
nSent, nSent ) );
break;
}
}
};
return handler;
}
private void resumeGame( boolean isStart ) private void resumeGame( boolean isStart )
{ {
if ( null == m_jniThread ) { if ( null == m_jniThread ) {
@ -2106,7 +2116,12 @@ public class BoardDelegate extends DelegateBase
int flags = DBUtils.getMsgFlags( m_activity, m_rowid ); int flags = DBUtils.getMsgFlags( m_activity, m_rowid );
if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) { if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) {
startChatActivity(); post( new Runnable() {
@Override
public void run() {
startChatActivity();
}
} );
} }
if ( m_overNotShown ) { if ( m_overNotShown ) {
boolean auto = false; boolean auto = false;
@ -2227,12 +2242,10 @@ public class BoardDelegate extends DelegateBase
R.string.not_again_undo, R.string.not_again_undo,
R.string.key_notagain_undo, R.string.key_notagain_undo,
Action.UNDO_ACTION ); Action.UNDO_ACTION );
if ( BuildConstants.CHAT_SUPPORTED ) { m_toolbar.setListener( Toolbar.BUTTON_CHAT,
m_toolbar.setListener( Toolbar.BUTTON_CHAT, R.string.not_again_chat,
R.string.not_again_chat, R.string.key_notagain_chat,
R.string.key_notagain_chat, Action.CHAT_ACTION );
Action.CHAT_ACTION );
}
} }
} // populateToolbar } // populateToolbar
@ -2320,13 +2333,11 @@ public class BoardDelegate extends DelegateBase
private void startChatActivity() private void startChatActivity()
{ {
if ( BuildConstants.CHAT_SUPPORTED ) { int curPlayer = XwJNI.board_getSelPlayer( m_jniGamePtr );
int curPlayer = XwJNI.board_getSelPlayer( m_jniGamePtr ); String[] names = m_gi.playerNames();
String[] names = m_gi.playerNames(); boolean[] locs = m_gi.playersLocal(); // to convert old histories
boolean[] locs = m_gi.playersLocal(); // to convert old histories ChatDelegate.start( getDelegator(), m_rowid, curPlayer,
ChatDelegate.startForResult( getDelegator(), RequestCode.CHAT_REQUEST, names, locs );
m_rowid, curPlayer, names, locs );
}
} }
private void closeIfFinishing( boolean force ) private void closeIfFinishing( boolean force )
@ -2354,14 +2365,6 @@ public class BoardDelegate extends DelegateBase
m_view.stopHandling(); m_view.stopHandling();
if ( XWPrefs.getThumbEnabled( m_activity ) ) {
// Before we dispose, and after JNIThread has
// relinquished interest, redraw on smaller scale.
Bitmap thumb =
GameUtils.takeSnapshot( m_activity, m_jniGamePtr, m_gi );
DBUtils.saveThumbnail( m_activity, m_gameLock, thumb );
}
m_gameLock = null; m_gameLock = null;
} }
} }
@ -2390,24 +2393,23 @@ public class BoardDelegate extends DelegateBase
} }
if ( m_connTypes.contains( CommsConnType.COMMS_CONN_RELAY ) ) { if ( m_connTypes.contains( CommsConnType.COMMS_CONN_RELAY ) ) {
if ( !RelayService.relayEnabled( m_activity ) ) { if ( !RelayService.relayEnabled( m_activity ) ) {
m_dropOnDismiss = false;
String msg = getString( R.string.warn_relay_disabled ) String msg = getString( R.string.warn_relay_disabled )
+ "\n\n" + getString( R.string.warn_relay_remove ); + "\n\n" + getString( R.string.warn_relay_remove );
showConfirmThen( msg, R.string.button_enable_relay, showConfirmThen( msg, R.string.button_enable_relay,
R.string.newgame_drop_relay, R.string.newgame_drop_relay,
Action.ENABLE_RELAY_DO ); Action.ENABLE_RELAY_DO_OR );
} }
} }
} }
private void trySendChats() private void trySendChats()
{ {
if ( BuildConstants.CHAT_SUPPORTED && null != m_jniThread ) { Iterator<String> iter = m_pendingChats.iterator();
Iterator<String> iter = m_pendingChats.iterator(); while ( iter.hasNext() ) {
while ( iter.hasNext() ) { handleViaThread( JNICmd.CMD_SENDCHAT, iter.next() );
handleViaThread( JNICmd.CMD_SENDCHAT, iter.next() );
}
m_pendingChats.clear();
} }
m_pendingChats.clear();
} }
private void tryInvites() private void tryInvites()
@ -2479,8 +2481,7 @@ public class BoardDelegate extends DelegateBase
m_toolbar.update( Toolbar.BUTTON_UNDO, m_gsi.canRedo ); m_toolbar.update( Toolbar.BUTTON_UNDO, m_gsi.canRedo );
m_toolbar.update( Toolbar.BUTTON_HINT_PREV, m_gsi.canHint ); m_toolbar.update( Toolbar.BUTTON_HINT_PREV, m_gsi.canHint );
m_toolbar.update( Toolbar.BUTTON_HINT_NEXT, m_gsi.canHint ); m_toolbar.update( Toolbar.BUTTON_HINT_NEXT, m_gsi.canHint );
m_toolbar.update( Toolbar.BUTTON_CHAT, m_toolbar.update( Toolbar.BUTTON_CHAT, m_gsi.canChat );
BuildConstants.CHAT_SUPPORTED && m_gsi.canChat );
m_toolbar.update( Toolbar.BUTTON_BROWSE_DICT, m_toolbar.update( Toolbar.BUTTON_BROWSE_DICT,
null != m_gi.dictName( m_view.getCurPlayer() ) ); null != m_gi.dictName( m_view.getCurPlayer() ) );
} }

View file

@ -24,6 +24,8 @@ import android.os.Bundle;
public class BoardFrag extends XWFragment { public class BoardFrag extends XWFragment {
public BoardFrag( Delegator parent ) { super( parent ); }
@Override @Override
public void onCreate( Bundle sis ) public void onCreate( Bundle sis )
{ {

View file

@ -22,21 +22,14 @@ package org.eehouse.android.xw4;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.FloatMath; import android.util.FloatMath;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import java.nio.IntBuffer;
import java.util.Set;
import org.eehouse.android.xw4.jni.*; import org.eehouse.android.xw4.jni.*;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet; import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet;
@ -155,7 +148,7 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
if ( m_boardDlgt.isPortrait() != (m_dims.height > m_dims.width) ) { if ( m_boardDlgt.isPortrait() != (m_dims.height > m_dims.width) ) {
// square possible; will break above! // square possible; will break above!
Assert.assertTrue( m_dims.height != m_dims.width ); Assert.assertTrue( m_dims.height != m_dims.width );
DbgUtils.logf( "onMeasure: discarding m_dims" ); DbgUtils.logdf( "onMeasure: discarding m_dims" );
if ( ++m_dimsTossCount < 4 ) { if ( ++m_dimsTossCount < 4 ) {
m_dims = null; m_dims = null;
m_layoutWidth = m_layoutHeight = 0; m_layoutWidth = m_layoutHeight = 0;
@ -204,7 +197,7 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
ConnStatusHandler.draw( m_context, canvas, getResources(), ConnStatusHandler.draw( m_context, canvas, getResources(),
m_connTypes, m_isSolo ); m_connTypes, m_isSolo );
} else { } else {
DbgUtils.logf( "BoardView.onDraw(): board not laid out yet" ); DbgUtils.logdf( "BoardView.onDraw(): board not laid out yet" );
} }
} }
} }
@ -215,15 +208,15 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
final int height = getHeight(); final int height = getHeight();
boolean layoutDone = width == m_layoutWidth && height == m_layoutHeight; boolean layoutDone = width == m_layoutWidth && height == m_layoutHeight;
if ( layoutDone ) { if ( layoutDone ) {
DbgUtils.logf( "layoutBoardOnce(): layoutDone true" ); DbgUtils.logdf( "layoutBoardOnce(): layoutDone true" );
} else if ( null == m_gi ) { } else if ( null == m_gi ) {
// nothing to do either // nothing to do either
DbgUtils.logf( "layoutBoardOnce(): no m_gi" ); DbgUtils.logdf( "layoutBoardOnce(): no m_gi" );
} else if ( null == m_jniThread ) { } else if ( null == m_jniThread ) {
// nothing to do either // nothing to do either
DbgUtils.logf( "layoutBoardOnce(): no m_jniThread" ); DbgUtils.logdf( "layoutBoardOnce(): no m_jniThread" );
} else if ( null == m_dims ) { } else if ( null == m_dims ) {
DbgUtils.logf( "layoutBoardOnce(): null m_dims" ); DbgUtils.logdf( "layoutBoardOnce(): null m_dims" );
// m_canvas = null; // m_canvas = null;
// need to synchronize?? // need to synchronize??
Paint paint = new Paint(); Paint paint = new Paint();
@ -234,12 +227,12 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
int timerWidth = scratch.width(); int timerWidth = scratch.width();
int fontWidth = int fontWidth =
Math.min(m_defaultFontHt, timerWidth / timerTxt.length()); Math.min(m_defaultFontHt, timerWidth / timerTxt.length());
DbgUtils.logf( "layoutBoardOnce(): posting JNICmd.CMD_LAYOUT(w=%d, h=%d)", width, height ); DbgUtils.logdf( "layoutBoardOnce(): posting JNICmd.CMD_LAYOUT(w=%d, h=%d)", width, height );
handle( JNIThread.JNICmd.CMD_LAYOUT, width, height, handle( JNIThread.JNICmd.CMD_LAYOUT, width, height,
fontWidth, m_defaultFontHt ); fontWidth, m_defaultFontHt );
// We'll be back.... // We'll be back....
} else { } else {
DbgUtils.logf( "layoutBoardOnce(): DOING IT" ); DbgUtils.logdf( "layoutBoardOnce(): DOING IT" );
// If board size has changed we need a new bitmap // If board size has changed we need a new bitmap
int bmHeight = 1 + m_dims.height; int bmHeight = 1 + m_dims.height;
int bmWidth = 1 + m_dims.width; int bmWidth = 1 + m_dims.width;
@ -273,7 +266,7 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
m_layoutHeight = height; m_layoutHeight = height;
layoutDone = true; layoutDone = true;
} }
DbgUtils.logf( "layoutBoardOnce()=>%b", layoutDone ); DbgUtils.logdf( "layoutBoardOnce()=>%b", layoutDone );
return layoutDone; return layoutDone;
} // layoutBoardOnce } // layoutBoardOnce
@ -286,7 +279,7 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
public void startHandling( Activity parent, JNIThread thread, public void startHandling( Activity parent, JNIThread thread,
CommsConnTypeSet connTypes ) CommsConnTypeSet connTypes )
{ {
DbgUtils.logf( "BoardView.startHandling(thread=%H)", thread ); DbgUtils.logdf( "BoardView.startHandling(thread=%H)", thread );
m_parent = parent; m_parent = parent;
m_jniThread = thread; m_jniThread = thread;
m_jniGamePtr = thread.getGamePtr(); m_jniGamePtr = thread.getGamePtr();
@ -328,10 +321,10 @@ public class BoardView extends View implements BoardHandler, SyncedDraw {
} }
} }
// Force update now that we have bits to copy // Force update now that we have bits to copy. I don't know why (yet),
if ( drew ) { // but on older versions of Android we need to run this even if drew
m_parent.runOnUiThread( m_invalidator ); // is false
} m_parent.runOnUiThread( m_invalidator );
} }
public void dimsChanged( BoardDims dims ) public void dimsChanged( BoardDims dims )

View file

@ -27,9 +27,7 @@ public class ChatActivity extends XWActivity {
@Override @Override
public void onCreate( Bundle savedInstanceState ) public void onCreate( Bundle savedInstanceState )
{ {
if ( BuildConstants.CHAT_SUPPORTED ) { ChatDelegate dlgt = new ChatDelegate( this, savedInstanceState );
ChatDelegate dlgt = new ChatDelegate( this, savedInstanceState ); super.onCreate( savedInstanceState, dlgt );
super.onCreate( savedInstanceState, dlgt );
}
} }
} }

View file

@ -30,6 +30,7 @@ import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View.OnLayoutChangeListener; import android.view.View.OnLayoutChangeListener;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.TableLayout; import android.widget.TableLayout;
@ -67,26 +68,28 @@ public class ChatDelegate extends DelegateBase {
protected void init( Bundle savedInstanceState ) protected void init( Bundle savedInstanceState )
{ {
DbgUtils.logf( "ChatDelegate.init()" ); DbgUtils.logf( "ChatDelegate.init()" );
if ( BuildConstants.CHAT_SUPPORTED ) { 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 ) { invalidateOptionsMenuIf();
invalidateOptionsMenuIf(); }
} public void beforeTextChanged( CharSequence s, int st,
public void beforeTextChanged( CharSequence s, int st, int cnt, int a ) {}
int cnt, int a ) {} public void onTextChanged( CharSequence s, int start,
public void onTextChanged( CharSequence s, int start, int before, int count ) {}
int before, int count ) {} } );
} );
Bundle args = getArguments(); Bundle args = getArguments();
m_rowid = args.getLong( GameUtils.INTENT_KEY_ROWID, -1 ); m_rowid = args.getLong( GameUtils.INTENT_KEY_ROWID, -1 );
m_curPlayer = args.getInt( INTENT_KEY_PLAYER, -1 ); m_curPlayer = args.getInt( INTENT_KEY_PLAYER, -1 );
m_names = args.getStringArray( INTENT_KEY_NAMES ); m_names = args.getStringArray( INTENT_KEY_NAMES );
boolean[] locals = args.getBooleanArray( INTENT_KEY_LOCS ); boolean[] locals = args.getBooleanArray( INTENT_KEY_LOCS );
m_scroll = (ScrollView)findViewById( R.id.scroll ); m_scroll = (ScrollView)findViewById( R.id.scroll );
m_layout = (TableLayout)findViewById( R.id.chat_history ); m_layout = (TableLayout)findViewById( R.id.chat_history );
// OnLayoutChangeListener added in API 11
if ( 11 <= Integer.valueOf( android.os.Build.VERSION.SDK ) ) {
m_layout.addOnLayoutChangeListener( new OnLayoutChangeListener() { m_layout.addOnLayoutChangeListener( new OnLayoutChangeListener() {
@Override @Override
public void onLayoutChange( View vv, int ll, int tt, int rr, public void onLayoutChange( View vv, int ll, int tt, int rr,
@ -95,24 +98,31 @@ public class ChatDelegate extends DelegateBase {
scrollDown(); scrollDown();
} }
}); });
DBUtils.HistoryPair[] pairs
= DBUtils.getChatHistory( m_activity, m_rowid, locals );
if ( null != pairs ) {
for ( DBUtils.HistoryPair pair : pairs ) {
addRow( pair.msg, pair.playerIndx );
}
}
// scrollDown();
String title = getString( R.string.chat_title_fmt,
GameUtils.getName( m_activity, m_rowid ) );
setTitle( title );
} else {
// Should really assert....
finish();
} }
}
Button sendButton = (Button)findViewById( R.id.chat_send );
if ( ABUtils.haveActionBar() ) {
sendButton.setVisibility( View.GONE );
} else {
sendButton.setOnClickListener( new View.OnClickListener() {
public void onClick( View view ) {
handleSend();
}
} );
}
DBUtils.HistoryPair[] pairs
= DBUtils.getChatHistory( m_activity, m_rowid, locals );
if ( null != pairs ) {
for ( DBUtils.HistoryPair pair : pairs ) {
addRow( pair.msg, pair.playerIndx );
}
}
String title = getString( R.string.chat_title_fmt,
GameUtils.getName( m_activity, m_rowid ) );
setTitle( title );
} // init
@Override @Override
protected void onResume() protected void onResume()
@ -124,6 +134,13 @@ public class ChatDelegate extends DelegateBase {
finish(); finish();
} else { } else {
s_visibleThis = this; s_visibleThis = this;
int[] startAndEnd = new int[2];
String curMsg = DBUtils.getCurChat( m_activity, m_rowid,
m_curPlayer, startAndEnd );
if ( null != curMsg && 0 < curMsg.length() ) {
m_edit.setText( curMsg );
m_edit.setSelection( startAndEnd[0], startAndEnd[1] );
}
} }
} }
@ -134,6 +151,12 @@ public class ChatDelegate extends DelegateBase {
m_jniThreadRef.release(); m_jniThreadRef.release();
} }
s_visibleThis = null; s_visibleThis = null;
String curText = m_edit.getText().toString();
DBUtils.setCurChat( m_activity, m_rowid, m_curPlayer, curText,
m_edit.getSelectionStart(),
m_edit.getSelectionEnd() );
super.onPause(); super.onPause();
} }
@ -163,6 +186,15 @@ public class ChatDelegate extends DelegateBase {
}); });
} }
private void handleSend() {
String text = m_edit.getText().toString();
DBUtils.appendChatHistory( m_activity, m_rowid, text, m_curPlayer );
addRow( text, m_curPlayer );
m_edit.setText( null );
m_jniThreadRef.sendChat( text );
}
@Override @Override
public boolean onPrepareOptionsMenu( Menu menu ) public boolean onPrepareOptionsMenu( Menu menu )
{ {
@ -183,26 +215,7 @@ public class ChatDelegate extends DelegateBase {
} }
break; break;
case R.id.chat_menu_send: case R.id.chat_menu_send:
String text = m_edit.getText().toString(); handleSend();
if ( null == text || text.length() == 0 ) {
setResult( Activity.RESULT_CANCELED );
finish();
} else {
DBUtils.appendChatHistory( m_activity, m_rowid, text, m_curPlayer );
addRow( text, m_curPlayer );
m_edit.setText( null );
m_jniThreadRef.sendChat( text );
// if ( null != jniThread ) {
// jniThread.handle( JNIThread.JNICmd.CMD_SENDCHAT, text );
// } else {
// Intent result = new Intent();
// result.putExtra( BoardDelegate.INTENT_KEY_CHAT, text );
// setResult( Activity.RESULT_OK, result );
// finish();
// }
}
// finish();
break; break;
default: default:
handled = false; handled = false;
@ -239,10 +252,9 @@ public class ChatDelegate extends DelegateBase {
return handled; return handled;
} }
public static void startForResult( Delegator delegator, public static void start( Delegator delegator,
RequestCode requestCode, long rowID, int curPlayer,
long rowID, int curPlayer, String[] names, boolean[] locs )
String[] names, boolean[] locs )
{ {
Assert.assertFalse( -1 == curPlayer ); Assert.assertFalse( -1 == curPlayer );
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
@ -251,13 +263,13 @@ public class ChatDelegate extends DelegateBase {
bundle.putStringArray( INTENT_KEY_NAMES, names ); bundle.putStringArray( INTENT_KEY_NAMES, names );
bundle.putBooleanArray( INTENT_KEY_LOCS, locs ); bundle.putBooleanArray( INTENT_KEY_LOCS, locs );
Activity activity = delegator.getActivity(); if ( delegator.inDPMode() ) {
if ( activity instanceof FragActivity ) { delegator.addFragment( new ChatFrag( delegator ), bundle );
FragActivity.addFragment( new ChatFrag(), bundle, delegator );
} else { } else {
Activity activity = delegator.getActivity();
Intent intent = new Intent( activity, ChatActivity.class ); Intent intent = new Intent( activity, ChatActivity.class );
intent.putExtras( bundle ); intent.putExtras( bundle );
activity.startActivityForResult( intent, requestCode.ordinal() ); activity.startActivity( intent );
} }
} }
} }

View file

@ -23,6 +23,8 @@ import android.os.Bundle;
public class ChatFrag extends XWFragment { public class ChatFrag extends XWFragment {
public ChatFrag( Delegator parent ) { super( parent ); }
@Override @Override
public void onCreate( Bundle sis ) public void onCreate( Bundle sis )
{ {

View file

@ -660,48 +660,44 @@ public class DBUtils {
public static void saveThumbnail( Context context, GameLock lock, public static void saveThumbnail( Context context, GameLock lock,
Bitmap thumb ) Bitmap thumb )
{ {
if ( BuildConstants.THUMBNAIL_SUPPORTED ) { long rowid = lock.getRowid();
long rowid = lock.getRowid(); String selection = String.format( ROW_ID_FMT, rowid );
String selection = String.format( ROW_ID_FMT, rowid ); ContentValues values = new ContentValues();
ContentValues values = new ContentValues();
if ( null == thumb ) { if ( null == thumb ) {
values.putNull( DBHelper.THUMBNAIL ); values.putNull( DBHelper.THUMBNAIL );
} else { } else {
ByteArrayOutputStream bas = new ByteArrayOutputStream(); ByteArrayOutputStream bas = new ByteArrayOutputStream();
thumb.compress( CompressFormat.PNG, 0, bas ); thumb.compress( CompressFormat.PNG, 0, bas );
values.put( DBHelper.THUMBNAIL, bas.toByteArray() ); values.put( DBHelper.THUMBNAIL, bas.toByteArray() );
} }
initDB( context ); initDB( context );
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase(); SQLiteDatabase db = s_dbHelper.getWritableDatabase();
long result = db.update( DBHelper.TABLE_NAME_SUM, long result = db.update( DBHelper.TABLE_NAME_SUM,
values, selection, null ); values, selection, null );
Assert.assertTrue( result >= 0 ); Assert.assertTrue( result >= 0 );
db.close(); db.close();
notifyListeners( rowid, GameChangeType.GAME_CHANGED ); notifyListeners( rowid, GameChangeType.GAME_CHANGED );
}
} }
} }
public static void clearThumbnails( Context context ) public static void clearThumbnails( Context context )
{ {
if ( BuildConstants.THUMBNAIL_SUPPORTED ) { ContentValues values = new ContentValues();
ContentValues values = new ContentValues(); values.putNull( DBHelper.THUMBNAIL );
values.putNull( DBHelper.THUMBNAIL ); initDB( context );
initDB( context ); synchronized( s_dbHelper ) {
synchronized( s_dbHelper ) { SQLiteDatabase db = s_dbHelper.getWritableDatabase();
SQLiteDatabase db = s_dbHelper.getWritableDatabase(); long result = db.update( DBHelper.TABLE_NAME_SUM,
long result = db.update( DBHelper.TABLE_NAME_SUM, values, null, null );
values, null, null ); db.close();
db.close();
notifyListeners( ROWIDS_ALL, GameChangeType.GAME_CHANGED ); notifyListeners( ROWIDS_ALL, GameChangeType.GAME_CHANGED );
}
} }
} }
@ -1151,6 +1147,8 @@ public class DBUtils {
// Delete chats too -- same sel as for invites // Delete chats too -- same sel as for invites
db.delete( DBHelper.TABLE_NAME_CHAT, selInvites, null ); db.delete( DBHelper.TABLE_NAME_CHAT, selInvites, null );
deleteCurChatsSync( db, rowid );
db.close(); db.close();
} }
notifyListeners( lock.getRowid(), GameChangeType.GAME_DELETED ); notifyListeners( lock.getRowid(), GameChangeType.GAME_DELETED );
@ -1270,36 +1268,74 @@ public class DBUtils {
boolean[] playersLocal ) boolean[] playersLocal )
{ {
HistoryPair[] result = null; HistoryPair[] result = null;
if ( BuildConstants.CHAT_SUPPORTED ) { String[] columns = { DBHelper.SENDER, DBHelper.MESSAGE };
String[] columns = { DBHelper.SENDER, DBHelper.MESSAGE }; String selection = String.format( "%s=%d", DBHelper.ROW, rowid );
String selection = String.format( "%s=%d", DBHelper.ROW, rowid ); initDB( context );
initDB( context ); synchronized( s_dbHelper ) {
synchronized( s_dbHelper ) { SQLiteDatabase db = s_dbHelper.getReadableDatabase();
SQLiteDatabase db = s_dbHelper.getReadableDatabase(); Cursor cursor = db.query( DBHelper.TABLE_NAME_CHAT, columns,
Cursor cursor = db.query( DBHelper.TABLE_NAME_CHAT, columns, selection, null, null, null, null );
selection, null, null, null, null ); if ( 0 < cursor.getCount() ) {
if ( 0 < cursor.getCount() ) { result = new HistoryPair[cursor.getCount()];
result = new HistoryPair[cursor.getCount()]; int msgIndex = cursor.getColumnIndex( DBHelper.MESSAGE );
int msgIndex = cursor.getColumnIndex( DBHelper.MESSAGE ); int plyrIndex = cursor.getColumnIndex( DBHelper.SENDER );
int plyrIndex = cursor.getColumnIndex( DBHelper.SENDER ); for ( int ii = 0; cursor.moveToNext(); ++ii ) {
for ( int ii = 0; cursor.moveToNext(); ++ii ) { String msg = cursor.getString( msgIndex );
String msg = cursor.getString( msgIndex ); int plyr = cursor.getInt( plyrIndex );
int plyr = cursor.getInt( plyrIndex ); HistoryPair pair = new HistoryPair(msg, plyr );
HistoryPair pair = new HistoryPair(msg, plyr ); result[ii] = pair;
result[ii] = pair;
}
} }
cursor.close();
db.close();
} }
cursor.close();
db.close();
}
if ( null == result ) { if ( null == result ) {
result = convertChatString( context, rowid, playersLocal ); result = convertChatString( context, rowid, playersLocal );
}
} }
return result; return result;
} }
private static String formatCurChatKey( long rowid ) {
return formatCurChatKey( rowid, -1 );
}
private static String formatCurChatKey( long rowid, int player ) {
String playerMatch = 0 <= player ? String.format( "%d", player ) : "%";
String result = String.format("<<chat/%d/%s>>", rowid, playerMatch );
return result;
}
public static String getCurChat( Context context, long rowid, int player,
int[] startAndEndOut ) {
String result = null;
String key = formatCurChatKey( rowid, player );
String all = getStringFor( context, key, "" );
String[] parts = TextUtils.split( all, ":" );
if ( 3 <= parts.length ) {
result = all.substring( 2 + parts[0].length() + parts[1].length() );
startAndEndOut[0] = Math.min( result.length(),
Integer.parseInt( parts[0] ) );
startAndEndOut[1] = Math.min( result.length(),
Integer.parseInt( parts[1] ) );
}
DbgUtils.logdf( "getCurChat(): => %s [%d,%d]", result,
startAndEndOut[0], startAndEndOut[1] );
return result;
}
public static void setCurChat( Context context, long rowid, int player,
String text, int start, int end ) {
String key = formatCurChatKey( rowid, player );
text = String.format( "%d:%d:%s", start, end, text );
setStringFor( context, key, text );
}
private static void deleteCurChatsSync( SQLiteDatabase db, long rowid ) {
String like = formatCurChatKey( rowid );
delStringsLikeSync( db, like );
}
public static class NeedsNagInfo { public static class NeedsNagInfo {
public long m_rowid; public long m_rowid;
public long m_nextNag; public long m_nextNag;
@ -1423,27 +1459,25 @@ public class DBUtils {
public static Bitmap getThumbnail( Context context, long rowid ) public static Bitmap getThumbnail( Context context, long rowid )
{ {
Bitmap thumb = null; Bitmap thumb = null;
if ( BuildConstants.THUMBNAIL_SUPPORTED ) { byte[] data = null;
byte[] data = null; String[] columns = { DBHelper.THUMBNAIL };
String[] columns = { DBHelper.THUMBNAIL }; String selection = String.format( ROW_ID_FMT, rowid );
String selection = String.format( ROW_ID_FMT, rowid );
initDB( context ); initDB( context );
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,
selection, null, null, null, null ); selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) { if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
data = cursor.getBlob( cursor. data = cursor.getBlob( cursor.
getColumnIndex(DBHelper.THUMBNAIL)); getColumnIndex(DBHelper.THUMBNAIL));
}
cursor.close();
db.close();
} }
cursor.close();
db.close();
}
if ( null != data ) { if ( null != data ) {
thumb = BitmapFactory.decodeByteArray( data, 0, data.length ); thumb = BitmapFactory.decodeByteArray( data, 0, data.length );
}
} }
return thumb; return thumb;
} }
@ -1756,24 +1790,22 @@ public class DBUtils {
private static String getChatHistoryStr( Context context, long rowid ) private static String getChatHistoryStr( Context context, long rowid )
{ {
String result = null; String result = null;
if ( BuildConstants.CHAT_SUPPORTED ) { String[] columns = { DBHelper.CHAT_HISTORY };
String[] columns = { DBHelper.CHAT_HISTORY }; String selection = String.format( ROW_ID_FMT, rowid );
String selection = String.format( ROW_ID_FMT, rowid ); initDB( context );
initDB( context ); 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,
selection, null, null, null, null ); selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) { if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = result =
cursor.getString( cursor cursor.getString( cursor
.getColumnIndex(DBHelper .getColumnIndex(DBHelper
.CHAT_HISTORY)); .CHAT_HISTORY));
}
cursor.close();
db.close();
} }
cursor.close();
db.close();
} }
return result; return result;
} }
@ -2304,6 +2336,12 @@ public class DBUtils {
} }
} }
private static void delStringsLikeSync( SQLiteDatabase db, String like )
{
String selection = String.format( "%s LIKE '%s'", DBHelper.KEY, like );
db.delete( DBHelper.TABLE_NAME_PAIRS, selection, null );
}
private static String getStringForSync( SQLiteDatabase db, String key, String dflt ) private static String getStringForSync( SQLiteDatabase db, String key, String dflt )
{ {
String selection = String.format( "%s = '%s'", DBHelper.KEY, key ); String selection = String.format( "%s = '%s'", DBHelper.KEY, key );

View file

@ -19,13 +19,14 @@
package org.eehouse.android.xw4; package org.eehouse.android.xw4;
import android.graphics.Rect;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnCancelListener;
import android.content.Intent; import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.graphics.Point;
import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -38,6 +39,11 @@ import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eehouse.android.xw4.DlgDelegate.Action; import org.eehouse.android.xw4.DlgDelegate.Action;
import org.eehouse.android.xw4.DlgDelegate.ActionPair; import org.eehouse.android.xw4.DlgDelegate.ActionPair;
import org.eehouse.android.xw4.loc.LocUtils; import org.eehouse.android.xw4.loc.LocUtils;
@ -57,6 +63,9 @@ public class DelegateBase implements DlgClickNotify,
private int m_layoutID; private int m_layoutID;
private View m_rootView; private View m_rootView;
private boolean m_isVisible; private boolean m_isVisible;
private ArrayList<Runnable> m_visibleProcs = new ArrayList<Runnable>();
private static Map<Class, WeakReference<DelegateBase>> s_instances
= new HashMap<Class, WeakReference<DelegateBase>>();
public DelegateBase( Delegator delegator, Bundle bundle, int layoutID ) public DelegateBase( Delegator delegator, Bundle bundle, int layoutID )
{ {
@ -80,14 +89,13 @@ public class DelegateBase implements DlgClickNotify,
protected void onSaveInstanceState( Bundle outState ) {} protected void onSaveInstanceState( Bundle outState ) {}
public boolean onPrepareOptionsMenu( Menu menu ) { return false; } public boolean onPrepareOptionsMenu( Menu menu ) { return false; }
public boolean onOptionsItemSelected( MenuItem item ) { return false; } public boolean onOptionsItemSelected( MenuItem item ) { return false; }
public void onCreateContextMenu( ContextMenu menu, View view, protected void onCreateContextMenu( ContextMenu menu, View view,
ContextMenuInfo menuInfo ) {} ContextMenuInfo menuInfo ) {}
public boolean onContextItemSelected( MenuItem item ) { return false; } protected boolean onContextItemSelected( MenuItem item ) { return false; }
protected void onStart() {}
protected void onStop() {} protected void onStop() {}
protected void onDestroy() {} protected void onDestroy() {}
protected void onWindowFocusChanged( boolean hasFocus ) {} protected void onWindowFocusChanged( boolean hasFocus ) {}
protected boolean onBackPressed() { return false; } protected boolean handleBackPressed() { return false; }
public void orientationChanged() {} public void orientationChanged() {}
protected void requestWindowFeature( int feature ) {} protected void requestWindowFeature( int feature ) {}
@ -108,13 +116,24 @@ public class DelegateBase implements DlgClickNotify,
protected void onActivityResult( RequestCode requestCode, int resultCode, protected void onActivityResult( RequestCode requestCode, int resultCode,
Intent data ) Intent data )
{ {
DbgUtils.logf( "DelegateBase.onActivityResult(): subclass responsibility!!!" ); DbgUtils.logf( "%s.onActivityResult(): subclass responsibility!!!",
getClass().getSimpleName() );
}
protected void onStart()
{
if ( s_instances.containsKey(getClass()) ) {
DbgUtils.logdf( "%s.onStart(): replacing curThis",
getClass().getSimpleName() );
}
s_instances.put( getClass(), new WeakReference<DelegateBase>(this) );
} }
protected void onResume() protected void onResume()
{ {
m_isVisible = true; m_isVisible = true;
XWService.setListener( this ); XWService.setListener( this );
runIfVisible();
} }
protected void onPause() protected void onPause()
@ -123,6 +142,17 @@ public class DelegateBase implements DlgClickNotify,
XWService.setListener( null ); XWService.setListener( null );
} }
protected DelegateBase curThis()
{
DelegateBase result = null;
WeakReference<DelegateBase> ref = s_instances.get( getClass() );
if ( null != ref ) {
result = ref.get();
}
// DbgUtils.logdf( "%s.curThis() => " + result, this.toString() );
return result;
}
public boolean onCreateOptionsMenu( Menu menu, MenuInflater inflater ) public boolean onCreateOptionsMenu( Menu menu, MenuInflater inflater )
{ {
boolean handled = 0 < m_optionsMenuID; boolean handled = 0 < m_optionsMenuID;
@ -144,7 +174,9 @@ public class DelegateBase implements DlgClickNotify,
protected boolean isFinishing() protected boolean isFinishing()
{ {
return m_activity.isFinishing(); boolean result = m_activity.isFinishing();
// DbgUtils.logf( "%s.isFinishing() => %b", getClass().getSimpleName(), result );
return result;
} }
protected Intent getIntent() protected Intent getIntent()
@ -210,8 +242,10 @@ public class DelegateBase implements DlgClickNotify,
protected void setResult( int result, Intent intent ) protected void setResult( int result, Intent intent )
{ {
if ( m_activity instanceof FragActivity ) { if ( m_activity instanceof MainActivity ) {
Assert.fail(); MainActivity main = (MainActivity)m_activity;
XWFragment fragment = (XWFragment)m_delegator;
main.setFragmentResult( fragment, result, intent );
} else { } else {
m_activity.setResult( result, intent ); m_activity.setResult( result, intent );
} }
@ -234,34 +268,52 @@ public class DelegateBase implements DlgClickNotify,
protected void finish() protected void finish()
{ {
if ( m_activity instanceof FragActivity ) { boolean handled = false;
((FragActivity)m_activity).finishFragment(); if ( m_activity instanceof MainActivity ) {
} else { MainActivity main = (MainActivity)m_activity;
if ( main.inDPMode() ) {
main.finishFragment();
handled = true;
}
}
if ( !handled ) {
m_activity.finish(); m_activity.finish();
} }
} }
protected boolean isPortrait() protected boolean isPortrait()
{ {
int[] containerDims = getContainerDims( new int[2] ); Point size = getContainerSize();
boolean result = containerDims[0] < containerDims[1]; boolean result = size.x < size.y;
DbgUtils.logdf( "%s.isPortrait() => %b", getClass().getName(), result ); DbgUtils.logdf( "%s.isPortrait() => %b",
getClass().getSimpleName(), result );
return result; return result;
} }
protected int[] getContainerDims( int[] outDims ) private Point getContainerSize()
{ {
if ( m_activity instanceof FragActivity ) { Point result = null;
((FragActivity)m_activity).getFragmentDims( outDims ); if ( m_activity instanceof MainActivity ) {
result = ((MainActivity)m_activity).getFragmentSize();
} else { } else {
Rect rect = new Rect(); Rect rect = new Rect();
m_rootView.getWindowVisibleDisplayFrame( rect ); m_rootView.getWindowVisibleDisplayFrame( rect );
outDims[0] = rect.width(); result = new Point( rect.width(), rect.height() );
outDims[1] = rect.height(); }
DbgUtils.logdf( "%s.getContainerSize(): width => %d, height => %d",
getClass().getSimpleName(), result.x, result.y );
return result;
}
private void runIfVisible()
{
if ( isVisible() ) {
for ( Runnable proc : m_visibleProcs ) {
post( proc );
}
m_visibleProcs.clear();
} }
DbgUtils.logdf( "%s.getContainerDims(): width => %d, height => %d",
getClass().getName(), outDims[0], outDims[1] );
return outDims;
} }
protected String getString( int resID, Object... params ) protected String getString( int resID, Object... params )
@ -585,6 +637,18 @@ public class DelegateBase implements DlgClickNotify,
protected boolean isVisible() { return m_isVisible; } protected boolean isVisible() { return m_isVisible; }
protected boolean handleNewIntent( Intent intent ) {
DbgUtils.logf( "%s.handleNewIntent(%s): not handling",
getClass().getSimpleName(), intent.toString() );
return false; // not handled
}
protected void runWhenActive( Runnable proc )
{
m_visibleProcs.add( proc );
runIfVisible();
}
////////////////////////////////////////////////// //////////////////////////////////////////////////
// MultiService.MultiEventListener interface // MultiService.MultiEventListener interface
////////////////////////////////////////////////// //////////////////////////////////////////////////
@ -680,5 +744,4 @@ public class DelegateBase implements DlgClickNotify,
{ {
Assert.fail(); Assert.fail();
} }
} }

View file

@ -28,7 +28,10 @@ public interface Delegator {
Activity getActivity(); Activity getActivity();
Bundle getArguments(); Bundle getArguments();
void finish(); void finish();
boolean inDPMode();
void addFragment( XWFragment fragment, Bundle extras );
void addFragmentForResult( XWFragment fragment, Bundle extras,
RequestCode requestCode );
// For activities with lists // For activities with lists
void setListAdapter( ListAdapter adapter ); void setListAdapter( ListAdapter adapter );
ListAdapter getListAdapter(); ListAdapter getListAdapter();

View file

@ -278,7 +278,6 @@ public class DictBrowseDelegate extends ListDelegateBase
launchLookup( words, m_lang, true ); launchLookup( words, m_lang, true );
} }
////////////////////////////////////////////////// //////////////////////////////////////////////////
// AdapterView.OnItemSelectedListener interface // AdapterView.OnItemSelectedListener interface
////////////////////////////////////////////////// //////////////////////////////////////////////////
@ -424,10 +423,10 @@ public class DictBrowseDelegate extends ListDelegateBase
private static void launch( Delegator delegator, Bundle bundle ) private static void launch( Delegator delegator, Bundle bundle )
{ {
Activity activity = delegator.getActivity(); if ( delegator.inDPMode() ) {
if ( activity instanceof FragActivity ) { delegator.addFragment( new DictBrowseFrag( delegator ), bundle );
FragActivity.addFragment( new DictBrowseFrag(), bundle, delegator );
} else { } else {
Activity activity = delegator.getActivity();
Intent intent = new Intent( activity, DictBrowseActivity.class ); Intent intent = new Intent( activity, DictBrowseActivity.class );
intent.putExtras( bundle ); intent.putExtras( bundle );
activity.startActivity( intent ); activity.startActivity( intent );
@ -447,6 +446,10 @@ public class DictBrowseDelegate extends ListDelegateBase
{ {
DictUtils.DictLoc loc DictUtils.DictLoc loc
= DictUtils.getDictLoc( delegator.getActivity(), name ); = DictUtils.getDictLoc( delegator.getActivity(), name );
launch( delegator, name, loc ); if ( null == loc ) {
DbgUtils.logf( "DictBrowseDelegate.launch(): DictLoc null; try again?" );
} else {
launch( delegator, name, loc );
}
} }
} }

View file

@ -23,6 +23,8 @@ import android.os.Bundle;
public class DictBrowseFrag extends XWFragment { public class DictBrowseFrag extends XWFragment {
public DictBrowseFrag( Delegator parent ) { super( parent ); }
@Override @Override
public void onCreate( Bundle sis ) public void onCreate( Bundle sis )
{ {

View file

@ -44,11 +44,4 @@ public class DictsActivity extends XWActivity {
m_dlgt = new DictsDelegate( this, savedInstanceState ); m_dlgt = new DictsDelegate( this, savedInstanceState );
super.onCreate( savedInstanceState, m_dlgt ); super.onCreate( savedInstanceState, m_dlgt );
} // onCreate } // onCreate
public static void start( Context context )
{
Intent intent = new Intent( context, DictsActivity.class );
context.startActivity( intent );
}
} }

View file

@ -382,19 +382,20 @@ public class DictsDelegate extends ListDelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
DictLoc toLoc = itemToRealLoc( moveTo[0] ); DictsDelegate self = curThis();
DictLoc toLoc = self.itemToRealLoc( moveTo[0] );
for ( XWListItem selItem : selItems ) { for ( XWListItem selItem : selItems ) {
DictLoc fromLoc = (DictLoc)selItem.getCached(); DictLoc fromLoc = (DictLoc)selItem.getCached();
String name = selItem.getText(); String name = selItem.getText();
if ( fromLoc == toLoc ) { if ( fromLoc == toLoc ) {
DbgUtils.logf( "not moving %s: same loc", name ); DbgUtils.logf( "not moving %s: same loc", name );
} else if ( DictUtils.moveDict( m_activity, } else if ( DictUtils.moveDict( self.m_activity,
name, fromLoc, name, fromLoc,
toLoc ) ) { toLoc ) ) {
selItem.setComment( m_locNames[toLoc.ordinal()] ); selItem.setComment( self.m_locNames[toLoc.ordinal()] );
selItem.setCached( toLoc ); selItem.setCached( toLoc );
selItem.invalidate(); selItem.invalidate();
DBUtils.dictsMoveInfo( m_activity, name, DBUtils.dictsMoveInfo( self.m_activity, name,
fromLoc, toLoc ); fromLoc, toLoc );
} else { } else {
DbgUtils.logf( "moveDict(%s) failed", name ); DbgUtils.logf( "moveDict(%s) failed", name );
@ -416,15 +417,16 @@ public class DictsDelegate extends ListDelegateBase
final XWListItem row = m_selDicts.values().iterator().next(); final XWListItem row = m_selDicts.values().iterator().next();
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
DictsDelegate self = curThis();
if ( DialogInterface.BUTTON_NEGATIVE == item if ( DialogInterface.BUTTON_NEGATIVE == item
|| DialogInterface.BUTTON_POSITIVE == item ) { || DialogInterface.BUTTON_POSITIVE == item ) {
setDefault( row, R.string.key_default_dict, self.setDefault( row, R.string.key_default_dict,
R.string.key_default_robodict ); R.string.key_default_robodict );
} }
if ( DialogInterface.BUTTON_NEGATIVE == item if ( DialogInterface.BUTTON_NEGATIVE == item
|| DialogInterface.BUTTON_NEUTRAL == item ) { || DialogInterface.BUTTON_NEUTRAL == item ) {
setDefault( row, R.string.key_default_robodict, self.setDefault( row, R.string.key_default_robodict,
R.string.key_default_dict ); R.string.key_default_dict );
} }
} }
}; };
@ -444,18 +446,18 @@ public class DictsDelegate extends ListDelegateBase
case DICT_OR_DECLINE: case DICT_OR_DECLINE:
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
Intent intent = getIntent(); DictsDelegate self = curThis();
Intent intent = self.getIntent();
int lang = intent.getIntExtra( MultiService.LANG, -1 ); int lang = intent.getIntExtra( MultiService.LANG, -1 );
String name = intent.getStringExtra( MultiService.DICT ); String name = intent.getStringExtra( MultiService.DICT );
m_launchedForMissing = true; self.m_launchedForMissing = true;
DwnldDelegate DwnldDelegate
.downloadDictInBack( m_activity, lang, .downloadDictInBack( self.m_activity, lang, name, self );
name, DictsDelegate.this );
} }
}; };
lstnr2 = new OnClickListener() { lstnr2 = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
finish(); curThis().finish();
} }
}; };
@ -571,7 +573,8 @@ public class DictsDelegate extends ListDelegateBase
} }
} }
protected boolean onBackPressed() @Override
protected boolean handleBackPressed()
{ {
boolean handled = 0 < m_selDicts.size(); boolean handled = 0 < m_selDicts.size();
if ( handled ) { if ( handled ) {
@ -1084,6 +1087,12 @@ public class DictsDelegate extends ListDelegateBase
return canHandle; return canHandle;
} }
@Override
protected DictsDelegate curThis()
{
return (DictsDelegate)super.curThis();
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// XWListItem.ExpandedListener interface // XWListItem.ExpandedListener interface
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -1445,4 +1454,15 @@ public class DictsDelegate extends ListDelegateBase
cancel( true ); cancel( true );
} }
} // class FetchListTask } // class FetchListTask
public static void start( Delegator delegator )
{
if ( delegator.inDPMode() ) {
delegator.addFragment( new DictsFrag( delegator ), null );
} else {
Activity activity = delegator.getActivity();
Intent intent = new Intent( activity, DictsActivity.class );
activity.startActivity( intent );
}
}
} }

View file

@ -0,0 +1,33 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2016 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.os.Bundle;
public class DictsFrag extends XWFragment {
public DictsFrag( Delegator parent ) { super( parent ); }
@Override
public void onCreate( Bundle sis )
{
super.onCreate( new DictsDelegate( this, sis ), sis, true );
}
}

View file

@ -122,6 +122,7 @@ public class DlgDelegate {
ENABLE_SMS_DO, ENABLE_SMS_DO,
ENABLE_BT_DO, ENABLE_BT_DO,
ENABLE_RELAY_DO, ENABLE_RELAY_DO,
ENABLE_RELAY_DO_OR,
DISABLE_RELAY_DO, DISABLE_RELAY_DO,
} }
@ -156,8 +157,8 @@ public class DlgDelegate {
void showNotAgainDlgThen( int msgID, int prefsKey, Action action ); void showNotAgainDlgThen( int msgID, int prefsKey, Action action );
} }
private static Map<Integer, WeakReference<DelegateBase>> s_pendings private static Map<DlgID, WeakReference<DelegateBase>> s_pendings
= new HashMap<Integer, WeakReference<DelegateBase>>(); = new HashMap<DlgID, WeakReference<DelegateBase>>();
private Activity m_activity; private Activity m_activity;
private DelegateBase m_dlgt; private DelegateBase m_dlgt;
private DlgClickNotify m_clickCallback; private DlgClickNotify m_clickCallback;
@ -206,12 +207,10 @@ public class DlgDelegate {
protected void showDialog( DlgID dlgID ) protected void showDialog( DlgID dlgID )
{ {
int id = dlgID.ordinal(); // DbgUtils.logf( "showDialog(%s)", dlgID.toString() );
if ( m_activity instanceof FragActivity ) {
s_pendings.put( id, new WeakReference<DelegateBase>(m_dlgt) );
}
if ( !m_activity.isFinishing() ) { if ( !m_activity.isFinishing() ) {
m_activity.showDialog( id ); s_pendings.put( dlgID, new WeakReference<DelegateBase>(m_dlgt) );
m_activity.showDialog( dlgID.ordinal() );
} }
} }
@ -889,7 +888,8 @@ public class DlgDelegate {
public static Dialog onCreateDialog( int id ) public static Dialog onCreateDialog( int id )
{ {
Dialog result = null; Dialog result = null;
WeakReference<DelegateBase> ref = s_pendings.get( id ); DlgID dlgID = DlgID.values()[id];
WeakReference<DelegateBase> ref = s_pendings.get( dlgID );
DelegateBase dlgt = ref.get(); DelegateBase dlgt = ref.get();
if ( null != dlgt ) { if ( null != dlgt ) {
result = dlgt.onCreateDialog( id ); result = dlgt.onCreateDialog( id );
@ -899,10 +899,11 @@ public class DlgDelegate {
public static void onPrepareDialog( int id, Dialog dialog ) public static void onPrepareDialog( int id, Dialog dialog )
{ {
WeakReference<DelegateBase> ref = s_pendings.get( id ); DlgID dlgID = DlgID.values()[id];
WeakReference<DelegateBase> ref = s_pendings.get( dlgID );
DelegateBase dlgt = ref.get(); DelegateBase dlgt = ref.get();
if ( null != dlgt ) { if ( null != dlgt ) {
dlgt.prepareDialog( DlgID.values()[id], dialog ); dlgt.prepareDialog( dlgID, dialog );
} }
} }

View file

@ -0,0 +1,98 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2009 - 2016 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.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
public class DualpaneDelegate extends DelegateBase {
private Activity m_activity;
public DualpaneDelegate( Delegator delegator, Bundle sis )
{
super( delegator, sis, R.layout.dualcontainer );
m_activity = delegator.getActivity();
}
@Override
protected void init( Bundle savedInstanceState )
{
}
@Override
protected Dialog onCreateDialog( int id )
{
return DlgDelegate.onCreateDialog( id );
}
@Override
protected void prepareDialog( DlgID dlgId, Dialog dialog )
{
DlgDelegate.onPrepareDialog( dlgId.ordinal(), dialog );
}
@Override
protected boolean handleNewIntent( Intent intent )
{
MainActivity main = (MainActivity)m_activity;
boolean handled = main.dispatchNewIntent( intent );
DbgUtils.logf( "DualpaneDelegate.handleNewIntent() => %b", handled );
return handled;
}
@Override
protected boolean handleBackPressed()
{
MainActivity main = (MainActivity)m_activity;
boolean handled = main.dispatchBackPressed();
DbgUtils.logf( "DualpaneDelegate.handleBackPressed() => %b", handled );
return handled;
}
@Override
protected void onActivityResult( RequestCode requestCode, int resultCode, Intent data )
{
MainActivity main = (MainActivity)m_activity;
main.dispatchOnActivityResult( requestCode, resultCode, data );
}
@Override
protected void onCreateContextMenu( ContextMenu menu, View view,
ContextMenuInfo menuInfo )
{
MainActivity main = (MainActivity)m_activity;
main.dispatchOnCreateContextMenu( menu, view, menuInfo );
}
@Override
protected boolean onContextItemSelected( MenuItem item )
{
MainActivity main = (MainActivity)m_activity;
return main.dispatchOnContextItemSelected( item );
}
}

View file

@ -307,7 +307,7 @@ public class DwnldDelegate extends ListDelegateBase {
} // init } // init
@Override @Override
protected boolean onBackPressed() protected boolean handleBackPressed()
{ {
// cancel any tasks that remain // cancel any tasks that remain
for ( Iterator<DownloadFilesTask> iter = m_dfts.iterator(); for ( Iterator<DownloadFilesTask> iter = m_dfts.iterator();
@ -315,7 +315,7 @@ public class DwnldDelegate extends ListDelegateBase {
DownloadFilesTask dft = iter.next(); DownloadFilesTask dft = iter.next();
dft.cancel( true ); dft.cancel( true );
} }
return super.onBackPressed(); return super.handleBackPressed();
} }
private void mkListAdapter() private void mkListAdapter()

View file

@ -1,309 +1,309 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */ // /* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/* // /*
* Copyright 2014-2016 by Eric House (xwords@eehouse.org). All rights // * Copyright 2014-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
* modify it under the terms of the GNU General Public License as // * modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the // * published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version. // * License, or (at your option) any later version.
* // *
* This program is distributed in the hope that it will be useful, but // * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of // * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. // * General Public License for more details.
* // *
* You should have received a copy of the GNU General Public License // * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software // * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ // */
package org.eehouse.android.xw4; // package org.eehouse.android.xw4;
import android.graphics.Rect; // import android.graphics.Rect;
import android.app.Dialog; // import android.app.Dialog;
import android.content.res.Configuration; // import android.content.res.Configuration;
import android.os.Bundle; // import android.os.Bundle;
import android.support.v4.app.Fragment; // import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity; // import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager; // import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentManager.BackStackEntry; // import android.support.v4.app.FragmentManager.BackStackEntry;
import android.support.v4.app.FragmentTransaction; // import android.support.v4.app.FragmentTransaction;
import android.view.View; // import android.view.View;
import android.widget.FrameLayout; // import android.widget.FrameLayout;
import android.widget.LinearLayout.LayoutParams; // import android.widget.LinearLayout.LayoutParams;
import android.widget.LinearLayout; // import android.widget.LinearLayout;
import android.widget.LinearLayout; // import android.widget.LinearLayout;
import junit.framework.Assert; // import junit.framework.Assert;
public class FragActivity extends FragmentActivity // public class FragActivity extends FragmentActivity
implements FragmentManager.OnBackStackChangedListener { // implements FragmentManager.OnBackStackChangedListener {
private static final int MAX_PANES_LANDSCAPE = 3; // private static final int MAX_PANES_LANDSCAPE = 3;
public interface OrientChangeListener { // // public interface OrientChangeListener {
void orientationChanged(); // // void orientationChanged();
} // // }
private static FragActivity s_this; // private static FragActivity s_this;
private LinearLayout m_root; // private LinearLayout m_root;
private int m_nextID = 0x00FFFFFF; // private int m_nextID = 0x00FFFFFF;
private int m_maxPanes; // private int m_maxPanes;
private Boolean m_isPortrait; // private Boolean m_isPortrait;
@Override // @Override
public void onCreate( Bundle savedInstanceState ) // public void onCreate( Bundle savedInstanceState )
{ // {
s_this = this; // s_this = this;
super.onCreate( savedInstanceState ); // super.onCreate( savedInstanceState );
setContentView( R.layout.fragact ); // setContentView( R.layout.dualcontainer );
m_root = (LinearLayout)findViewById( R.id.main_container ); // m_root = (LinearLayout)findViewById( R.id.main_container );
getSupportFragmentManager().addOnBackStackChangedListener( this ); // getSupportFragmentManager().addOnBackStackChangedListener( this );
m_maxPanes = maxPanes(); // m_maxPanes = maxPanes();
// Nothing to do if we're restarting // // Nothing to do if we're restarting
if ( savedInstanceState == null ) { // if ( savedInstanceState == null ) {
// In case this activity was started with special instructions from an Intent, // // In case this activity was started with special instructions from an Intent,
// pass the Intent's extras to the fragment as arguments // // pass the Intent's extras to the fragment as arguments
addFragmentImpl( new GamesListFrag(), getIntent().getExtras(), null ); // addFragmentImpl( new GamesListFrag(), getIntent().getExtras(), null );
} // }
} // }
@Override // @Override
public void onBackPressed() // public void onBackPressed()
{ // {
DbgUtils.logf( "FragActivity.onBackPressed()" ); // DbgUtils.logf( "FragActivity.onBackPressed()" );
super.onBackPressed(); // super.onBackPressed();
} // }
@Override // @Override
public void onConfigurationChanged( Configuration newConfig ) // public void onConfigurationChanged( Configuration newConfig )
{ // {
Rect rect = new Rect(); // Rect rect = new Rect();
m_root.getWindowVisibleDisplayFrame( rect ); // m_root.getWindowVisibleDisplayFrame( rect );
boolean isPortrait // boolean isPortrait
= Configuration.ORIENTATION_PORTRAIT == newConfig.orientation; // = Configuration.ORIENTATION_PORTRAIT == newConfig.orientation;
DbgUtils.logf( "FragActivity.onConfigurationChanged(isPortrait=%b)", // DbgUtils.logf( "FragActivity.onConfigurationChanged(isPortrait=%b)",
isPortrait ); // isPortrait );
m_isPortrait = isPortrait; // m_isPortrait = isPortrait;
if ( isPortrait != (rect.width() <= rect.height()) ) { // if ( isPortrait != (rect.width() <= rect.height()) ) {
DbgUtils.logdf( "FragActivity.onConfigurationChanged(): isPortrait:" // DbgUtils.logdf( "FragActivity.onConfigurationChanged(): isPortrait:"
+ " %b; width: %d; height: %d", // + " %b; width: %d; height: %d",
isPortrait, rect.width(), rect.height() ); // isPortrait, rect.width(), rect.height() );
} // }
int maxPanes = isPortrait? 1 : MAX_PANES_LANDSCAPE; // int maxPanes = isPortrait? 1 : MAX_PANES_LANDSCAPE;
if ( m_maxPanes != maxPanes ) { // if ( m_maxPanes != maxPanes ) {
m_maxPanes = maxPanes; // m_maxPanes = maxPanes;
setVisiblePanes(); // setVisiblePanes();
} // }
tellOrientationChanged(); // tellOrientationChanged();
super.onConfigurationChanged( newConfig ); // super.onConfigurationChanged( newConfig );
} // }
protected void getFragmentDims( int[] dims ) // protected void getFragmentDims( int[] dims )
{ // {
Rect rect = new Rect(); // Rect rect = new Rect();
m_root.getWindowVisibleDisplayFrame( rect ); // m_root.getWindowVisibleDisplayFrame( rect );
int width = rect.width(); // int width = rect.width();
int height = rect.height(); // int height = rect.height();
if ( null != m_isPortrait && m_isPortrait && height < width ) { // if ( null != m_isPortrait && m_isPortrait && height < width ) {
int tmp = width; // int tmp = width;
width = height; // width = height;
height = tmp; // height = tmp;
} // }
dims[0] = width / Math.min( m_maxPanes, m_root.getChildCount() ); // dims[0] = width / Math.min( m_maxPanes, m_root.getChildCount() );
dims[1] = height; // dims[1] = height;
} // }
@Override // @Override
protected Dialog onCreateDialog( int id ) // protected Dialog onCreateDialog( int id )
{ // {
return DlgDelegate.onCreateDialog( id ); // return DlgDelegate.onCreateDialog( id );
} // }
@Override // @Override
protected void onPrepareDialog( int id, Dialog dialog ) // protected void onPrepareDialog( int id, Dialog dialog )
{ // {
DlgDelegate.onPrepareDialog( id, dialog ); // DlgDelegate.onPrepareDialog( id, dialog );
} // }
////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////
// FragmentManager.OnBackStackChangedListener // // FragmentManager.OnBackStackChangedListener
////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////
public void onBackStackChanged() // public void onBackStackChanged()
{ // {
DbgUtils.logf( "FragActivity.onBackStackChanged()" ); // DbgUtils.logf( "FragActivity.onBackStackChanged()" );
// make sure the right-most are visible // // make sure the right-most are visible
int fragCount = getSupportFragmentManager().getBackStackEntryCount(); // int fragCount = getSupportFragmentManager().getBackStackEntryCount();
if ( 0 == fragCount ) { // if ( 0 == fragCount ) {
finish(); // finish();
} else if ( fragCount == m_root.getChildCount() - 1 ) { // } else if ( fragCount == m_root.getChildCount() - 1 ) {
m_root.removeViewAt( fragCount ); // m_root.removeViewAt( fragCount );
setVisiblePanes(); // setVisiblePanes();
} // }
} // }
// public void launchDictFrag( Bundle args ) // // public void launchDictFrag( Bundle args )
// { // // {
// // DictBrowseFrag dbf = new DictBrowseFrag(); // // // DictBrowseFrag dbf = new DictBrowseFrag();
// // dbf.setArguments( args ); // // // dbf.setArguments( args );
// // addFragment( dbf ); // // // addFragment( dbf );
// } // // }
protected void finishFragment() // protected void finishFragment()
{ // {
popFragment( null ); // popFragment( null );
} // }
protected void popFragment( Fragment frag ) // protected void popFragment( Fragment frag )
{ // {
getSupportFragmentManager().popBackStack(); // getSupportFragmentManager().popBackStack();
} // }
private void addFragmentImpl( Fragment fragment, Bundle bundle, // private void addFragmentImpl( Fragment fragment, Bundle bundle,
Delegator parent ) // Delegator parent )
{ // {
fragment.setArguments( bundle ); // fragment.setArguments( bundle );
addFragmentImpl( fragment, parent ); // addFragmentImpl( fragment, parent );
} // }
private void addFragmentImpl( Fragment fragment, Delegator delegator ) // private void addFragmentImpl( Fragment fragment, Delegator delegator )
{ // {
String newName = fragment.getClass().getName(); // String newName = fragment.getClass().getName();
boolean replace = false; // boolean replace = false;
FragmentManager fm = getSupportFragmentManager(); // FragmentManager fm = getSupportFragmentManager();
int fragCount = fm.getBackStackEntryCount(); // int fragCount = fm.getBackStackEntryCount();
int containerCount = m_root.getChildCount(); // int containerCount = m_root.getChildCount();
DbgUtils.logf( "fragCount: %d; containerCount: %d", fragCount, containerCount ); // DbgUtils.logf( "fragCount: %d; containerCount: %d", fragCount, containerCount );
// Assert.assertTrue( fragCount == containerCount ); // // Assert.assertTrue( fragCount == containerCount );
// Replace IF we're adding something of the same class at right OR if // // Replace IF we're adding something of the same class at right OR if
// we're adding something with the existing left pane as its parent // // we're adding something with the existing left pane as its parent
// (delegator) // // (delegator)
if ( 0 < fragCount ) { // if ( 0 < fragCount ) {
FragmentManager.BackStackEntry entry = fm.getBackStackEntryAt( fragCount - 1 ); // FragmentManager.BackStackEntry entry = fm.getBackStackEntryAt( fragCount - 1 );
String curName = entry.getName(); // String curName = entry.getName();
DbgUtils.logf( "name of last entry: %s", curName ); // DbgUtils.logf( "name of last entry: %s", curName );
replace = curName.equals( newName ); // replace = curName.equals( newName );
if ( !replace && 1 < fragCount ) { // if ( !replace && 1 < fragCount ) {
entry = fm.getBackStackEntryAt( fragCount - 2 ); // entry = fm.getBackStackEntryAt( fragCount - 2 );
curName = entry.getName(); // curName = entry.getName();
String delName = delegator.getClass().getName(); // String delName = delegator.getClass().getName();
DbgUtils.logf( "comparing %s, %s", curName, delName ); // DbgUtils.logf( "comparing %s, %s", curName, delName );
replace = curName.equals( delName ); // replace = curName.equals( delName );
} // }
if ( replace ) { // if ( replace ) {
fm.popBackStack(); // fm.popBackStack();
} // }
} // }
// Replace doesn't seem to work with generated IDs, so we'll create a // // Replace doesn't seem to work with generated IDs, so we'll create a
// new FrameLayout each time. If we're replacing, we'll replace the // // new FrameLayout each time. If we're replacing, we'll replace the
// current rightmost FrameLayout. Otherwise we'll add a new one. // // current rightmost FrameLayout. Otherwise we'll add a new one.
FrameLayout cont = new FrameLayout( this ); // FrameLayout cont = new FrameLayout( this );
cont.setLayoutParams( new LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f) ); // cont.setLayoutParams( new LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f) );
int id = --m_nextID; // int id = --m_nextID;
cont.setId( id ); // cont.setId( id );
m_root.addView( cont, replace ? containerCount - 1 : containerCount ); // m_root.addView( cont, replace ? containerCount - 1 : containerCount );
if ( !replace && containerCount >= m_maxPanes ) { // if ( !replace && containerCount >= m_maxPanes ) {
int indx = containerCount - m_maxPanes; // int indx = containerCount - m_maxPanes;
View child = m_root.getChildAt( indx ); // View child = m_root.getChildAt( indx );
child.setVisibility( View.GONE ); // child.setVisibility( View.GONE );
setMenuVisibility( child, false ); // setMenuVisibility( child, false );
DbgUtils.logf( "hiding %dth container", indx ); // DbgUtils.logf( "hiding %dth container", indx );
} // }
fm.beginTransaction() // fm.beginTransaction()
.add( id, fragment ) // .add( id, fragment )
.addToBackStack( newName ) // .addToBackStack( newName )
.commit(); // .commit();
// fm.executePendingTransactions(); // // fm.executePendingTransactions();
} // }
private void setVisiblePanes() // private void setVisiblePanes()
{ // {
// hide all but the right-most m_maxPanes children // // hide all but the right-most m_maxPanes children
int nPanes = m_root.getChildCount(); // int nPanes = m_root.getChildCount();
for ( int ii = 0; ii < nPanes; ++ii ) { // for ( int ii = 0; ii < nPanes; ++ii ) {
View child = m_root.getChildAt( ii ); // View child = m_root.getChildAt( ii );
boolean visible = ii >= nPanes - m_maxPanes; // boolean visible = ii >= nPanes - m_maxPanes;
DbgUtils.logf( "pane %d: visible=%b", ii, visible ); // DbgUtils.logf( "pane %d: visible=%b", ii, visible );
child.setVisibility( visible ? View.VISIBLE : View.GONE ); // child.setVisibility( visible ? View.VISIBLE : View.GONE );
setMenuVisibility( child, visible ); // setMenuVisibility( child, visible );
} // }
} // }
private void setMenuVisibility( View cont, boolean visible ) // private void setMenuVisibility( View cont, boolean visible )
{ // {
FrameLayout layout = (FrameLayout)cont; // FrameLayout layout = (FrameLayout)cont;
FragmentManager fm = getSupportFragmentManager(); // FragmentManager fm = getSupportFragmentManager();
int hidingId = layout.getId(); // int hidingId = layout.getId();
Fragment frag = fm.findFragmentById( hidingId ); // Fragment frag = fm.findFragmentById( hidingId );
if ( null != frag ) { // hasn't been popped? // if ( null != frag ) { // hasn't been popped?
frag.setMenuVisibility( visible ); // frag.setMenuVisibility( visible );
} // }
} // }
// Walk all Fragment children and if they care notify of change. // // Walk all Fragment children and if they care notify of change.
private void tellOrientationChanged() // private void tellOrientationChanged()
{ // {
FragmentManager fm = getSupportFragmentManager(); // FragmentManager fm = getSupportFragmentManager();
int nPanes = m_root.getChildCount(); // int nPanes = m_root.getChildCount();
for ( int ii = 0; ii < nPanes; ++ii ) { // for ( int ii = 0; ii < nPanes; ++ii ) {
FrameLayout frame = (FrameLayout)m_root.getChildAt( ii ); // FrameLayout frame = (FrameLayout)m_root.getChildAt( ii );
int id = frame.getId(); // int id = frame.getId();
Fragment frag = fm.findFragmentById( id ); // Fragment frag = fm.findFragmentById( id );
if ( null == frag ) { // if ( null == frag ) {
DbgUtils.logf( "tellOrienationChanged: NO FRAG at %d, id=%d", ii, id ); // DbgUtils.logf( "tellOrienationChanged: NO FRAG at %d, id=%d", ii, id );
} else if ( frag instanceof OrientChangeListener ) { // } else if ( frag instanceof XWFragment ) {
((OrientChangeListener)frag).orientationChanged(); // ((XWFragment)frag).getDelegate().orientationChanged();
} // }
} // }
} // }
private int maxPanes() // private int maxPanes()
{ // {
int result; // int result;
int orientation = getResources().getConfiguration().orientation; // int orientation = getResources().getConfiguration().orientation;
if ( XWPrefs.getIsTablet( this ) // if ( XWPrefs.getIsTablet( this )
&& Configuration.ORIENTATION_LANDSCAPE == orientation ) { // && Configuration.ORIENTATION_LANDSCAPE == orientation ) {
result = 2; // result = 2;
} else { // } else {
result = 1; // result = 1;
} // }
return result; // return result;
} // }
private static FragActivity getThis() // private static FragActivity getThis()
{ // {
Assert.assertNotNull( s_this ); // Assert.assertNotNull( s_this );
return s_this; // return s_this;
} // }
public static void addFragment( Fragment fragment, Bundle bundle ) // public static void addFragment( Fragment fragment, Bundle bundle )
{ // {
addFragment( fragment, bundle, null ); // addFragment( fragment, bundle, null );
} // }
public static void addFragment( Fragment fragment, Bundle bundle, // public static void addFragment( Fragment fragment, Bundle bundle,
Delegator parent ) // Delegator parent )
{ // {
getThis().addFragmentImpl( fragment, bundle, parent ); // getThis().addFragmentImpl( fragment, bundle, parent );
} // }
public static void addFragmentForResult( Fragment fragment, Bundle bundle, // public static void addFragmentForResult( Fragment fragment, Bundle bundle,
RequestCode requestCode, Delegator parent ) // RequestCode requestCode, Delegator parent )
{ // {
getThis().addFragmentImpl( fragment, bundle, parent ); // getThis().addFragmentImpl( fragment, bundle, parent );
} // }
} // }

View file

@ -65,7 +65,7 @@ public class GameConfigDelegate extends DelegateBase
,XWListItem.DeleteCallback ,XWListItem.DeleteCallback
,RefreshNamesTask.NoNameFound { ,RefreshNamesTask.NoNameFound {
private static final String INTENT_FORRESULT_ROWID = "forresult"; private static final String INTENT_FORRESULT_NEWGAME = "newgame";
private static final String WHICH_PLAYER = "WHICH_PLAYER"; private static final String WHICH_PLAYER = "WHICH_PLAYER";
@ -73,6 +73,7 @@ public class GameConfigDelegate extends DelegateBase
private CheckBox m_joinPublicCheck; private CheckBox m_joinPublicCheck;
private CheckBox m_gameLockedCheck; private CheckBox m_gameLockedCheck;
private boolean m_isLocked; private boolean m_isLocked;
private boolean m_haveClosed;
private LinearLayout m_publicRoomsSet; private LinearLayout m_publicRoomsSet;
private LinearLayout m_privateRoomsSet; private LinearLayout m_privateRoomsSet;
@ -88,9 +89,10 @@ public class GameConfigDelegate extends DelegateBase
private Spinner m_roomChoose; private Spinner m_roomChoose;
// private Button m_configureButton; // private Button m_configureButton;
private long m_rowid; private long m_rowid;
private boolean m_forResult; private boolean m_isNewGame;
private CurGameInfo m_gi; private CurGameInfo m_gi;
private CurGameInfo m_giOrig; private CurGameInfo m_giOrig;
private JNIThread m_jniThread;
private int m_whichPlayer; private int m_whichPlayer;
// private Spinner m_roleSpinner; // private Spinner m_roleSpinner;
// private Spinner m_connectSpinner; // private Spinner m_connectSpinner;
@ -181,8 +183,9 @@ public class GameConfigDelegate extends DelegateBase
public void public void
onClick( DialogInterface dlg, onClick( DialogInterface dlg,
int button ) { int button ) {
getPlayerSettings( dlg ); GameConfigDelegate self = curThis();
loadPlayersList(); self.getPlayerSettings( dlg );
self.loadPlayersList();
} }
}) })
.setNegativeButton( android.R.string.cancel, null ) .setNegativeButton( android.R.string.cancel, null )
@ -210,7 +213,7 @@ public class GameConfigDelegate extends DelegateBase
dlpos = new DialogInterface.OnClickListener() { dlpos = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int whichButton ) { int whichButton ) {
loadPlayersList(); curThis().loadPlayersList();
} }
}; };
dialog = makeAlertBuilder() dialog = makeAlertBuilder()
@ -223,9 +226,14 @@ public class GameConfigDelegate extends DelegateBase
@Override @Override
public void onDismiss( DialogInterface di ) public void onDismiss( DialogInterface di )
{ {
if ( m_gi.forceRemoteConsistent() ) { GameConfigDelegate self = curThis();
showToast( R.string.forced_consistent ); if ( null != self
loadPlayersList(); && self.m_gi.forceRemoteConsistent() ) {
self.showToast( R.string.forced_consistent );
self.loadPlayersList();
} else {
DbgUtils.logf( "GameConfigDelegate.onDismiss(): "
+ "no visible self" );
} }
} }
}; };
@ -236,9 +244,10 @@ public class GameConfigDelegate extends DelegateBase
dlpos = new DialogInterface.OnClickListener() { dlpos = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int whichButton ) { int whichButton ) {
applyChanges( true ); GameConfigDelegate self = curThis();
self.applyChanges( true );
if ( DlgID.CONFIRM_CHANGE_PLAY == dlgID ) { if ( DlgID.CONFIRM_CHANGE_PLAY == dlgID ) {
launchGame(); self.launchGame( true );
} }
} }
}; };
@ -250,7 +259,7 @@ public class GameConfigDelegate extends DelegateBase
dlpos = new DialogInterface.OnClickListener() { dlpos = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int whichButton ) { int whichButton ) {
launchGame(); curThis().finishAndLaunch();
} }
}; };
} else { } else {
@ -262,7 +271,7 @@ public class GameConfigDelegate extends DelegateBase
dialog.setOnDismissListener( new DialogInterface. dialog.setOnDismissListener( new DialogInterface.
OnDismissListener() { OnDismissListener() {
public void onDismiss( DialogInterface di ) { public void onDismiss( DialogInterface di ) {
finish(); curThis().closeNoSave();
} }
}); });
break; break;
@ -288,16 +297,17 @@ public class GameConfigDelegate extends DelegateBase
final DialogInterface.OnClickListener lstnr = final DialogInterface.OnClickListener lstnr =
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int button ) { public void onClick( DialogInterface dlg, int button ) {
m_conTypes = items.getTypes(); GameConfigDelegate self = curThis();
self.m_conTypes = items.getTypes();
if ( cb.isChecked()) { if ( cb.isChecked()) {
XWPrefs.setAddrTypes( m_activity, m_conTypes ); XWPrefs.setAddrTypes( self.m_activity, self.m_conTypes );
} }
m_car.populate( m_activity, m_conTypes ); self.m_car.populate( self.m_activity, self.m_conTypes );
setConnLabel(); self.setConnLabel();
setupRelayStuffIf( false ); self.setupRelayStuffIf( false );
showHideRelayStuff(); self.showHideRelayStuff();
} }
}; };
@ -474,7 +484,7 @@ public class GameConfigDelegate extends DelegateBase
Bundle args = getArguments(); Bundle args = getArguments();
m_rowid = args.getLong( GameUtils.INTENT_KEY_ROWID, DBUtils.ROWID_NOTFOUND ); m_rowid = args.getLong( GameUtils.INTENT_KEY_ROWID, DBUtils.ROWID_NOTFOUND );
Assert.assertTrue( DBUtils.ROWID_NOTFOUND != m_rowid ); Assert.assertTrue( DBUtils.ROWID_NOTFOUND != m_rowid );
m_forResult = args.getBoolean( INTENT_FORRESULT_ROWID, false ); m_isNewGame = args.getBoolean( INTENT_FORRESULT_NEWGAME, false );
m_connectSetRelay = findViewById( R.id.connect_set_relay ); m_connectSetRelay = findViewById( R.id.connect_set_relay );
@ -509,6 +519,7 @@ public class GameConfigDelegate extends DelegateBase
@Override @Override
protected void onResume() protected void onResume()
{ {
m_jniThread = JNIThread.getRetained( m_rowid );
super.onResume(); super.onResume();
loadGame(); loadGame();
} }
@ -517,6 +528,10 @@ public class GameConfigDelegate extends DelegateBase
{ {
m_giOrig = null; // flag for onStart and onResume m_giOrig = null; // flag for onStart and onResume
super.onPause(); super.onPause();
if ( null != m_jniThread ) {
m_jniThread.release();
m_jniThread = null;
}
} }
protected void onSaveInstanceState( Bundle outState ) protected void onSaveInstanceState( Bundle outState )
@ -551,8 +566,16 @@ public class GameConfigDelegate extends DelegateBase
if ( null == m_giOrig ) { if ( null == m_giOrig ) {
m_giOrig = new CurGameInfo( m_activity ); m_giOrig = new CurGameInfo( m_activity );
GameLock gameLock = new GameLock( m_rowid, false ).lock(); GameLock gameLock;
XwJNI.GamePtr gamePtr = GameUtils.loadMakeGame( m_activity, m_giOrig, gameLock ); XwJNI.GamePtr gamePtr;
if ( null == m_jniThread ) {
gameLock = new GameLock( m_rowid, false ).lock();
gamePtr = GameUtils.loadMakeGame( m_activity, m_giOrig, gameLock );
} else {
gameLock = m_jniThread.getLock();
gamePtr = m_jniThread.getGamePtr();
}
if ( null == gamePtr ) { if ( null == gamePtr ) {
showDictGoneFinish(); showDictGoneFinish();
} else { } else {
@ -584,9 +607,11 @@ public class GameConfigDelegate extends DelegateBase
relayPort ); relayPort );
} }
m_conTypes = (CommsConnTypeSet)m_carOrig.conTypes.clone(); m_conTypes = (CommsConnTypeSet)m_carOrig.conTypes.clone();
gamePtr.release();
gameLock.unlock(); if ( null == m_jniThread ) {
gamePtr.release();
gameLock.unlock();
}
m_car = new CommsAddrRec( m_carOrig ); m_car = new CommsAddrRec( m_carOrig );
@ -658,6 +683,8 @@ public class GameConfigDelegate extends DelegateBase
public void dlgButtonClicked( Action action, int button, Object[] params ) public void dlgButtonClicked( Action action, int button, Object[] params )
{ {
boolean callSuper = false; boolean callSuper = false;
Assert.assertTrue( curThis() == this );
if ( AlertDialog.BUTTON_POSITIVE == button ) { if ( AlertDialog.BUTTON_POSITIVE == button ) {
switch( action ) { switch( action ) {
case LOCKED_CHANGE_ACTION: case LOCKED_CHANGE_ACTION:
@ -667,10 +694,10 @@ public class GameConfigDelegate extends DelegateBase
Utils.launchSettings( m_activity ); Utils.launchSettings( m_activity );
break; break;
case DELETE_AND_EXIT: case DELETE_AND_EXIT:
if ( m_forResult ) { if ( m_isNewGame ) {
deleteGame(); deleteGame();
} }
finish(); closeNoSave();
break; break;
case SET_ENABLE_PUBLIC: case SET_ENABLE_PUBLIC:
XWPrefs.setPrefsBoolean( m_activity, R.string.key_enable_pubroom, XWPrefs.setPrefsBoolean( m_activity, R.string.key_enable_pubroom,
@ -727,26 +754,19 @@ public class GameConfigDelegate extends DelegateBase
// from here if there's no confirmation needed, or launch // from here if there's no confirmation needed, or launch
// a new dialog whose OK button does the same thing. // a new dialog whose OK button does the same thing.
saveChanges(); saveChanges();
if ( !localOnlyGame() && 0 == m_conTypes.size() ) { if ( !localOnlyGame() && 0 == m_conTypes.size() ) {
showConfirmThen( R.string.config_no_connvia, showConfirmThen( R.string.config_no_connvia,
R.string.button_discard, R.string.button_discard,
R.string.button_edit, R.string.button_edit,
Action.DELETE_AND_EXIT ); Action.DELETE_AND_EXIT );
} else if ( m_forResult ) { } else if ( m_isNewGame || !m_gameStarted ) {
applyChanges( true ); saveAndClose( true );
Intent intent = new Intent();
intent.putExtra( GameUtils.INTENT_KEY_ROWID, m_rowid );
setResult( Activity.RESULT_OK, intent );
finish();
} else if ( !m_gameStarted ) { // no confirm needed
applyChanges( true );
launchGame();
} else if ( m_giOrig.changesMatter(m_gi) } else if ( m_giOrig.changesMatter(m_gi)
|| m_carOrig.changesMatter(m_car) ) { || m_carOrig.changesMatter(m_car) ) {
showDialog( DlgID.CONFIRM_CHANGE_PLAY ); showDialog( DlgID.CONFIRM_CHANGE_PLAY );
} else { } else {
applyChanges( false ); finishAndLaunch();
launchGame();
} }
} else { } else {
@ -754,12 +774,42 @@ public class GameConfigDelegate extends DelegateBase
} }
} // onClick } // onClick
private void saveAndClose( boolean forceNew )
{
DbgUtils.logf( "GameConfigDelegate.saveAndClose(forceNew=%b)",
forceNew );
applyChanges( forceNew );
finishAndLaunch();
}
private void finishAndLaunch()
{
if ( !m_haveClosed ) {
m_haveClosed = true;
DbgUtils.logf( "GameConfigDelegate.finishAndLaunch()" );
Intent intent = new Intent();
intent.putExtra( GameUtils.INTENT_KEY_ROWID, m_rowid );
setResult( Activity.RESULT_OK, intent );
finish();
}
}
private void closeNoSave()
{
if ( !m_haveClosed ) {
m_haveClosed = true;
setResult( Activity.RESULT_CANCELED, null );
finish();
}
}
@Override @Override
protected boolean onBackPressed() protected boolean handleBackPressed()
{ {
boolean consumed = false; boolean consumed = false;
if ( ! isFinishing() ) { if ( ! isFinishing() ) {
if ( m_forResult ) { if ( m_isNewGame ) {
deleteGame(); deleteGame();
} else { } else {
saveChanges(); saveChanges();
@ -778,6 +828,12 @@ public class GameConfigDelegate extends DelegateBase
return consumed; return consumed;
} }
@Override
protected GameConfigDelegate curThis()
{
return (GameConfigDelegate)super.curThis();
}
private void deleteGame() private void deleteGame()
{ {
GameUtils.deleteGame( m_activity, m_rowid, false ); GameUtils.deleteGame( m_activity, m_rowid, false );
@ -1162,21 +1218,25 @@ public class GameConfigDelegate extends DelegateBase
private void applyChanges( boolean forceNew ) private void applyChanges( boolean forceNew )
{ {
if ( !isFinishing() ) { if ( !isFinishing() ) {
GameLock gameLock = new GameLock( m_rowid, true ).lock(); GameLock gameLock = m_jniThread == null
? new GameLock( m_rowid, true ).lock()
: m_jniThread.getLock();
GameUtils.applyChanges( m_activity, m_gi, m_car, gameLock, GameUtils.applyChanges( m_activity, m_gi, m_car, gameLock,
forceNew ); forceNew );
DBUtils.saveThumbnail( m_activity, gameLock, null ); // clear it DBUtils.saveThumbnail( m_activity, gameLock, null ); // clear it
gameLock.unlock(); if ( null == m_jniThread ) {
gameLock.unlock();
}
} }
} }
private void launchGame() private void launchGame( boolean forceNew )
{ {
if ( m_conTypes.contains( CommsConnType.COMMS_CONN_RELAY ) if ( m_conTypes.contains( CommsConnType.COMMS_CONN_RELAY )
&& 0 == m_car.ip_relay_invite.length() ) { && 0 == m_car.ip_relay_invite.length() ) {
showOKOnlyDialog( R.string.no_empty_rooms ); showOKOnlyDialog( R.string.no_empty_rooms );
} else { } else {
GameUtils.launchGameAndFinish( getDelegator(), m_rowid ); saveAndClose( forceNew );
} }
} }
@ -1207,17 +1267,17 @@ public class GameConfigDelegate extends DelegateBase
public static void editForResult( Delegator delegator, public static void editForResult( Delegator delegator,
RequestCode requestCode, RequestCode requestCode,
long rowID ) long rowID, boolean newGame )
{ {
Activity activity = delegator.getActivity();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putLong( GameUtils.INTENT_KEY_ROWID, rowID ); bundle.putLong( GameUtils.INTENT_KEY_ROWID, rowID );
bundle.putBoolean( INTENT_FORRESULT_ROWID, true ); bundle.putBoolean( INTENT_FORRESULT_NEWGAME, newGame );
if ( activity instanceof FragActivity ) { if ( delegator.inDPMode() ) {
FragActivity.addFragmentForResult( new GameConfigFrag(), bundle, delegator.addFragmentForResult( new GameConfigFrag( delegator ),
requestCode, delegator ); bundle, requestCode );
} else { } else {
Activity activity = delegator.getActivity();
Intent intent = new Intent( activity, GameConfigActivity.class ); Intent intent = new Intent( activity, GameConfigActivity.class );
intent.setAction( Intent.ACTION_EDIT ); intent.setAction( Intent.ACTION_EDIT );
intent.putExtras( bundle ); intent.putExtras( bundle );

View file

@ -23,6 +23,8 @@ import android.os.Bundle;
public class GameConfigFrag extends XWFragment { public class GameConfigFrag extends XWFragment {
public GameConfigFrag( Delegator parent ) { super( parent ); }
@Override @Override
public void onCreate( Bundle sis ) public void onCreate( Bundle sis )
{ {

View file

@ -198,9 +198,7 @@ public class GameListItem extends LinearLayout
m_state = (TextView)findViewById( R.id.state ); m_state = (TextView)findViewById( R.id.state );
m_modTime = (TextView)findViewById( R.id.modtime ); m_modTime = (TextView)findViewById( R.id.modtime );
m_marker = (ImageView)findViewById( R.id.msg_marker ); m_marker = (ImageView)findViewById( R.id.msg_marker );
if ( BuildConstants.THUMBNAIL_SUPPORTED ) { m_thumb = (ImageView)findViewById( R.id.thumbnail );
m_thumb = (ImageView)findViewById( R.id.thumbnail );
}
m_role = (TextView)findViewById( R.id.role ); m_role = (TextView)findViewById( R.id.role );
} }
@ -221,11 +219,10 @@ 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 );
if ( BuildConstants.THUMBNAIL_SUPPORTED ) {
int vis = m_expanded && XWPrefs.getThumbEnabled( m_context ) int vis = m_expanded && XWPrefs.getThumbEnabled( m_context )
? View.VISIBLE : View.GONE; ? View.VISIBLE : View.GONE;
m_thumb.setVisibility( vis ); m_thumb.setVisibility( vis );
}
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,
@ -354,26 +351,30 @@ public class GameListItem extends LinearLayout
@Override @Override
protected GameSummary doInBackground( Void... unused ) protected GameSummary doInBackground( Void... unused )
{ {
return DBUtils.getSummary( m_context, m_rowid, SUMMARY_WAIT_MSECS ); GameSummary result = null;
JNIThread thread = JNIThread.getRetained( m_rowid );
if ( null != thread ) {
GameLock lock = thread.getLock();
if ( null != lock ) {
result = DBUtils.getSummary( m_context, lock );
}
thread.release( false );
}
if ( null == result ) {
result = DBUtils.getSummary( m_context, m_rowid, SUMMARY_WAIT_MSECS );
}
return result;
} // doInBackground } // doInBackground
@Override @Override
protected void onPostExecute( GameSummary summary ) protected void onPostExecute( GameSummary summary )
{ {
if ( 0 == --m_loadingCount ) { if ( 0 == --m_loadingCount ) {
if ( null == summary ) {
// Try again. Maybe it's open
JNIThread thread = JNIThread.getRetained( m_rowid );
if ( null != thread ) {
summary = DBUtils.getSummary( m_context,
thread.getLock() );
thread.release();
}
}
m_summary = summary; m_summary = summary;
boolean expanded = DBUtils.getExpanded( m_context, m_rowid );
boolean expanded = DBUtils.getExpanded( m_context, m_rowid );
makeThumbnailIf( expanded ); makeThumbnailIf( expanded );
setData( summary, expanded ); setData( summary, expanded );
@ -448,14 +449,12 @@ public class GameListItem extends LinearLayout
private static void enqueueGetThumbnail( GameListItem item, long rowid ) private static void enqueueGetThumbnail( GameListItem item, long rowid )
{ {
if ( BuildConstants.THUMBNAIL_SUPPORTED ) { s_queue.add( new ThumbQueueElem( item, rowid ) );
s_queue.add( new ThumbQueueElem( item, rowid ) );
synchronized( GameListItem.class ) { synchronized( GameListItem.class ) {
if ( null == s_thumbThread ) { if ( null == s_thumbThread ) {
s_thumbThread = makeThumbThread(); s_thumbThread = makeThumbThread();
s_thumbThread.start(); s_thumbThread.start();
}
} }
} }
} }

View file

@ -160,7 +160,7 @@ public class GameLock {
if ( DEBUG_LOCKS ) { if ( DEBUG_LOCKS ) {
DbgUtils.logf( "lock %H overlocked", this ); DbgUtils.logf( "lock %H overlocked", this );
} }
Assert.fail(); // firing Assert.fail();
} }
} }
// DbgUtils.logf( "GameLock.lock(%s) done", m_path ); // DbgUtils.logf( "GameLock.lock(%s) done", m_path );

View file

@ -150,8 +150,9 @@ public class GameUtils {
return lockDest; return lockDest;
} // resetGame } // resetGame
public static void resetGame( Context context, long rowidIn ) public static boolean resetGame( Context context, long rowidIn )
{ {
boolean success = false;
GameLock lock = new GameLock( rowidIn, true ).lock( 500 ); GameLock lock = new GameLock( rowidIn, true ).lock( 500 );
if ( null != lock ) { if ( null != lock ) {
tellDied( context, lock, true ); tellDied( context, lock, true );
@ -159,9 +160,11 @@ public class GameUtils {
lock.unlock(); lock.unlock();
Utils.cancelNotification( context, (int)rowidIn ); Utils.cancelNotification( context, (int)rowidIn );
success = true;
} else { } else {
DbgUtils.logf( "resetGame: unable to open rowid %d", rowidIn ); DbgUtils.logf( "resetGame: unable to open rowid %d", rowidIn );
} }
return success;
} }
private static int setFromFeedImpl( FeedUtilsImpl feedImpl ) private static int setFromFeedImpl( FeedUtilsImpl feedImpl )
@ -289,10 +292,17 @@ public class GameUtils {
public static GamePtr loadMakeGame( Context context, CurGameInfo gi, public static GamePtr loadMakeGame( Context context, CurGameInfo gi,
UtilCtxt util, TransportProcs tp, UtilCtxt util, TransportProcs tp,
GameLock lock ) GameLock lock )
{
byte[] stream = savedGame( context, lock );
return loadMakeGame( context, gi, util, tp, stream, lock.getRowid() );
}
private static GamePtr loadMakeGame( Context context, CurGameInfo gi,
UtilCtxt util, TransportProcs tp,
byte[] stream, long rowid )
{ {
GamePtr gamePtr = null; GamePtr gamePtr = null;
byte[] stream = savedGame( context, lock );
if ( null == stream ) { if ( null == stream ) {
DbgUtils.logf( "loadMakeGame: no saved game!"); DbgUtils.logf( "loadMakeGame: no saved game!");
} else { } else {
@ -303,7 +313,7 @@ public class GameUtils {
DbgUtils.logf( "loadMakeGame() failing: dicts %s unavailable", DbgUtils.logf( "loadMakeGame() failing: dicts %s unavailable",
TextUtils.join( ",", dictNames ) ); TextUtils.join( ",", dictNames ) );
} else { } else {
gamePtr = XwJNI.initJNI( lock.getRowid() ); gamePtr = XwJNI.initJNI( rowid );
String langName = gi.langName(); String langName = gi.langName();
boolean madeGame = boolean madeGame =
@ -324,59 +334,72 @@ public class GameUtils {
return gamePtr; return gamePtr;
} }
public static Bitmap loadMakeBitmap( Activity activity, long rowid ) public static Bitmap loadMakeBitmap( Context context, long rowid )
{ {
Bitmap thumb = null; Bitmap thumb = null;
GameLock lock = new GameLock( rowid, false ); GameLock lock = new GameLock( rowid, false );
if ( lock.tryLock() ) { if ( lock.tryLock() ) {
CurGameInfo gi = new CurGameInfo( activity ); CurGameInfo gi = new CurGameInfo( context );
GamePtr gamePtr = loadMakeGame( activity, gi, lock ); GamePtr gamePtr = loadMakeGame( context, gi, lock );
if ( null != gamePtr ) { if ( null != gamePtr ) {
thumb = takeSnapshot( activity, gamePtr, gi ); thumb = takeSnapshot( context, gamePtr, gi );
gamePtr.release(); gamePtr.release();
DBUtils.saveThumbnail( activity, lock, thumb ); DBUtils.saveThumbnail( context, lock, thumb );
} }
lock.unlock(); lock.unlock();
} }
return thumb; return thumb;
} }
public static Bitmap loadMakeBitmap( Context context, byte[] stream,
GameLock lock )
{
Bitmap thumb = null;
CurGameInfo gi = new CurGameInfo( context );
GamePtr gamePtr = loadMakeGame( context, gi, null, null, stream,
lock.getRowid() );
if ( null != gamePtr ) {
thumb = takeSnapshot( context, gamePtr, gi );
gamePtr.release();
DBUtils.saveThumbnail( context, lock, thumb );
}
return thumb;
}
public static Bitmap takeSnapshot( Context context, GamePtr gamePtr, public static Bitmap takeSnapshot( Context context, GamePtr gamePtr,
CurGameInfo gi ) CurGameInfo gi )
{ {
Bitmap thumb = null; Bitmap thumb = null;
if ( BuildConstants.THUMBNAIL_SUPPORTED ) { if ( XWPrefs.getThumbEnabled( context ) ) {
if ( XWPrefs.getThumbEnabled( context ) ) { int nCols = gi.boardSize;
int nCols = gi.boardSize; int pct = XWPrefs.getThumbPct( context );
int pct = XWPrefs.getThumbPct( context ); Assert.assertTrue( 0 < pct );
Assert.assertTrue( 0 < pct );
if ( null == s_minScreen ) { if ( null == s_minScreen ) {
if ( context instanceof Activity ) { if ( context instanceof Activity ) {
Activity activity = (Activity)context; Activity activity = (Activity)context;
Display display = Display display =
activity.getWindowManager().getDefaultDisplay(); activity.getWindowManager().getDefaultDisplay();
int width = display.getWidth(); int width = display.getWidth();
int height = display.getHeight(); int height = display.getHeight();
s_minScreen = new Integer( Math.min( width, height ) ); s_minScreen = new Integer( Math.min( width, height ) );
}
} }
if ( null != s_minScreen ) { }
int dim = s_minScreen * pct / 100; if ( null != s_minScreen ) {
int size = dim - (dim % nCols); int dim = s_minScreen * pct / 100;
int size = dim - (dim % nCols);
thumb = Bitmap.createBitmap( size, size, thumb = Bitmap.createBitmap( size, size,
Bitmap.Config.ARGB_8888 ); Bitmap.Config.ARGB_8888 );
XwJNI.board_figureLayout( gamePtr, gi, 0, 0, size, size, XwJNI.board_figureLayout( gamePtr, gi, 0, 0, size, size,
0, 0, 0, 20, 20, false, null ); 0, 0, 0, 20, 20, false, null );
ThumbCanvas canvas = new ThumbCanvas( context, thumb ); ThumbCanvas canvas = new ThumbCanvas( context, thumb );
XwJNI.board_setDraw( gamePtr, canvas ); XwJNI.board_setDraw( gamePtr, canvas );
XwJNI.board_invalAll( gamePtr ); XwJNI.board_invalAll( gamePtr );
Assert.assertNotNull( gamePtr ); Assert.assertNotNull( gamePtr );
XwJNI.board_draw( gamePtr ); XwJNI.board_draw( gamePtr );
}
} }
} }
return thumb; return thumb;
@ -851,11 +874,11 @@ public class GameUtils {
public static void launchGame( Delegator delegator, long rowid, public static void launchGame( Delegator delegator, long rowid,
boolean invited ) boolean invited )
{ {
Activity activity = delegator.getActivity();
Bundle extras = makeLaunchExtras( rowid, invited ); Bundle extras = makeLaunchExtras( rowid, invited );
if ( activity instanceof FragActivity ) { if ( delegator.inDPMode() ) {
FragActivity.addFragment( new BoardFrag(), extras, delegator ); delegator.addFragment( new BoardFrag( delegator ), extras );
} else { } else {
Activity activity = delegator.getActivity();
Intent intent = new Intent( activity, BoardActivity.class ); Intent intent = new Intent( activity, BoardActivity.class );
intent.putExtras( extras ); intent.putExtras( extras );
activity.startActivity( intent ); activity.startActivity( intent );
@ -867,12 +890,6 @@ public class GameUtils {
launchGame( delegator, rowid, false ); launchGame( delegator, rowid, false );
} }
public static void launchGameAndFinish( Delegator delegator, long rowid )
{
launchGame( delegator, rowid );
delegator.getActivity().finish();
}
private static class FeedUtilsImpl extends UtilCtxtImpl { private static class FeedUtilsImpl extends UtilCtxtImpl {
private Context m_context; private Context m_context;
private long m_rowid; private long m_rowid;
@ -1087,22 +1104,6 @@ public class GameUtils {
DBUtils.saveSummary( context, lock, summary ); DBUtils.saveSummary( context, lock, summary );
} // applyChanges } // applyChanges
public static void doConfig( Delegator delegator, long rowid )
{
Bundle extras = new Bundle();
extras.putLong( INTENT_KEY_ROWID, rowid );
Activity activity = delegator.getActivity();
if ( activity instanceof FragActivity ) {
FragActivity.addFragment( new GameConfigFrag(), extras, delegator );
} else {
Intent intent = new Intent( activity, GameConfigActivity.class );
intent.setAction( Intent.ACTION_EDIT );
intent.putExtras( extras );
activity.startActivity( intent );
}
}
public static String formatGameID( int gameID ) public static String formatGameID( int gameID )
{ {
Assert.assertTrue( 0 != gameID ); Assert.assertTrue( 0 != gameID );
@ -1126,14 +1127,6 @@ public class GameUtils {
return rint; return rint;
} }
// public static void postSelfNotification( Context context, long rowid )
// {
// Assert.assertTrue( BuildConfig.DEBUG );
// Intent intent = GamesListDelegate.makeRowidIntent( context, rowid );
// Utils.postNotification( context, intent, "launch",
// String.format("%d", rowid), (int)rowid );
// }
public static void postMoveNotification( Context context, long rowid, public static void postMoveNotification( Context context, long rowid,
BackMoveResult bmr, BackMoveResult bmr,
boolean isTurnNow ) boolean isTurnNow )

View file

@ -1,65 +0,0 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2009 - 2014 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.Intent;
import android.net.Uri;
import android.os.Bundle;
import org.eehouse.android.xw4.jni.CurGameInfo;
import junit.framework.Assert;
public class GamesListActivity extends XWActivity {
private GamesListDelegate m_dlgt;
@Override
protected void onCreate( Bundle savedInstanceState )
{
m_dlgt = new GamesListDelegate( this, savedInstanceState );
super.onCreate( savedInstanceState, m_dlgt );
// Trying to debug situation where two of this activity are running at
// once. finish()ing when Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT is
// passed is not the fix, but perhaps there's another
// int flags = getIntent().getFlags();
// DbgUtils.logf( "GamesListActivity.onCreate(this=%H): flags=0x%x",
// this, flags );
} // onCreate
// called when we're brought to the front (probably as a result of
// notification)
@Override
protected void onNewIntent( Intent intent )
{
super.onNewIntent( intent );
m_dlgt.onNewIntent( intent );
}
//////////////////////////////////////////////////////////////////////
// GamesListDelegator interface
//////////////////////////////////////////////////////////////////////
public void launchGame( long rowID, boolean invited )
{
GameUtils.launchGame( this, rowID, invited );
}
}

View file

@ -404,6 +404,11 @@ public class GamesListDelegate extends ListDelegateBase
List<Object> alist = new ArrayList<Object>(); List<Object> alist = new ArrayList<Object>();
long[] rows = DBUtils.getGroupGames( m_activity, groupID ); long[] rows = DBUtils.getGroupGames( m_activity, groupID );
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() );
@ -615,18 +620,20 @@ public class GamesListDelegate extends ListDelegateBase
case WARN_NODICT_SUBST: case WARN_NODICT_SUBST:
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
GamesListDelegate self = curThis();
// no name, so user must pick // no name, so user must pick
if ( null == m_missingDictName ) { if ( null == m_missingDictName ) {
DictsDelegate.downloadForResult( m_activity, DictsDelegate
RequestCode .downloadForResult( self.m_activity,
.REQUEST_LANG_GL, RequestCode
m_missingDictLang ); .REQUEST_LANG_GL,
self.m_missingDictLang );
} else { } else {
DwnldDelegate DwnldDelegate
.downloadDictInBack( m_activity, .downloadDictInBack( self.m_activity,
m_missingDictLang, self.m_missingDictLang,
m_missingDictName, self.m_missingDictName,
GamesListDelegate.this ); self );
} }
} }
}; };
@ -655,7 +662,7 @@ public class GamesListDelegate extends ListDelegateBase
if ( DlgID.WARN_NODICT_SUBST == dlgID ) { if ( DlgID.WARN_NODICT_SUBST == dlgID ) {
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
showDialog( DlgID.SHOW_SUBST ); curThis().showDialog( DlgID.SHOW_SUBST );
} }
}; };
ab.setNeutralButton( R.string.button_substdict, lstnr ); ab.setNeutralButton( R.string.button_substdict, lstnr );
@ -669,15 +676,16 @@ public class GamesListDelegate extends ListDelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, public void onClick( DialogInterface dlg,
int which ) { int which ) {
GamesListDelegate self = curThis();
int pos = ((AlertDialog)dlg).getListView(). int pos = ((AlertDialog)dlg).getListView().
getCheckedItemPosition(); getCheckedItemPosition();
String dict = m_sameLangDicts[pos]; String dict = self.m_sameLangDicts[pos];
dict = DictLangCache.stripCount( dict ); dict = DictLangCache.stripCount( dict );
if ( GameUtils.replaceDicts( m_activity, if ( GameUtils.replaceDicts( self.m_activity,
m_missingDictRowId, self.m_missingDictRowId,
m_missingDictName, self.m_missingDictName,
dict ) ) { dict ) ) {
launchGameIf(); self.launchGameIf();
} }
} }
}; };
@ -697,10 +705,11 @@ public class GamesListDelegate extends ListDelegateBase
case RENAME_GAME: case RENAME_GAME:
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
String name = m_namer.getName(); GamesListDelegate self = curThis();
DBUtils.setName( m_activity, m_rowid, String name = self.m_namer.getName();
DBUtils.setName( self.m_activity, self.m_rowid,
name ); name );
m_adapter.invalName( m_rowid ); self.m_adapter.invalName( self.m_rowid );
} }
}; };
GameSummary summary = DBUtils.getSummary( m_activity, m_rowid ); GameSummary summary = DBUtils.getSummary( m_activity, m_rowid );
@ -714,11 +723,12 @@ public class GamesListDelegate extends ListDelegateBase
case RENAME_GROUP: case RENAME_GROUP:
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
String name = m_namer.getName(); GamesListDelegate self = curThis();
DBUtils.setGroupName( m_activity, String name = self.m_namer.getName();
m_groupid, name ); DBUtils.setGroupName( self.m_activity,
reloadGame( m_rowid ); self.m_groupid, name );
mkListAdapter(); self.reloadGame( self.m_rowid );
self.mkListAdapter();
} }
}; };
dialog = buildNamerDlg( m_adapter.groupName( m_groupid ), dialog = buildNamerDlg( m_adapter.groupName( m_groupid ),
@ -730,15 +740,16 @@ public class GamesListDelegate extends ListDelegateBase
case NEW_GROUP: case NEW_GROUP:
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
String name = m_namer.getName(); GamesListDelegate self = curThis();
DBUtils.addGroup( m_activity, name ); String name = self.m_namer.getName();
mkListAdapter(); DBUtils.addGroup( self.m_activity, name );
showNewGroupIf(); self.mkListAdapter();
self.showNewGroupIf();
} }
}; };
lstnr2 = new OnClickListener() { lstnr2 = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
showNewGroupIf(); curThis().showNewGroupIf();
} }
}; };
dialog = buildNamerDlg( "", R.string.newgroup_label, dialog = buildNamerDlg( "", R.string.newgroup_label,
@ -753,13 +764,14 @@ public class GamesListDelegate extends ListDelegateBase
final int[] selItem = {-1}; // hack!!!! final int[] selItem = {-1}; // hack!!!!
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlgi, int item ) { public void onClick( DialogInterface dlgi, int item ) {
GamesListDelegate self = curThis();
selItem[0] = item; selItem[0] = item;
AlertDialog dlg = (AlertDialog)dlgi; AlertDialog dlg = (AlertDialog)dlgi;
Button btn = Button btn =
dlg.getButton( AlertDialog.BUTTON_POSITIVE ); dlg.getButton( AlertDialog.BUTTON_POSITIVE );
boolean enabled = startGroup == -1; boolean enabled = startGroup == -1;
if ( !enabled ) { if ( !enabled ) {
long newGroup = m_adapter.getGroupIDFor( item ); long newGroup = self.m_adapter.getGroupIDFor( item );
enabled = newGroup != startGroup; enabled = newGroup != startGroup;
} }
btn.setEnabled( enabled ); btn.setEnabled( enabled );
@ -767,20 +779,22 @@ public class GamesListDelegate extends ListDelegateBase
}; };
lstnr2 = new OnClickListener() { lstnr2 = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
GamesListDelegate self = curThis();
Assert.assertTrue( -1 != selItem[0] ); Assert.assertTrue( -1 != selItem[0] );
long gid = m_adapter.getGroupIDFor( selItem[0] ); long gid = self.m_adapter.getGroupIDFor( selItem[0] );
for ( long rowid : m_rowids ) { for ( long rowid : self.m_rowids ) {
DBUtils.moveGame( m_activity, rowid, gid ); DBUtils.moveGame( self.m_activity, rowid, gid );
} }
DBUtils.setGroupExpanded( m_activity, gid, true ); DBUtils.setGroupExpanded( self.m_activity, gid, true );
mkListAdapter(); self.mkListAdapter();
} }
}; };
OnClickListener lstnr3 = OnClickListener lstnr3 =
new OnClickListener() { new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
m_moveAfterNewGroup = true; GamesListDelegate self = curThis();
showDialog( DlgID.NEW_GROUP ); self.m_moveAfterNewGroup = true;
self.showDialog( DlgID.NEW_GROUP );
} }
}; };
String[] groups = m_adapter.groupNames(); String[] groups = m_adapter.groupNames();
@ -828,12 +842,12 @@ public class GamesListDelegate extends ListDelegateBase
final EditText edit = (EditText)view.findViewById( R.id.edit ); final EditText edit = (EditText)view.findViewById( R.id.edit );
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
makeThenLaunchOrConfigure( edit, true, false ); curThis().makeThenLaunchOrConfigure( edit, true, false );
} }
}; };
lstnr2 = new OnClickListener() { lstnr2 = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
makeThenLaunchOrConfigure( edit, false, false ); curThis().makeThenLaunchOrConfigure( edit, false, false );
} }
}; };
@ -857,7 +871,7 @@ public class GamesListDelegate extends ListDelegateBase
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
EditText edit = (EditText)((Dialog)dlg) EditText edit = (EditText)((Dialog)dlg)
.findViewById( R.id.edit ); .findViewById( R.id.edit );
startRematchWithName( edit ); curThis().startRematchWithName( edit );
} }
} ) } )
.create(); .create();
@ -919,7 +933,6 @@ public class GamesListDelegate extends ListDelegateBase
protected void init( Bundle savedInstanceState ) protected void init( Bundle savedInstanceState )
{ {
m_origTitle = getTitle(); m_origTitle = getTitle();
Assert.assertTrue( m_origTitle.equals( getString(R.string.app_name) ) );
m_handler = new Handler(); m_handler = new Handler();
// Next line useful if contents of DB are crashing app on start // Next line useful if contents of DB are crashing app on start
@ -951,28 +964,28 @@ public class GamesListDelegate extends ListDelegateBase
NetUtils.informOfDeaths( m_activity ); NetUtils.informOfDeaths( m_activity );
tryStartsFromIntent( getIntent() ); post( new Runnable() {
@Override
public void run() {
tryStartsFromIntent( getIntent() );
getDictForLangIf();
}
} );
getDictForLangIf();
} // init } // init
// protected View onCreateView( Bundle savedInstanceState ) @Override
// { protected boolean handleNewIntent( Intent intent )
// View result = inflate( R.layout.game_list );
// // init( savedInstanceState );
// return result;
// }
// called when we're brought to the front (probably as a result of
// notification)
protected void onNewIntent( Intent intent )
{ {
// super.onNewIntent( intent ); DbgUtils.logf( "GamesListDelegate.handleNewIntent(%s)",
intent.toString() );
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
} }
protected void onStop() protected void onStop()
@ -1051,6 +1064,12 @@ public class GamesListDelegate extends ListDelegateBase
} }
} }
@Override
protected GamesListDelegate curThis()
{
return (GamesListDelegate)super.curThis();
}
// OnItemLongClickListener interface // OnItemLongClickListener interface
public boolean onItemLongClick( AdapterView<?> parent, View view, public boolean onItemLongClick( AdapterView<?> parent, View view,
int position, long id ) { int position, long id ) {
@ -1101,13 +1120,11 @@ public class GamesListDelegate extends ListDelegateBase
public void itemClicked( SelectableItem.LongClickHandler clicked, public void itemClicked( SelectableItem.LongClickHandler clicked,
GameSummary summary ) GameSummary summary )
{ {
DbgUtils.logf( "GamesListDelegate.itemClicked()" );
// We need a way to let the user get back to the basic-config // We need a way to let the user get back to the basic-config
// dialog in case it was dismissed. That way it to check for // dialog in case it was dismissed. That way it to check for
// an empty room name. // an empty room name.
if ( clicked instanceof GameListItem ) { if ( clicked instanceof GameListItem ) {
long rowid = ((GameListItem)clicked).getRowID(); long rowid = ((GameListItem)clicked).getRowID();
DbgUtils.logf( "GamesListDelegate.itemClicked(%d)", rowid );
if ( ! m_launchedGames.contains( rowid ) ) { if ( ! m_launchedGames.contains( rowid ) ) {
showNotAgainDlgThen( R.string.not_again_newselect, showNotAgainDlgThen( R.string.not_again_newselect,
R.string.key_notagain_newselect, R.string.key_notagain_newselect,
@ -1199,10 +1216,13 @@ public class GamesListDelegate extends ListDelegateBase
break; break;
case RESET_GAMES: case RESET_GAMES:
long[] rowids = (long[])params[0]; long[] rowids = (long[])params[0];
boolean changed = false;
for ( long rowid : rowids ) { for ( long rowid : rowids ) {
GameUtils.resetGame( m_activity, rowid ); changed = GameUtils.resetGame( m_activity, rowid ) || changed;
}
if ( changed ) {
mkListAdapter(); // required because position may change
} }
mkListAdapter(); // required because position may change
break; break;
case SYNC_MENU: case SYNC_MENU:
doSyncMenuitem(); doSyncMenuitem();
@ -1311,7 +1331,7 @@ public class GamesListDelegate extends ListDelegateBase
} }
@Override @Override
protected boolean onBackPressed() protected boolean handleBackPressed()
{ {
boolean handled = 0 < m_selGames.size() || 0 < m_selGroupIDs.size(); boolean handled = 0 < m_selGames.size() || 0 < m_selGroupIDs.size();
if ( handled ) { if ( handled ) {
@ -1325,7 +1345,7 @@ public class GamesListDelegate extends ListDelegateBase
@Override @Override
public boolean onPrepareOptionsMenu( Menu menu ) public boolean onPrepareOptionsMenu( Menu menu )
{ {
int nGamesSelected = m_selGames.size(); // NPE! int nGamesSelected = m_selGames.size();
int nGroupsSelected = m_selGroupIDs.size(); int nGroupsSelected = m_selGroupIDs.size();
int groupCount = m_adapter.getGroupCount(); int groupCount = m_adapter.getGroupCount();
m_menuPrepared = 0 == nGamesSelected || 0 == nGroupsSelected; m_menuPrepared = 0 == nGamesSelected || 0 == nGroupsSelected;
@ -1385,15 +1405,18 @@ public class GamesListDelegate extends ListDelegateBase
Utils.setItemVisible( menu, R.id.games_menu_newgame_net, Utils.setItemVisible( menu, R.id.games_menu_newgame_net,
nothingSelected || 1 == nGroupsSelected ); nothingSelected || 1 == nGroupsSelected );
// Multiples can be deleted // Multiples can be deleted, but disable if any selected game is
Utils.setItemVisible( menu, R.id.games_game_delete, // currently open
0 < nGamesSelected ); enable = 0 < nGamesSelected;
for ( long row : m_selGames ) {
enable = enable && !m_launchedGames.contains( row );
}
Utils.setItemVisible( menu, R.id.games_game_delete, enable );
Utils.setItemVisible( menu, R.id.games_game_reset, enable );
// multiple games can be regrouped/reset. // multiple games can be regrouped/reset.
Utils.setItemVisible( menu, R.id.games_game_move, Utils.setItemVisible( menu, R.id.games_game_move,
0 < nGamesSelected ); 0 < nGamesSelected );
Utils.setItemVisible( menu, R.id.games_game_reset,
0 < nGamesSelected );
// Hide rate-me if not a google play app // Hide rate-me if not a google play app
enable = nothingSelected && Utils.isGooglePlayApp( m_activity ); enable = nothingSelected && Utils.isGooglePlayApp( m_activity );
@ -1454,7 +1477,7 @@ public class GamesListDelegate extends ListDelegateBase
break; break;
case R.id.games_menu_dicts: case R.id.games_menu_dicts:
DictsActivity.start( m_activity ); DictsDelegate.start( getDelegator() );
break; break;
case R.id.games_menu_checkmoves: case R.id.games_menu_checkmoves:
@ -1529,7 +1552,7 @@ public class GamesListDelegate extends ListDelegateBase
= (AdapterView.AdapterContextMenuInfo)menuInfo; = (AdapterView.AdapterContextMenuInfo)menuInfo;
View targetView = info.targetView; View targetView = info.targetView;
DbgUtils.logf( "onCreateContextMenu(t=%s)", DbgUtils.logf( "onCreateContextMenu(t=%s)",
targetView.getClass().getName() ); targetView.getClass().getSimpleName() );
if ( targetView instanceof GameListItem ) { if ( targetView instanceof GameListItem ) {
item = (GameListItem)targetView; item = (GameListItem)targetView;
id = R.menu.games_list_game_menu; id = R.menu.games_list_game_menu;
@ -1552,16 +1575,19 @@ public class GamesListDelegate extends ListDelegateBase
Utils.setItemVisible( menu, hideId, false ); Utils.setItemVisible( menu, hideId, false );
if ( null != item ) { if ( null != item ) {
enable = BoardDelegate.rematchSupported( m_activity, long rowID = item.getRowID();
item.getRowID() ); enable = BoardDelegate.rematchSupported( m_activity, rowID );
Utils.setItemVisible( menu, R.id.games_game_rematch, enable ); Utils.setItemVisible( menu, R.id.games_game_rematch, enable );
enable = item.getSummary().isMultiGame() enable = item.getSummary().isMultiGame()
&& (BuildConfig.DEBUG || XWPrefs.getDebugEnabled( m_activity )); && (BuildConfig.DEBUG || XWPrefs.getDebugEnabled( m_activity ));
Utils.setItemVisible( menu, R.id.games_game_invites, enable ); Utils.setItemVisible( menu, R.id.games_game_invites, enable );
enable = !m_launchedGames.contains( rowID );
Utils.setItemVisible( menu, R.id.games_game_delete, enable );
Utils.setItemVisible( menu, R.id.games_game_reset, enable );
} }
} }
} }
public boolean onContextItemSelected( MenuItem item ) public boolean onContextItemSelected( MenuItem item )
@ -1594,7 +1620,7 @@ public class GamesListDelegate extends ListDelegateBase
public void downloadFinished( String lang, String name, public void downloadFinished( String lang, String name,
final boolean success ) final boolean success )
{ {
post( new Runnable() { runWhenActive( new Runnable() {
public void run() { public void run() {
boolean madeGame = false; boolean madeGame = false;
if ( success ) { if ( success ) {
@ -1677,7 +1703,9 @@ public class GamesListDelegate extends ListDelegateBase
break; break;
case R.id.games_game_config: case R.id.games_game_config:
GameUtils.doConfig( getDelegator(), selRowIDs[0] ); GameConfigDelegate.editForResult( getDelegator(),
RequestCode.CONFIG_GAME,
selRowIDs[0], false );
break; break;
case R.id.games_game_move: case R.id.games_game_move:
@ -1750,48 +1778,49 @@ public class GamesListDelegate extends ListDelegateBase
private boolean handleSelGroupsItem( int itemID, long[] groupIDs ) private boolean handleSelGroupsItem( int itemID, long[] groupIDs )
{ {
boolean handled = true; boolean handled = 0 < groupIDs.length;
String msg; if ( handled ) {
Assert.assertTrue( 0 < groupIDs.length ); String msg;
long groupID = groupIDs[0]; long groupID = groupIDs[0];
switch( itemID ) { switch( itemID ) {
case R.id.games_group_delete: case R.id.games_group_delete:
long dftGroup = XWPrefs.getDefaultNewGameGroup( m_activity ); long dftGroup = XWPrefs.getDefaultNewGameGroup( m_activity );
if ( m_selGroupIDs.contains( dftGroup ) ) { if ( m_selGroupIDs.contains( dftGroup ) ) {
msg = getString( R.string.cannot_delete_default_group_fmt, msg = getString( R.string.cannot_delete_default_group_fmt,
m_adapter.groupName( dftGroup ) ); m_adapter.groupName( dftGroup ) );
showOKOnlyDialog( msg ); showOKOnlyDialog( msg );
} else { } else {
Assert.assertTrue( 0 < groupIDs.length ); Assert.assertTrue( 0 < groupIDs.length );
msg = getQuantityString( R.plurals.groups_confirm_del_fmt, msg = getQuantityString( R.plurals.groups_confirm_del_fmt,
groupIDs.length, groupIDs.length ); groupIDs.length, groupIDs.length );
int nGames = 0; int nGames = 0;
for ( long tmp : groupIDs ) { for ( long tmp : groupIDs ) {
nGames += m_adapter.getChildrenCount( tmp ); nGames += m_adapter.getChildrenCount( tmp );
}
if ( 0 < nGames ) {
msg += getQuantityString( R.plurals.groups_confirm_del_games_fmt,
nGames, nGames );
}
showConfirmThen( msg, Action.DELETE_GROUPS, groupIDs );
} }
if ( 0 < nGames ) { break;
msg += getQuantityString( R.plurals.groups_confirm_del_games_fmt, case R.id.games_group_default:
nGames, nGames ); XWPrefs.setDefaultNewGameGroup( m_activity, groupID );
} break;
showConfirmThen( msg, Action.DELETE_GROUPS, groupIDs ); case R.id.games_group_rename:
m_groupid = groupID;
showDialog( DlgID.RENAME_GROUP );
break;
case R.id.games_group_moveup:
moveGroup( groupID, true );
break;
case R.id.games_group_movedown:
moveGroup( groupID, false );
break;
default:
handled = false;
} }
break;
case R.id.games_group_default:
XWPrefs.setDefaultNewGameGroup( m_activity, groupID );
break;
case R.id.games_group_rename:
m_groupid = groupID;
showDialog( DlgID.RENAME_GROUP );
break;
case R.id.games_group_moveup:
moveGroup( groupID, true );
break;
case R.id.games_group_movedown:
moveGroup( groupID, false );
break;
default:
handled = false;
} }
return handled; return handled;
} }
@ -1809,7 +1838,7 @@ public class GamesListDelegate extends ListDelegateBase
final boolean solo = isSolos[ii]; final boolean solo = isSolos[ii];
button.setOnClickListener( new View.OnClickListener() { button.setOnClickListener( new View.OnClickListener() {
public void onClick( View view ) { public void onClick( View view ) {
handleNewGameButton( solo ); curThis().handleNewGameButton( solo );
} }
} ); } );
} }
@ -1900,6 +1929,8 @@ public class GamesListDelegate extends ListDelegateBase
missingLang ); missingLang );
} catch ( GameUtils.NoSuchGameException nsge ) { } catch ( GameUtils.NoSuchGameException nsge ) {
hasDicts = true; // irrelevant question hasDicts = true; // irrelevant question
} catch ( GameLock.GameLockedException gle ) {
hasDicts = true; // irrelevant question
} }
if ( !hasDicts ) { if ( !hasDicts ) {
@ -2276,12 +2307,6 @@ public class GamesListDelegate extends ListDelegateBase
{ {
boolean madeGame = DBUtils.ROWID_NOTFOUND != m_missingDictRowId; boolean madeGame = DBUtils.ROWID_NOTFOUND != m_missingDictRowId;
if ( madeGame ) { if ( madeGame ) {
// if ( R.id.games_game_reset == m_missingDictMenuId ) {
// long[] rowIDs = { m_missingDictRowId };
// doConfirmReset( rowIDs );
// } else {
// launchGame( m_missingDictRowId );
// }
// save in case checkWarnNoDict needs to set them // save in case checkWarnNoDict needs to set them
long rowID = m_missingDictRowId; long rowID = m_missingDictRowId;
int menuID = m_missingDictMenuId; int menuID = m_missingDictMenuId;
@ -2300,10 +2325,6 @@ public class GamesListDelegate extends ListDelegateBase
private void launchGame( long rowid, boolean invited ) private void launchGame( long rowid, boolean invited )
{ {
// DbgUtils.logf( "launchGame(%d)", rowid );
// if ( ! m_launchedGames.contains( rowid ) ) {
// m_launchedGames.add( rowid );
// m_delegator.launchGame( rowid, invited );
if ( ! m_launchedGames.contains( rowid ) ) { if ( ! m_launchedGames.contains( rowid ) ) {
m_launchedGames.add( rowid ); m_launchedGames.add( rowid );
if ( m_adapter.inExpandedGroup( rowid ) ) { if ( m_adapter.inExpandedGroup( rowid ) ) {
@ -2339,7 +2360,6 @@ public class GamesListDelegate extends ListDelegateBase
{ {
GameSummary summary = (GameSummary)params[1]; GameSummary summary = (GameSummary)params[1];
long rowid = (Long)params[0]; long rowid = (Long)params[0];
DbgUtils.logf( "GamesListDelegate.doOpenGame(%d)", rowid );
if ( summary.conTypes.contains( CommsAddrRec.CommsConnType.COMMS_CONN_RELAY ) if ( summary.conTypes.contains( CommsAddrRec.CommsConnType.COMMS_CONN_RELAY )
&& summary.roomName.length() == 0 ) { && summary.roomName.length() == 0 ) {
@ -2492,7 +2512,7 @@ public class GamesListDelegate extends ListDelegateBase
// configure it // configure it
GameConfigDelegate.editForResult( getDelegator(), GameConfigDelegate.editForResult( getDelegator(),
RequestCode.CONFIG_GAME, RequestCode.CONFIG_GAME,
rowID ); rowID, true );
} else { } else {
// launch it // launch it
GameUtils.launchGame( getDelegator(), rowID ); GameUtils.launchGame( getDelegator(), rowID );
@ -2509,15 +2529,15 @@ public class GamesListDelegate extends ListDelegateBase
public static void onGameDictDownload( Context context, Intent intent ) public static void onGameDictDownload( Context context, Intent intent )
{ {
intent.setClass( context, GamesListActivity.class ); intent.setClass( context, MainActivity.class );
context.startActivity( intent ); context.startActivity( intent );
} }
private static Intent makeSelfIntent( Context context ) private static Intent makeSelfIntent( Context context )
{ {
Intent intent = new Intent( context, GamesListActivity.class ); Intent intent = new Intent( context, MainActivity.class );
intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK ); | Intent.FLAG_ACTIVITY_SINGLE_TOP );
return intent; return intent;
} }

View file

@ -24,6 +24,8 @@ import android.os.Bundle;
public class GamesListFrag extends XWFragment { public class GamesListFrag extends XWFragment {
public GamesListFrag( Delegator parent ) { super( parent ); }
@Override @Override
public void onCreate( Bundle sis ) public void onCreate( Bundle sis )
{ {

View file

@ -0,0 +1,484 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2009 - 2014 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.Intent;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager.BackStackEntry;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eehouse.android.xw4.jni.CurGameInfo;
import junit.framework.Assert;
public class MainActivity extends XWActivity
implements FragmentManager.OnBackStackChangedListener {
private static final int MAX_PANES_LANDSCAPE = 2;
private static final boolean LOG_IDS = true;
private DelegateBase m_dlgt;
private boolean m_dpEnabled;
// Used only if m_dpEnabled is true
private LinearLayout m_root;
private int m_maxPanes;
private int m_nextID = 0x00FFFFFF;
private Boolean m_isPortrait;
// for tracking launchForResult callback recipients
private Map<RequestCode, WeakReference<DelegateBase>> m_pendingCodes
= new HashMap<RequestCode, WeakReference<DelegateBase>>();
@Override
protected void onCreate( Bundle savedInstanceState )
{
m_dpEnabled = XWPrefs.dualpaneEnabled( this );
if ( BuildConfig.DEBUG ) {
Utils.showToast( this, "dualpane mode: " + m_dpEnabled );
}
m_dlgt = m_dpEnabled ? new DualpaneDelegate( this, savedInstanceState )
: new GamesListDelegate( this, savedInstanceState );
super.onCreate( savedInstanceState, m_dlgt );
if ( m_dpEnabled ) {
m_root = (LinearLayout)findViewById( R.id.main_container );
getSupportFragmentManager().addOnBackStackChangedListener( this );
m_maxPanes = maxPanes();
// Nothing to do if we're restarting
if ( savedInstanceState == null ) {
// In case this activity was started with special instructions from an Intent,
// pass the Intent's extras to the fragment as arguments
addFragmentImpl( new GamesListFrag(null),
getIntent().getExtras(), null );
}
}
} // onCreate
// called when we're brought to the front (probably as a result of
// notification)
@Override
protected void onNewIntent( Intent intent )
{
super.onNewIntent( intent );
m_dlgt.handleNewIntent( intent );
}
@Override
public void onConfigurationChanged( Configuration newConfig )
{
if ( m_dpEnabled ) {
Rect rect = new Rect();
m_root.getWindowVisibleDisplayFrame( rect );
boolean isPortrait
= Configuration.ORIENTATION_PORTRAIT == newConfig.orientation;
DbgUtils.logf( "MainActivity.onConfigurationChanged(isPortrait=%b)",
isPortrait );
m_isPortrait = isPortrait;
if ( isPortrait != (rect.width() <= rect.height()) ) {
DbgUtils.logdf( "FragActivity.onConfigurationChanged(): isPortrait:"
+ " %b; width: %d; height: %d",
isPortrait, rect.width(), rect.height() );
}
int maxPanes = isPortrait? 1 : MAX_PANES_LANDSCAPE;
if ( m_maxPanes != maxPanes ) {
m_maxPanes = maxPanes;
setVisiblePanes();
}
tellOrientationChanged();
}
super.onConfigurationChanged( newConfig );
}
/**
* Run down the list of fragments until one handles the intent. If no
* visible one does, pop hidden ones into view until one of them
* 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
* GamesList anyway.
*/
protected boolean dispatchNewIntent( Intent intent )
{
boolean handled = false;
FragmentManager fm = getSupportFragmentManager();
// First try non-left-most fragments, if any. Once we've eliminated
// them we can just iterate on the leftmost fragment.
int nNonLeft = m_maxPanes - 1;
// include paged-to-left invisible views
int viewCount = m_root.getChildCount();
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 ) {
break;
} else if ( ii > 0 ) {
DbgUtils.logf( "popping %s",
frag.getClass().getSimpleName() );
fm.popBackStackImmediate(); // callback removes view
}
}
}
return handled;
}
/**
* The right-most pane only gets a chance to handle on-back-pressed.
*/
protected boolean dispatchBackPressed()
{
XWFragment frag = getTopFragment();
boolean handled = null != frag
&& frag.getDelegate().handleBackPressed();
return handled;
}
protected void dispatchOnActivityResult( RequestCode requestCode,
int resultCode, Intent data )
{
XWFragment frag = getTopFragment();
if ( null != frag ) {
frag.onActivityResult( requestCode.ordinal(), resultCode, data );
} else {
DbgUtils.logdf( "dispatchOnActivityResult(): can't dispatch %s",
requestCode.toString() );
}
}
protected void dispatchOnCreateContextMenu( ContextMenu menu, View view,
ContextMenuInfo menuInfo )
{
XWFragment[] frags = getVisibleFragments();
for ( XWFragment frag : frags ) {
frag.getDelegate().onCreateContextMenu( menu, view, menuInfo );
}
}
protected boolean dispatchOnContextItemSelected( MenuItem item )
{
boolean handled = false;
XWFragment[] frags = getVisibleFragments();
for ( XWFragment frag : frags ) {
handled = frag.getDelegate().onContextItemSelected( item );
if ( handled ) {
break;
}
}
return handled;
}
protected Point getFragmentSize()
{
Rect rect = new Rect();
m_root.getWindowVisibleDisplayFrame( rect );
int width = rect.width();
int height = rect.height();
if ( null != m_isPortrait && m_isPortrait && height < width ) {
int tmp = width;
width = height;
height = tmp;
}
return new Point( width / Math.min( m_maxPanes, m_root.getChildCount() ),
height );
}
//////////////////////////////////////////////////////////////////////
// Delegator interface
//////////////////////////////////////////////////////////////////////
@Override
public boolean inDPMode() {
return m_dpEnabled;
}
@Override
public void addFragment( XWFragment fragment, Bundle extras )
{
addFragmentImpl( fragment, extras, fragment.getParent() );
}
private class PendingResultCache {
private WeakReference<Fragment> m_frag;
public int m_request;
public int m_result;
public Intent m_data;
public PendingResultCache( Fragment target, int request, int result, Intent data ) {
m_frag = new WeakReference<Fragment>(target);
m_request = request;
m_result = result;
m_data = data;
}
public Fragment getTarget() { return m_frag.get(); }
}
private PendingResultCache m_pendingResult;
public void addFragmentForResult( XWFragment fragment, Bundle extras,
RequestCode requestCode, XWFragment registrant )
{
DbgUtils.assertOnUIThread();
fragment.setTargetFragment( registrant, requestCode.ordinal() );
addFragmentImpl( fragment, extras, fragment.getParent() );
}
protected void setFragmentResult( XWFragment fragment, int resultCode,
Intent data )
{
Fragment target = fragment.getTargetFragment();
int requestCode = fragment.getTargetRequestCode();
Assert.assertNull( m_pendingResult );
m_pendingResult = new PendingResultCache( target, requestCode,
resultCode, data );
}
protected void finishFragment()
{
// Assert.assertTrue( fragment instanceof XWFragment );
// DbgUtils.logf( "MainActivity.finishFragment(%s)", fragment.toString() );
getSupportFragmentManager().popBackStack/*Immediate*/();
}
//////////////////////////////////////////////////////////////////////
// FragmentManager.OnBackStackChangedListener
//////////////////////////////////////////////////////////////////////
public void onBackStackChanged()
{
// make sure the right-most are visible
int fragCount = getSupportFragmentManager().getBackStackEntryCount();
DbgUtils.logf( "MainActivity.onBackStackChanged(); count now %d", fragCount );
if ( 0 == fragCount ) {
finish();
} else {
if ( fragCount == m_root.getChildCount() - 1 ) {
View child = m_root.getChildAt( fragCount );
if ( LOG_IDS ) {
DbgUtils.logf( "onBackStackChanged(): removing view with id %x",
child.getId() );
}
m_root.removeView( child );
setVisiblePanes();
}
// If there's a pending on-result call, make it.
if ( null != m_pendingResult ) {
Fragment target = m_pendingResult.getTarget();
if ( null != target ) {
DbgUtils.logf( "onBackStackChanged(): calling onActivityResult()" );
target.onActivityResult( m_pendingResult.m_request,
m_pendingResult.m_result,
m_pendingResult.m_data );
}
m_pendingResult = null;
}
}
}
////////////////////////////////////////////////////////////////////////
// Dualpane mode stuff
////////////////////////////////////////////////////////////////////////
private XWFragment getTopFragment()
{
View child = m_root.getChildAt( m_root.getChildCount() - 1 );
XWFragment frag = (XWFragment)getSupportFragmentManager()
.findFragmentById( child.getId() );
return frag;
}
private XWFragment[] getVisibleFragments()
{
int childCount = m_root.getChildCount();
int count = Math.min( m_maxPanes, childCount );
XWFragment[] result = new XWFragment[count];
for ( int ii = 0; ii < count; ++ii ) {
View child = m_root.getChildAt( childCount - 1 - ii );
result[ii] = (XWFragment)getSupportFragmentManager()
.findFragmentById( child.getId() );
}
return result;
}
// Walk all Fragment children and if they care notify of change.
private void tellOrientationChanged()
{
FragmentManager fm = getSupportFragmentManager();
int nPanes = m_root.getChildCount();
for ( int ii = 0; ii < nPanes; ++ii ) {
FrameLayout frame = (FrameLayout)m_root.getChildAt( ii );
int id = frame.getId();
Fragment frag = fm.findFragmentById( id );
if ( null == frag ) {
DbgUtils.logf( "tellOrienationChanged: NO FRAG at %d, id=%d", ii, id );
} else if ( frag instanceof XWFragment ) {
((XWFragment)frag).getDelegate().orientationChanged();
}
}
}
private int maxPanes()
{
int result;
int orientation = getResources().getConfiguration().orientation;
if ( XWPrefs.getIsTablet( this )
&& Configuration.ORIENTATION_LANDSCAPE == orientation ) {
result = MAX_PANES_LANDSCAPE;
} else {
result = 1;
}
// DbgUtils.logf( "maxPanes() => %d", result );
return result;
}
private void setVisiblePanes()
{
// hide all but the right-most m_maxPanes children
int nPanes = m_root.getChildCount();
for ( int ii = 0; ii < nPanes; ++ii ) {
View child = m_root.getChildAt( ii );
boolean visible = ii >= nPanes - m_maxPanes;
DbgUtils.logf( "pane %d: visible=%b", ii, visible );
child.setVisibility( visible ? View.VISIBLE : View.GONE );
setMenuVisibility( child, visible );
}
}
private void setMenuVisibility( View cont, boolean visible )
{
FrameLayout layout = (FrameLayout)cont;
FragmentManager fm = getSupportFragmentManager();
int hidingId = layout.getId();
Fragment frag = fm.findFragmentById( hidingId );
if ( null != frag ) { // hasn't been popped?
frag.setMenuVisibility( visible );
}
}
private void addFragmentImpl( Fragment fragment, Bundle bundle,
Delegator parent )
{
fragment.setArguments( bundle );
addFragmentImpl( fragment, parent );
}
private void addFragmentImpl( Fragment fragment, Delegator parent )
{
String newName = fragment.getClass().getSimpleName();
boolean replace = false;
FragmentManager fm = getSupportFragmentManager();
int fragCount = fm.getBackStackEntryCount();
int containerCount = m_root.getChildCount();
DbgUtils.logf( "fragCount: %d; containerCount: %d", fragCount, containerCount );
// Assert.assertTrue( fragCount == containerCount );
// Replace IF we're adding something of the same class at right OR if
// we're adding something with the existing left pane as its parent
// (delegator)
if ( 1 < fragCount ) {
Assert.assertTrue( MAX_PANES_LANDSCAPE == 2 ); // otherwise FIXME
FragmentManager.BackStackEntry entry
= fm.getBackStackEntryAt( fragCount - 2 );
String curName = entry.getName();
String delName = parent.getClass().getSimpleName();
// DbgUtils.logf( "comparing %s, %s", curName, delName );
replace = curName.equals( delName );
}
if ( replace ) {
fm.popBackStack();
}
// Replace doesn't seem to work with generated IDs, so we'll create a
// new FrameLayout each time. If we're replacing, we'll replace the
// current rightmost FrameLayout. Otherwise we'll add a new one.
LinearLayout.LayoutParams lp
= new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams
.MATCH_PARENT, 1.0f);
FrameLayout cont = new FrameLayout( this );
cont.setLayoutParams( lp );
int id = --m_nextID;
cont.setId( id );
if ( LOG_IDS ) {
DbgUtils.logf( "assigning id %x to view with name %s", id, newName );
}
m_root.addView( cont, replace ? containerCount - 1 : containerCount );
if ( !replace && containerCount >= m_maxPanes ) {
int indx = containerCount - m_maxPanes;
View child = m_root.getChildAt( indx );
child.setVisibility( View.GONE );
setMenuVisibility( child, false );
DbgUtils.logf( "hiding %dth container", indx );
}
fm.beginTransaction()
.add( id, fragment )
.addToBackStack( newName )
.commit();
// Don't do this. It causes an exception if e.g. from fragment.start()
// I wind up launching another fragment and calling into this code
// again. If I need executePendingTransactions() I'm doing something
// else wrong.
// fm.executePendingTransactions();
}
}

View file

@ -31,7 +31,7 @@ public class OnBootReceiver extends BroadcastReceiver {
{ {
if ( null != intent && null != intent.getAction() if ( null != intent && null != intent.getAction()
&& intent.getAction().equals( Intent.ACTION_BOOT_COMPLETED ) ) { && intent.getAction().equals( Intent.ACTION_BOOT_COMPLETED ) ) {
DbgUtils.logf( "OnBootReceiver: got ACTION_BOOT_COMPLETED" ); DbgUtils.logdf( "OnBootReceiver: got ACTION_BOOT_COMPLETED" );
startTimers( context ); startTimers( context );
} }
} }

View file

@ -26,6 +26,8 @@ import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import junit.framework.Assert;
import org.eehouse.android.xw4.loc.LocUtils; import org.eehouse.android.xw4.loc.LocUtils;
import org.eehouse.android.xw4.DlgDelegate.Action; import org.eehouse.android.xw4.DlgDelegate.Action;
@ -53,6 +55,7 @@ public class PrefsActivity extends PreferenceActivity
{ {
LocUtils.xlatePreferences( this ); LocUtils.xlatePreferences( this );
super.onStart(); super.onStart();
m_dlgt.onStart();
} }
@Override @Override
@ -141,4 +144,9 @@ public class PrefsActivity extends PreferenceActivity
{ {
return getIntent().getExtras(); return getIntent().getExtras();
} }
public boolean inDPMode() { Assert.fail(); return false; }
public void addFragment( XWFragment fragment, Bundle extras ) { Assert.fail(); }
public void addFragmentForResult( XWFragment fragment, Bundle extras,
RequestCode code ) { Assert.fail(); }
} }

View file

@ -82,7 +82,8 @@ public class PrefsDelegate extends DelegateBase
confirmID = R.string.confirm_revert_colors; confirmID = R.string.confirm_revert_colors;
lstnr = new DialogInterface.OnClickListener() { lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
SharedPreferences sp = getSharedPreferences(); PrefsDelegate self = (PrefsDelegate)curThis();
SharedPreferences sp = self.getSharedPreferences();
SharedPreferences.Editor editor = sp.edit(); SharedPreferences.Editor editor = sp.edit();
int[] colorKeys = { int[] colorKeys = {
R.string.key_player0, R.string.key_player0,
@ -103,7 +104,7 @@ public class PrefsDelegate extends DelegateBase
editor.remove( getString(colorKey) ); editor.remove( getString(colorKey) );
} }
editor.commit(); editor.commit();
relaunch(); self.relaunch();
} }
}; };
break; break;
@ -111,11 +112,12 @@ public class PrefsDelegate extends DelegateBase
confirmID = R.string.confirm_revert_all; confirmID = R.string.confirm_revert_all;
lstnr = new DialogInterface.OnClickListener() { lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
SharedPreferences sp = getSharedPreferences(); PrefsDelegate self = (PrefsDelegate)curThis();
SharedPreferences sp = self.getSharedPreferences();
SharedPreferences.Editor editor = sp.edit(); SharedPreferences.Editor editor = sp.edit();
editor.clear(); editor.clear();
editor.commit(); editor.commit();
relaunch(); self.relaunch();
} }
}; };
break; break;
@ -149,13 +151,13 @@ public class PrefsDelegate extends DelegateBase
Button button = (Button)findViewById( R.id.revert_colors ); Button button = (Button)findViewById( R.id.revert_colors );
button.setOnClickListener( new View.OnClickListener() { button.setOnClickListener( new View.OnClickListener() {
public void onClick( View v ) { public void onClick( View v ) {
showDialog( DlgID.REVERT_COLORS ); curThis().showDialog( DlgID.REVERT_COLORS );
} }
} ); } );
button = (Button)findViewById( R.id.revert_all ); button = (Button)findViewById( R.id.revert_all );
button.setOnClickListener(new View.OnClickListener() { button.setOnClickListener(new View.OnClickListener() {
public void onClick( View v ) { public void onClick( View v ) {
showDialog( DlgID.REVERT_ALL ); curThis().showDialog( DlgID.REVERT_ALL );
} }
} ); } );
@ -240,7 +242,6 @@ public class PrefsDelegate extends DelegateBase
@Override @Override
public void dlgButtonClicked( Action action, int button, Object[] params ) public void dlgButtonClicked( Action action, int button, Object[] params )
{ {
DbgUtils.logf( "PrefsDelegate.dlgButtonClicked(%s)", action.toString() );
boolean handled = AlertDialog.BUTTON_POSITIVE == button; boolean handled = AlertDialog.BUTTON_POSITIVE == button;
if ( handled ) { if ( handled ) {
switch ( action ) { switch ( action ) {

View file

@ -555,7 +555,6 @@ public class RelayService extends XWService
DatagramPacket packet = DatagramPacket packet =
new DatagramPacket( buf, buf.length ); new DatagramPacket( buf, buf.length );
try { try {
Assert.assertTrue( relayEnabled( RelayService.this ) );
m_UDPSocket.receive( packet ); m_UDPSocket.receive( packet );
resetExitTimer(); resetExitTimer();
gotPacket( packet ); gotPacket( packet );
@ -584,7 +583,6 @@ public class RelayService extends XWService
int port = XWPrefs.getDefaultRelayPort( this ); int port = XWPrefs.getDefaultRelayPort( this );
String host = XWPrefs.getDefaultRelayHost( this ); String host = XWPrefs.getDefaultRelayHost( this );
try { try {
Assert.assertTrue( relayEnabled( this ) );
m_UDPSocket = new DatagramSocket(); m_UDPSocket = new DatagramSocket();
m_UDPSocket.setSoTimeout(30 * 1000); // timeout so we can log m_UDPSocket.setSoTimeout(30 * 1000); // timeout so we can log
@ -626,7 +624,6 @@ public class RelayService extends XWService
} }
try { try {
Assert.assertTrue( relayEnabled( RelayService.this ) );
DatagramPacket outPacket = outData.assemble(); DatagramPacket outPacket = outData.assemble();
m_UDPSocket.send( outPacket ); m_UDPSocket.send( outPacket );
int pid = outData.m_packetID; int pid = outData.m_packetID;

View file

@ -25,7 +25,6 @@ public enum RequestCode {
__UNUSED, __UNUSED,
// BoardDelegate // BoardDelegate
CHAT_REQUEST,
BT_INVITE_RESULT, BT_INVITE_RESULT,
SMS_INVITE_RESULT, SMS_INVITE_RESULT,
RELAY_INVITE_RESULT, RELAY_INVITE_RESULT,

View file

@ -85,9 +85,6 @@ public class SMSInviteDelegate extends InviteDelegate {
protected void init( Bundle savedInstanceState ) protected void init( Bundle savedInstanceState )
{ {
// super.init( R.id.button_invite, R.id.button_add,
// R.id.button_clear, R.id.invite_desc,
// R.string.invite_sms_desc_fmt );
String msg = getString( R.string.button_invite ); String msg = getString( R.string.button_invite );
msg = getQuantityString( R.plurals.invite_sms_desc_fmt, m_nMissing, msg = getQuantityString( R.plurals.invite_sms_desc_fmt, m_nMissing,
m_nMissing, msg ); m_nMissing, msg );
@ -150,13 +147,14 @@ public class SMSInviteDelegate extends InviteDelegate {
namerView.setKeyListener(DialerKeyListener.getInstance()); namerView.setKeyListener(DialerKeyListener.getInstance());
lstnr = new DialogInterface.OnClickListener() { lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
SMSInviteDelegate self = (SMSInviteDelegate)curThis();
String number = namerView.getName(); String number = namerView.getName();
PhoneRec rec = new PhoneRec( number ); PhoneRec rec = new PhoneRec( number );
m_pendingNumber = number; self.m_pendingNumber = number;
m_pendingName = null; self.m_pendingName = null;
showConfirmThen( R.string.warn_unlimited, self.showConfirmThen( R.string.warn_unlimited,
R.string.button_yes, R.string.button_yes,
Action.POST_WARNING_ACTION ); Action.POST_WARNING_ACTION );
} }
}; };
dialog = makeAlertBuilder() dialog = makeAlertBuilder()

View file

@ -289,7 +289,7 @@ public class SMSService extends XWService {
return s_showToasts; return s_showToasts;
} }
@Override // abstract @Override
protected MultiMsgSink getSink( long rowid ) protected MultiMsgSink getSink( long rowid )
{ {
return new SMSMsgSink( this ); return new SMSMsgSink( this );

View file

@ -86,7 +86,7 @@ public class StudyListDelegate extends ListDelegateBase
} }
@Override @Override
protected boolean onBackPressed() protected boolean handleBackPressed()
{ {
boolean handled = 0 < m_checkeds.size(); boolean handled = 0 < m_checkeds.size();
if ( handled ) { if ( handled ) {
@ -293,7 +293,6 @@ public class StudyListDelegate extends ListDelegateBase
} }
} }
DbgUtils.logf( "creating studylist adapter" );
ArrayAdapter<String> adapter = new ArrayAdapter<String> adapter = new
ArrayAdapter<String>( m_activity, ArrayAdapter<String>( m_activity,
android.R.layout.simple_spinner_item, android.R.layout.simple_spinner_item,
@ -363,9 +362,8 @@ public class StudyListDelegate extends ListDelegateBase
bundle.putInt( START_LANG, lang ); bundle.putInt( START_LANG, lang );
} }
if ( activity instanceof FragActivity ) { if ( delegator.inDPMode() ) {
StudyListFrag frag = new StudyListFrag(); delegator.addFragment( new StudyListFrag( delegator ), bundle );
((FragActivity)activity).addFragment( frag, bundle, delegator );
} else { } else {
Intent intent = new Intent( activity, StudyListActivity.class ); Intent intent = new Intent( activity, StudyListActivity.class );
intent.putExtras( bundle ); intent.putExtras( bundle );

View file

@ -24,6 +24,8 @@ import android.os.Bundle;
public class StudyListFrag extends XWFragment { public class StudyListFrag extends XWFragment {
public StudyListFrag( Delegator parent ) { super( parent ); }
@Override @Override
public void onCreate( Bundle sis ) public void onCreate( Bundle sis )
{ {

View file

@ -35,6 +35,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.database.Cursor; import android.database.Cursor;
import android.media.Ringtone;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.provider.ContactsContract.PhoneLookup; import android.provider.ContactsContract.PhoneLookup;
@ -243,7 +244,10 @@ public class Utils {
if ( CommonPrefs.getSoundNotify( context ) ) { if ( CommonPrefs.getSoundNotify( context ) ) {
Uri uri = RingtoneManager Uri uri = RingtoneManager
.getDefaultUri( RingtoneManager.TYPE_NOTIFICATION ); .getDefaultUri( RingtoneManager.TYPE_NOTIFICATION );
RingtoneManager.getRingtone( context, uri ).play(); Ringtone ringtone = RingtoneManager.getRingtone( context, uri );
if ( null != ringtone ) {
ringtone.play();
}
} }
} }

View file

@ -24,6 +24,7 @@ import android.app.Dialog;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.Menu; import android.view.Menu;
@ -35,16 +36,15 @@ import android.widget.ListView;
import junit.framework.Assert; import junit.framework.Assert;
import junit.framework.Assert; public class XWActivity extends FragmentActivity implements Delegator {
public class XWActivity extends Activity implements Delegator {
private DelegateBase m_dlgt; private DelegateBase m_dlgt;
protected void onCreate( Bundle savedInstanceState, DelegateBase dlgt ) protected void onCreate( Bundle savedInstanceState, DelegateBase dlgt )
{ {
if ( XWApp.LOG_LIFECYLE ) { if ( XWApp.LOG_LIFECYLE ) {
DbgUtils.logf( "%s.onCreate(this=%H)", getClass().getName(), this ); DbgUtils.logf( "%s.onCreate(this=%H)",
getClass().getSimpleName(), this );
} }
super.onCreate( savedInstanceState ); super.onCreate( savedInstanceState );
m_dlgt = dlgt; m_dlgt = dlgt;
@ -68,7 +68,8 @@ public class XWActivity extends Activity implements Delegator {
protected void onPause() protected void onPause()
{ {
if ( XWApp.LOG_LIFECYLE ) { if ( XWApp.LOG_LIFECYLE ) {
DbgUtils.logf( "%s.onPause(this=%H)", getClass().getName(), this ); DbgUtils.logf( "%s.onPause(this=%H)",
getClass().getSimpleName(), this );
} }
m_dlgt.onPause(); m_dlgt.onPause();
super.onPause(); super.onPause();
@ -78,7 +79,8 @@ public class XWActivity extends Activity implements Delegator {
protected void onResume() protected void onResume()
{ {
if ( XWApp.LOG_LIFECYLE ) { if ( XWApp.LOG_LIFECYLE ) {
DbgUtils.logf( "%s.onResume(this=%H)", getClass().getName(), this ); DbgUtils.logf( "%s.onResume(this=%H)",
getClass().getSimpleName(), this );
} }
super.onResume(); super.onResume();
m_dlgt.onResume(); m_dlgt.onResume();
@ -88,7 +90,8 @@ public class XWActivity extends Activity implements Delegator {
protected void onStart() protected void onStart()
{ {
if ( XWApp.LOG_LIFECYLE ) { if ( XWApp.LOG_LIFECYLE ) {
DbgUtils.logf( "%s.onStart(this=%H)", getClass().getName(), this ); DbgUtils.logf( "%s.onStart(this=%H)",
getClass().getSimpleName(), this );
} }
super.onStart(); super.onStart();
m_dlgt.onStart(); m_dlgt.onStart();
@ -98,7 +101,8 @@ public class XWActivity extends Activity implements Delegator {
protected void onStop() protected void onStop()
{ {
if ( XWApp.LOG_LIFECYLE ) { if ( XWApp.LOG_LIFECYLE ) {
DbgUtils.logf( "%s.onStop(this=%H)", getClass().getName(), this ); DbgUtils.logf( "%s.onStop(this=%H)",
getClass().getSimpleName(), this );
} }
m_dlgt.onStop(); m_dlgt.onStop();
super.onStop(); super.onStop();
@ -108,7 +112,8 @@ public class XWActivity extends Activity implements Delegator {
protected void onDestroy() protected void onDestroy()
{ {
if ( XWApp.LOG_LIFECYLE ) { if ( XWApp.LOG_LIFECYLE ) {
DbgUtils.logf( "%s.onDestroy(this=%H)", getClass().getName(), this ); DbgUtils.logf( "%s.onDestroy(this=%H)",
getClass().getSimpleName(), this );
} }
m_dlgt.onDestroy(); m_dlgt.onDestroy();
super.onDestroy(); super.onDestroy();
@ -123,7 +128,7 @@ public class XWActivity extends Activity implements Delegator {
@Override @Override
public void onBackPressed() { public void onBackPressed() {
if ( !m_dlgt.onBackPressed() ) { if ( !m_dlgt.handleBackPressed() ) {
super.onBackPressed(); super.onBackPressed();
} }
} }
@ -222,4 +227,19 @@ public class XWActivity extends Activity implements Delegator {
{ {
return getListView().getAdapter(); return getListView().getAdapter();
} }
public boolean inDPMode() {
return false;
}
public void addFragment( XWFragment fragment, Bundle extras )
{
Assert.fail();
}
public void addFragmentForResult( XWFragment fragment, Bundle extras,
RequestCode request )
{
Assert.fail();
}
} }

View file

@ -38,7 +38,7 @@ public class XWApp extends Application {
public static final boolean REMATCH_SUPPORTED = true; public static final boolean REMATCH_SUPPORTED = true;
public static final boolean RELAYINVITE_SUPPORTED = false; public static final boolean RELAYINVITE_SUPPORTED = false;
public static final boolean ATTACH_SUPPORTED = false; public static final boolean ATTACH_SUPPORTED = false;
public static final boolean LOG_LIFECYLE = true; public static final boolean LOG_LIFECYLE = false;
public static final boolean DEBUG_EXP_TIMERS = false; public static final boolean DEBUG_EXP_TIMERS = false;
public static final boolean GCM_IGNORED = false; public static final boolean GCM_IGNORED = false;
public static final boolean UDP_ENABLED = true; public static final boolean UDP_ENABLED = true;

View file

@ -61,7 +61,6 @@ public class XWConnAddrPreference extends DialogPreference {
m_view.configure( XWPrefs.getAddrTypes( m_context ), m_view.configure( XWPrefs.getAddrTypes( m_context ),
new ConnViaViewLayout.CheckEnabledWarner() { new ConnViaViewLayout.CheckEnabledWarner() {
public void warnDisabled( CommsConnType typ ) { public void warnDisabled( CommsConnType typ ) {
String msg;
switch( typ ) { switch( typ ) {
case COMMS_CONN_SMS: case COMMS_CONN_SMS:
activity.showConfirmThen( R.string.warn_sms_disabled, activity.showConfirmThen( R.string.warn_sms_disabled,
@ -75,7 +74,7 @@ public class XWConnAddrPreference extends DialogPreference {
R.string.button_later, R.string.button_later,
Action.ENABLE_BT_DO ); Action.ENABLE_BT_DO );
case COMMS_CONN_RELAY: case COMMS_CONN_RELAY:
msg = LocUtils String msg = LocUtils
.getString( m_context, R.string .getString( m_context, R.string
.warn_relay_disabled ); .warn_relay_disabled );
msg += "\n\n" + LocUtils msg += "\n\n" + LocUtils

View file

@ -20,6 +20,7 @@
package org.eehouse.android.xw4; package org.eehouse.android.xw4;
import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
@ -34,13 +35,16 @@ import android.widget.ListView;
import junit.framework.Assert; import junit.framework.Assert;
public class XWFragment extends Fragment public class XWFragment extends Fragment implements Delegator {
implements Delegator,
FragActivity.OrientChangeListener {
private DelegateBase m_dlgt; private DelegateBase m_dlgt;
private Delegator m_parent;
private boolean m_hasOptionsMenu = false; private boolean m_hasOptionsMenu = false;
public XWFragment( Delegator parent ) { m_parent = parent; }
public Delegator getParent() { return m_parent; }
protected void onCreate( DelegateBase dlgt, Bundle sis, boolean hasOptionsMenu ) protected void onCreate( DelegateBase dlgt, Bundle sis, boolean hasOptionsMenu )
{ {
m_hasOptionsMenu = hasOptionsMenu; m_hasOptionsMenu = hasOptionsMenu;
@ -49,7 +53,7 @@ public class XWFragment extends Fragment
protected void onCreate( DelegateBase dlgt, Bundle sis ) protected void onCreate( DelegateBase dlgt, Bundle sis )
{ {
DbgUtils.logdf( "%s.onCreate() called", this.getClass().getName() ); DbgUtils.logdf( "%s.onCreate() called", this.getClass().getSimpleName() );
super.onCreate( sis ); super.onCreate( sis );
m_dlgt = dlgt; m_dlgt = dlgt;
} }
@ -58,14 +62,15 @@ public class XWFragment extends Fragment
public View onCreateView( LayoutInflater inflater, ViewGroup container, public View onCreateView( LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState ) Bundle savedInstanceState )
{ {
DbgUtils.logdf( "%s.onCreateView() called", this.getClass().getName() ); DbgUtils.logdf( "%s.onCreateView() called", this.getClass().getSimpleName() );
return m_dlgt.inflateView( inflater, container ); return m_dlgt.inflateView( inflater, container );
} }
@Override @Override
public void onActivityCreated( Bundle savedInstanceState ) public void onActivityCreated( Bundle savedInstanceState )
{ {
DbgUtils.logdf( "%s.onActivityCreated() called", this.getClass().getName() ); DbgUtils.logdf( "%s.onActivityCreated() called",
this.getClass().getSimpleName() );
m_dlgt.init( savedInstanceState ); m_dlgt.init( savedInstanceState );
super.onActivityCreated( savedInstanceState ); super.onActivityCreated( savedInstanceState );
if ( m_hasOptionsMenu ) { if ( m_hasOptionsMenu ) {
@ -76,7 +81,8 @@ public class XWFragment extends Fragment
@Override @Override
public void onPause() public void onPause()
{ {
DbgUtils.logdf( "%s.onPause() called", this.getClass().getName() ); DbgUtils.logdf( "%s.onPause() called",
this.getClass().getSimpleName() );
m_dlgt.onPause(); m_dlgt.onPause();
super.onPause(); super.onPause();
} }
@ -84,6 +90,8 @@ public class XWFragment extends Fragment
@Override @Override
public void onResume() public void onResume()
{ {
DbgUtils.logdf( "%s.onResume() called",
this.getClass().getSimpleName() );
super.onResume(); super.onResume();
m_dlgt.onResume(); m_dlgt.onResume();
} }
@ -91,7 +99,8 @@ public class XWFragment extends Fragment
@Override @Override
public void onStart() public void onStart()
{ {
DbgUtils.logdf( "%s.onStart() called", this.getClass().getName() ); DbgUtils.logdf( "%s.onStart() called",
this.getClass().getSimpleName() );
super.onStart(); super.onStart();
m_dlgt.onStart(); m_dlgt.onStart();
} }
@ -99,7 +108,8 @@ public class XWFragment extends Fragment
@Override @Override
public void onStop() public void onStop()
{ {
DbgUtils.logdf( "%s.onStop() called", this.getClass().getName() ); DbgUtils.logdf( "%s.onStop() called",
this.getClass().getSimpleName() );
m_dlgt.onStop(); m_dlgt.onStop();
super.onStop(); super.onStop();
} }
@ -107,11 +117,21 @@ public class XWFragment extends Fragment
@Override @Override
public void onDestroy() public void onDestroy()
{ {
DbgUtils.logdf( "%s.onDestroy() called", this.getClass().getName() ); DbgUtils.logdf( "%s.onDestroy() called",
this.getClass().getSimpleName() );
m_dlgt.onDestroy(); m_dlgt.onDestroy();
super.onDestroy(); super.onDestroy();
} }
@Override
public void onActivityResult( int requestCode, int resultCode, Intent data )
{
DbgUtils.logdf( "%s.onActivityResult() called",
this.getClass().getSimpleName() );
m_dlgt.onActivityResult( RequestCode.values()[requestCode],
resultCode, data );
}
@Override @Override
public void onPrepareOptionsMenu( Menu menu ) public void onPrepareOptionsMenu( Menu menu )
{ {
@ -135,12 +155,30 @@ public class XWFragment extends Fragment
Assert.fail(); Assert.fail();
} }
// FragActivity.OrientChangeListener @Override
public void orientationChanged() public boolean inDPMode() {
{ MainActivity main = (MainActivity)getActivity();
m_dlgt.orientationChanged(); Assert.assertTrue( main.inDPMode() ); // otherwise should be somewhere else
return true;
} }
@Override
public void addFragment( XWFragment fragment, Bundle extras )
{
MainActivity main = (MainActivity)getActivity();
main.addFragment( fragment, extras );
}
@Override
public void addFragmentForResult( XWFragment fragment, Bundle extras,
RequestCode code )
{
MainActivity main = (MainActivity)getActivity();
main.addFragmentForResult( fragment, extras, code, this );
}
public DelegateBase getDelegate() { return m_dlgt; }
public ListView getListView() public ListView getListView()
{ {
ListView view = (ListView)m_dlgt.findViewById( android.R.id.list ); ListView view = (ListView)m_dlgt.findViewById( android.R.id.list );
@ -157,5 +195,3 @@ public class XWFragment extends Fragment
return getListView().getAdapter(); return getListView().getAdapter();
} }
} }

View file

@ -445,8 +445,15 @@ public class XWPrefs {
public static boolean getIsTablet( Context context ) public static boolean getIsTablet( Context context )
{ {
return isTablet( context ) || boolean result = isTablet( context ) ||
getPrefsBoolean( context, R.string.key_force_tablet, false ); getPrefsBoolean( context, R.string.key_force_tablet, false );
// DbgUtils.logf( "getIsTablet() => %b", result );
return result;
}
public static boolean dualpaneEnabled( Context context )
{
return getPrefsBoolean( context, R.string.key_enable_dualpane, false );
} }
public static CommsConnTypeSet getAddrTypes( Context context ) public static CommsConnTypeSet getAddrTypes( Context context )

View file

@ -289,9 +289,10 @@ public class CommsAddrRec {
CommsConnType conType = iter.next(); CommsConnType conType = iter.next();
switch( conType ) { switch( conType ) {
case COMMS_CONN_RELAY: case COMMS_CONN_RELAY:
matter = ! ip_relay_invite.equals( other.ip_relay_invite ) matter = null == ip_relay_invite
|| ! ip_relay_hostName.equals( other.ip_relay_hostName ) || ! ip_relay_invite.equals( other.ip_relay_invite )
|| ip_relay_port != other.ip_relay_port; || ! ip_relay_hostName.equals( other.ip_relay_hostName )
|| ip_relay_port != other.ip_relay_port;
break; break;
default: default:
DbgUtils.logf( "changesMatter: not handling case: %s", DbgUtils.logf( "changesMatter: not handling case: %s",

View file

@ -55,21 +55,6 @@ import junit.framework.Assert;
public class JNIThread extends Thread { public class JNIThread extends Thread {
private static Set<JNIThread> s_curThreads = new HashSet<JNIThread>();
public static JNIThread getCurrent() {
JNIThread result = null;
synchronized( s_curThreads ) {
// DbgUtils.logf( "JNIThread.getCurrent(): have %d threads",
// s_curThreads.size() );
if ( 1 == s_curThreads.size() ) {
result = s_curThreads.iterator().next();
}
}
// DbgUtils.logf( "JNIThread.getCurrent() => %H", result );
return result;
}
public enum JNICmd { CMD_NONE, public enum JNICmd { CMD_NONE,
// CMD_RUN, // CMD_RUN,
CMD_DRAW, CMD_DRAW,
@ -393,9 +378,12 @@ public class JNIThread extends Thread {
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 );
// There'd better be no way for saveGame above to fail! // There'd better be no way for saveGame above to fail!
XwJNI.game_saveSucceeded( m_jniGamePtr ); XwJNI.game_saveSucceeded( m_jniGamePtr );
m_lastSavedState = state; m_lastSavedState = state;
GameUtils.loadMakeBitmap( m_context, state, m_lock );
} }
} }
} }
@ -764,7 +752,9 @@ public class JNIThread extends Thread {
return this; return this;
} }
public void release() public void release() { release( true ); }
public void release( boolean save )
{ {
boolean stop = false; boolean stop = false;
synchronized( s_instances ) { synchronized( s_instances ) {
@ -778,7 +768,7 @@ public class JNIThread extends Thread {
if ( stop ) { if ( stop ) {
waitToStop( true ); waitToStop( true );
} else { } else if ( save && null != m_lastSavedState ) { // has configure() run?
handle( JNICmd.CMD_SAVE ); // in case releaser has made changes handle( JNICmd.CMD_SAVE ); // in case releaser has made changes
} }
} }

View file

@ -56,7 +56,8 @@ public class LocDelegate extends ListDelegateBase
m_activity = delegator.getActivity(); m_activity = delegator.getActivity();
} }
protected boolean onBackPressed() @Override
protected boolean handleBackPressed()
{ {
LocUtils.saveLocalData( m_activity ); LocUtils.saveLocalData( m_activity );
return false; return false;

View file

@ -193,7 +193,7 @@ public class LocUtils {
// DbgUtils.logf( "xlateView(%s, %s)", context.getClass().getName(), // DbgUtils.logf( "xlateView(%s, %s)", context.getClass().getName(),
// view.getClass().getName() ); // view.getClass().getName() );
if ( XWApp.LOCUTILS_ENABLED ) { if ( XWApp.LOCUTILS_ENABLED ) {
xlateView( context, context.getClass().getName(), view, 0 ); xlateView( context, context.getClass().getSimpleName(), view, 0 );
} }
} }

View file

@ -16,22 +16,9 @@ APKS=''
DEVICES='' DEVICES=''
DIRNAME=$(basename $(pwd)) DIRNAME=$(basename $(pwd))
ADB="$(which adb)" ADB="$(which adb)"
MAIN=GamesListActivity MAIN=MainActivity
case $DIRNAME in PKG=$(xmlstarlet sel -T -t -m "/manifest" -v @package -n AndroidManifest.xml)
XWords4-dbg)
PKG=xw4dbg
;;
XWords4-bt)
PKG=xw4bt
;;
XWords4)
PKG=xw4
;;
*)
usage "running in unexpected directory $DIRNAME"
;;
esac
while [ $# -ge 1 ]; do while [ $# -ge 1 ]; do
case $1 in case $1 in
@ -76,7 +63,7 @@ for DEVICE in $DEVICES; do
ls -l $APK ls -l $APK
$ADB -s $DEVICE install -r $APK $ADB -s $DEVICE install -r $APK
$ADB -s $DEVICE shell am start \ $ADB -s $DEVICE shell am start \
-n org.eehouse.android.${PKG}/org.eehouse.android.${PKG}.${MAIN} -n ${PKG}/${PKG}.${MAIN}
done done
COUNT=$((COUNT+1)) COUNT=$((COUNT+1))
done done

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
set -e -u -x set -e -u
# use this: adb -s 04bd25af2523aae6 shell "pm list packages" | grep org.eehouse # use this: adb -s 04bd25af2523aae6 shell "pm list packages" | grep org.eehouse
@ -17,7 +17,7 @@ usage() {
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"
echo "uninstall crosswords variant" echo "uninstall apps based on known .apk or package name"
exit 1 exit 1
} }

View file

@ -27,14 +27,10 @@
<arg value="${build.target}"/> <arg value="${build.target}"/>
</exec> </exec>
<property name="CHAT_ENABLED" value="true" />
<property name="THUMBNAIL_ENABLED" value="true" />
<exec dir="." executable="../scripts/ndkbuild.sh" failonerror="true"> <exec dir="." executable="../scripts/ndkbuild.sh" failonerror="true">
<arg value="BUILD_TARGET=${build.target}" /> <arg value="BUILD_TARGET=${build.target}" />
<arg value="-j3"/> <arg value="-j3"/>
<arg value="INITIAL_CLIENT_VERS=${INITIAL_CLIENT_VERS}" /> <arg value="INITIAL_CLIENT_VERS=${INITIAL_CLIENT_VERS}" />
<arg value="CHAT_ENABLED=${CHAT_ENABLED}" />
<arg value="THUMBNAIL_ENABLED=${THUMBNAIL_ENABLED}" />
<arg value="VARIANT=${VARIANT_NAME}" /> <arg value="VARIANT=${VARIANT_NAME}" />
<arg value="V=1" /> <arg value="V=1" />
</exec> </exec>
@ -45,7 +41,10 @@
<exec dir="." executable="../scripts/copy-strings.py" <exec dir="." executable="../scripts/copy-strings.py"
failonerror="true" output="/dev/null" failonerror="true" output="/dev/null"
/> >
<arg value="-k"/>
<arg value="${SKIP_LANGS}"/>
</exec>
<exec dir="." executable="../scripts/mk_xml.py" <exec dir="." executable="../scripts/mk_xml.py"
failonerror="true" failonerror="true"
@ -64,10 +63,6 @@
<arg value="${VARIANT_NAME}" /> <arg value="${VARIANT_NAME}" />
<arg value="--client-vers" /> <arg value="--client-vers" />
<arg value="${INITIAL_CLIENT_VERS}" /> <arg value="${INITIAL_CLIENT_VERS}" />
<arg value="--chat-enabled"/>
<arg value="${CHAT_ENABLED}" />
<arg value="--thumbnail-enabled"/>
<arg value="${THUMBNAIL_ENABLED}" />
<arg value="--vers-outfile" /> <arg value="--vers-outfile" />
<arg value="./assets/gitvers.txt" /> <arg value="./assets/gitvers.txt" />
</exec> </exec>
@ -97,6 +92,13 @@
</exec> </exec>
</target> </target>
<!-- For some reason project.properties is suddenly getting
removed by clean and not regenerated. So make sure it's
there. -->
<target name="my-check-props">
<exec executable="../scripts/setup_local_props.sh" />
</target>
<target name="my-pre-compile"> <target name="my-pre-compile">
<copy file="./gen/org/eehouse/android/${VARIANT_NAME}/R.java" todir="archive"/> <copy file="./gen/org/eehouse/android/${VARIANT_NAME}/R.java" todir="archive"/>

View file

@ -15,10 +15,14 @@ g_oneToOthers = ['values-ja']
sComment = """ sComment = """
DO NOT EDIT THIS FILE!!!! DO NOT EDIT THIS FILE!!!!
It was generated (from %s). It was generated (from %s, by %s).
Any changes you make to it will be lost. Any changes you make to it will be lost.
""" """
def usage():
print "usage:", sys.argv[0], '[-k <list-o-dirs>]'
sys.exit(1)
def sameOrSameWithPrefix( str1, str2 ): def sameOrSameWithPrefix( str1, str2 ):
result = str1 == str2 result = str1 == str2
if not result: if not result:
@ -126,7 +130,7 @@ def loadPlural(plural):
return items return items
def writeDoc(doc, src, dest): def writeDoc(doc, src, dest):
comment = etree.Comment(sComment % (src)) comment = etree.Comment(sComment % (src, os.path.basename(sys.argv[0])))
doc.getroot().insert( 0, comment ) doc.getroot().insert( 0, comment )
dir = os.path.dirname( dest ) dir = os.path.dirname( dest )
try: os.makedirs( dir ) try: os.makedirs( dir )
@ -182,6 +186,15 @@ def main():
excepts = ['values-ca_PS', 'values-ba_CK'] excepts = ['values-ca_PS', 'values-ba_CK']
verboses = ['values-ja'] verboses = ['values-ja']
try:
pairs, rest = getopt.getopt(sys.argv[1:], "k:")
for option, value in pairs:
if option == '-k': excepts += value.split(' ')
else: usage()
except:
print "Unexpected error:", sys.exc_info()[0]
usage()
# summarize the english file # summarize the english file
wd = os.path.dirname(sys.argv[0]) wd = os.path.dirname(sys.argv[0])
path = wd + '/../XWords4/res/values/strings.xml' path = wd + '/../XWords4/res/values/strings.xml'

View file

@ -72,7 +72,9 @@ esac
# if we're running for the first time in this directory/variant, # if we're running for the first time in this directory/variant,
# generate local.properties # generate local.properties
[ -e local.properties ] || ../scripts/setup_local_props.sh if [ -e ../scripts/setup_local_props.sh ]; then
[ -e local.properties ] || ../scripts/setup_local_props.sh
fi
# If this fails, the "set -e" above means we won't try to install anything # If this fails, the "set -e" above means we won't try to install anything
[ -n "$CMDS" ] && ant $CMDS [ -n "$CMDS" ] && ant $CMDS
@ -88,5 +90,5 @@ if [ -n "$INSTALL" ]; then
fi fi
# if [ "$CMDS" != "${CMDS%%install}" ]; then # if [ "$CMDS" != "${CMDS%%install}" ]; then
# adb shell am start -n org.eehouse.android.${PKG}/org.eehouse.android.${PKG}.GamesListActivity # adb shell am start -n org.eehouse.android.${PKG}/org.eehouse.android.${PKG}.MainActivity
# fi # fi

View file

@ -6,14 +6,11 @@ STRINGS_HASH=""
OUT_PATH="" OUT_PATH=""
VARIANT="" VARIANT=""
CLIENT_VERS_RELAY="" CLIENT_VERS_RELAY=""
CHAT_SUPPORTED=""
THUMBNAIL_SUPPORTED=""
GCM_SENDER_ID=${GCM_SENDER_ID:-""} GCM_SENDER_ID=${GCM_SENDER_ID:-""}
CRITTERCISM_APP_ID=${CRITTERCISM_APP_ID:-""} CRITTERCISM_APP_ID=${CRITTERCISM_APP_ID:-""}
usage() { usage() {
echo "usage: $0 --variant <variant> --client-vers <relay_vers> \\" echo "usage: $0 --variant <variant> --client-vers <relay_vers> \\"
echo " --chat-enabled <trueOrFalse> --thumbnail-enabled <trueOrFalse> \\"
echo " [--vers-outfile path/to/versout.txt]" echo " [--vers-outfile path/to/versout.txt]"
exit 1 exit 1
} }
@ -29,14 +26,6 @@ while [ $# -gt 0 ]; do
CLIENT_VERS_RELAY=$2 CLIENT_VERS_RELAY=$2
shift shift
;; ;;
--chat-enabled)
CHAT_SUPPORTED=$2
shift
;;
--thumbnail-enabled)
THUMBNAIL_SUPPORTED=$2
shift
;;
--vers-outfile) --vers-outfile)
OUT_PATH=$2 OUT_PATH=$2
shift shift
@ -48,7 +37,7 @@ while [ $# -gt 0 ]; do
shift shift
done done
[ -n "$VARIANT" -a -n "$CLIENT_VERS_RELAY" -a -n "$CHAT_SUPPORTED" -a -n "$THUMBNAIL_SUPPORTED" ] || usage [ -n "$VARIANT" -a -n "$CLIENT_VERS_RELAY" ] || usage
BUILD_DIR=$(basename $(pwd)) BUILD_DIR=$(basename $(pwd))
cd $(dirname $0) cd $(dirname $0)
@ -119,8 +108,6 @@ public class BuildConstants {
public static final String GIT_REV = "$SHORTVERS"; public static final String GIT_REV = "$SHORTVERS";
public static final String STRINGS_HASH = "$STRINGS_HASH"; public static final String STRINGS_HASH = "$STRINGS_HASH";
public static final short CLIENT_VERS_RELAY = $CLIENT_VERS_RELAY; public static final short CLIENT_VERS_RELAY = $CLIENT_VERS_RELAY;
public static final boolean CHAT_SUPPORTED = $CHAT_SUPPORTED;
public static final boolean THUMBNAIL_SUPPORTED = $THUMBNAIL_SUPPORTED;
public static final long BUILD_STAMP = $(date +'%s'); public static final long BUILD_STAMP = $(date +'%s');
public static final String DBG_TAG = "$DBG_TAG"; public static final String DBG_TAG = "$DBG_TAG";
public static final String VARIANT = "$VARIANT"; public static final String VARIANT = "$VARIANT";

View file

@ -3,50 +3,16 @@
set -u -e set -u -e
EXCEPTS=" " EXCEPTS=" "
DRY_RUN=''
echo "$0 $*"
pwd
usage() { usage() {
[ $# -ge 1 ] && echo "ERROR: $1" [ $# -ge 1 ] && echo "ERROR: $1"
echo "usage: $0 [--except path/to/file]*" echo "usage: $0 [--dry-run] [--except path/to/file]*"
echo " Starting in current directory, recursively remove all non-git-controlled"
echo " files, excepting those named with --except flags."
exit 1 exit 1
} }
# rm_not_excepted() {
# FILE=$1
# for EXCEPT in $EXCEPTS; do
# if [ $EXCEPT = $FILE ]; then
# echo "skipping delete of $FILE"
# FILE=""
# break
# fi
# done
# [ -n "$FILE" ] && rm $FILE
# }
rm_in() {
echo "rm_in $1"
for FILE in $(ls $1); do
FILE=$1/$FILE
echo "FILE: $FILE"
if [ ! "${EXCEPTS}" = "${EXCEPTS# $FILE }" ]; then
echo "$FILE is in $EXCEPTS"
continue
elif [ -d $FILE ]; then
rm_in $FILE
elif git ls-files $FILE --error-unmatch 2>/dev/null; then
echo "$FILE is a git file"
continue
else
echo "rm $FILE"
rm $FILE
fi
done
}
while [ $# -ge 1 ]; do while [ $# -ge 1 ]; do
case $1 in case $1 in
--except) --except)
@ -61,6 +27,12 @@ while [ $# -ge 1 ]; do
fi fi
EXCEPTS=" $EXCEPTS $FILE " EXCEPTS=" $EXCEPTS $FILE "
;; ;;
--dry-run)
DRY_RUN=1
;;
--help)
usage
;;
*) *)
usage "unexpected param $1" usage "unexpected param $1"
;; ;;
@ -68,8 +40,15 @@ while [ $# -ge 1 ]; do
shift shift
done done
echo "EXCEPTS: $EXCEPTS" for FILE in $(find $(pwd) -type f); do
exit 0 if [ ! "${EXCEPTS}" = "${EXCEPTS# $FILE }" ]; then
continue
elif git ls-files $FILE --error-unmatch 2>/dev/null 1>/dev/null; then
continue
else
echo "$FILE not under git; removing..."
[ -n "$DRY_RUN" ] || rm $FILE
fi
done
rm_in "." echo "$0: done" >&2
echo "$0: exiting cleanly"

View file

@ -2596,7 +2596,7 @@ setTurn( ServerCtxt* server, XP_S16 turn )
{ {
XP_ASSERT( -1 == turn XP_ASSERT( -1 == turn
|| (!amServer(server) || (0 == server->nv.pendingRegistrations))); || (!amServer(server) || (0 == server->nv.pendingRegistrations)));
if ( server->nv.currentTurn != turn ) { if ( server->nv.currentTurn != turn || 1 == server->vol.gi->nPlayers ) {
server->nv.currentTurn = turn; server->nv.currentTurn = turn;
server->nv.lastMoveTime = util_getCurSeconds( server->vol.util ); server->nv.lastMoveTime = util_getCurSeconds( server->vol.util );
callTurnChangeListener( server ); callTurnChangeListener( server );

View file

@ -52,6 +52,7 @@ openGamesDB( const char* dbName )
",gameid INT" ",gameid INT"
",ntotal INT(2)" ",ntotal INT(2)"
",nmissing INT(2)" ",nmissing INT(2)"
",lastMoveTime INT"
")"; ")";
result = sqlite3_exec( pDb, createGamesStr, NULL, NULL, NULL ); result = sqlite3_exec( pDb, createGamesStr, NULL, NULL, NULL );
@ -159,6 +160,7 @@ 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_S16 turn = server_getCurrentTurn( 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;
XP_U16 nTotal = cGlobals->gi->nPlayers; XP_U16 nTotal = cGlobals->gi->nPlayers;
@ -203,11 +205,12 @@ 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, gameid=%d, connvia='%s'" " SET room='%s', ended=%d, turn=%d, ntotal=%d, nmissing=%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, nTotal, nMissing,
nMoves, seed, gameID, connvia, cGlobals->selRow ); 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 );
@ -259,7 +262,7 @@ 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, nmoves, ntotal, nmissing, "
"seed, connvia, gameid " "seed, connvia, gameid, lastMoveTime "
"FROM games WHERE rowid = %lld"; "FROM games WHERE rowid = %lld";
XP_UCHAR query[256]; XP_UCHAR query[256];
snprintf( query, sizeof(query), fmt, rowid ); snprintf( query, sizeof(query), fmt, rowid );
@ -279,6 +282,7 @@ getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
gib->seed = sqlite3_column_int( ppStmt, 6 ); gib->seed = sqlite3_column_int( ppStmt, 6 );
getColumnText( ppStmt, 7, gib->conn, sizeof(gib->conn) ); getColumnText( ppStmt, 7, gib->conn, sizeof(gib->conn) );
gib->gameID = sqlite3_column_int( ppStmt, 8 ); gib->gameID = sqlite3_column_int( ppStmt, 8 );
gib->lastMoveTime = sqlite3_column_int( ppStmt, 9 );
snprintf( gib->name, sizeof(gib->name), "Game %lld", rowid ); snprintf( gib->name, sizeof(gib->name), "Game %lld", rowid );
} }
sqlite3_finalize( ppStmt ); sqlite3_finalize( ppStmt );

View file

@ -38,9 +38,9 @@ typedef struct _GameInfo {
XP_U16 nTotal; XP_U16 nTotal;
XP_S16 nMissing; XP_S16 nMissing;
XP_U16 seed; XP_U16 seed;
XP_U32 lastMoveTime;
} GameInfo; } GameInfo;
sqlite3* openGamesDB( const char* dbName ); sqlite3* openGamesDB( const char* dbName );
void closeGamesDB( sqlite3* dbp ); void closeGamesDB( sqlite3* dbp );

View file

@ -76,7 +76,7 @@ findOpenGame( const GtkAppGlobals* apg, sqlite3_int64 rowid )
} }
enum { ROW_ITEM, NAME_ITEM, ROOM_ITEM, GAMEID_ITEM, SEED_ITEM, CONN_ITEM, OVER_ITEM, TURN_ITEM, enum { ROW_ITEM, NAME_ITEM, ROOM_ITEM, GAMEID_ITEM, SEED_ITEM, CONN_ITEM, OVER_ITEM, TURN_ITEM,
NMOVES_ITEM, NTOTAL_ITEM, MISSING_ITEM, N_ITEMS }; NMOVES_ITEM, NTOTAL_ITEM, MISSING_ITEM, LASTTURN_ITEM, N_ITEMS };
static void static void
foreachProc( GtkTreeModel* model, GtkTreePath* XP_UNUSED(path), foreachProc( GtkTreeModel* model, GtkTreePath* XP_UNUSED(path),
@ -159,6 +159,7 @@ init_games_list( GtkAppGlobals* apg )
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 );
addTextColumn( list, "LastTurn", LASTTURN_ITEM );
GtkListStore* store = gtk_list_store_new( N_ITEMS, GtkListStore* store = gtk_list_store_new( N_ITEMS,
G_TYPE_INT64, /* ROW_ITEM */ G_TYPE_INT64, /* ROW_ITEM */
@ -171,7 +172,8 @@ init_games_list( GtkAppGlobals* apg )
G_TYPE_INT, /* TURN_ITEM */ G_TYPE_INT, /* TURN_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 */
); );
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 );
@ -220,6 +222,7 @@ add_to_list( GtkWidget* list, sqlite3_int64 rowid, XP_Bool isNew,
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,
-1 ); -1 );
XP_LOGF( "DONE adding" ); XP_LOGF( "DONE adding" );
} }