[Libreoffice-commits] core.git: 4 commits - android/sdremote
Artur Dryomov
artur.dryomov at gmail.com
Sun Jul 28 18:13:51 PDT 2013
android/sdremote/res/drawable-hdpi/ic_action_timer.png |binary
android/sdremote/res/drawable-mdpi/ic_action_timer.png |binary
android/sdremote/res/drawable-xhdpi/ic_action_timer.png |binary
android/sdremote/res/drawable/underline_header.xml | 12
android/sdremote/res/layout/fragment_slides_pager.xml | 80 ++++
android/sdremote/res/layout/view_pager_slide.xml | 3
android/sdremote/res/menu/menu_action_bar_slide_show.xml | 27 +
android/sdremote/res/menu/menu_action_bar_slide_show_grid.xml | 10
android/sdremote/res/menu/menu_action_bar_slide_show_pager.xml | 10
android/sdremote/res/values/colors.xml | 1
android/sdremote/res/values/dimens.xml | 9
android/sdremote/res/values/strings.xml | 12
android/sdremote/res/values/themes.xml | 2
android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java | 42 +-
android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java | 165 ++++++++--
android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesGridAdapter.java | 31 +
android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesPagerAdapter.java | 19 -
android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothServersFinder.java | 31 -
android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java | 12
android/sdremote/src/org/libreoffice/impressremote/communication/MessagesReceiver.java | 2
android/sdremote/src/org/libreoffice/impressremote/communication/Server.java | 4
android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java | 29 -
android/sdremote/src/org/libreoffice/impressremote/communication/Timer.java | 128 ++-----
android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesGridFragment.java | 24 +
android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesPagerFragment.java | 90 ++++-
android/sdremote/src/org/libreoffice/impressremote/fragment/TimerEditingDialog.java | 136 ++++++++
android/sdremote/src/org/libreoffice/impressremote/fragment/TimerSettingDialog.java | 72 ++++
android/sdremote/src/org/libreoffice/impressremote/util/BluetoothOperator.java | 26 +
android/sdremote/src/org/libreoffice/impressremote/util/FragmentOperator.java | 54 +++
android/sdremote/src/org/libreoffice/impressremote/util/ImageLoader.java | 154 +++++++++
android/sdremote/src/org/libreoffice/impressremote/util/Intents.java | 29 +
31 files changed, 991 insertions(+), 223 deletions(-)
New commits:
commit f1b77bf3715b7a28cf4a9afd5f47b3e20d50ca36
Author: Artur Dryomov <artur.dryomov at gmail.com>
Date: Mon Jul 29 04:09:29 2013 +0300
Add timer support.
Show the timer as a dialog, plus update all following information as it
should be.
Change-Id: Idae00b009ce098cfd482ec79629fc8f674502c9a
diff --git a/android/sdremote/res/drawable-hdpi/ic_action_timer.png b/android/sdremote/res/drawable-hdpi/ic_action_timer.png
new file mode 100755
index 0000000..314ec93
Binary files /dev/null and b/android/sdremote/res/drawable-hdpi/ic_action_timer.png differ
diff --git a/android/sdremote/res/drawable-mdpi/ic_action_timer.png b/android/sdremote/res/drawable-mdpi/ic_action_timer.png
new file mode 100755
index 0000000..a09df2b
Binary files /dev/null and b/android/sdremote/res/drawable-mdpi/ic_action_timer.png differ
diff --git a/android/sdremote/res/drawable-xhdpi/ic_action_timer.png b/android/sdremote/res/drawable-xhdpi/ic_action_timer.png
new file mode 100755
index 0000000..c8771db
Binary files /dev/null and b/android/sdremote/res/drawable-xhdpi/ic_action_timer.png differ
diff --git a/android/sdremote/res/menu/menu_action_bar_slide_show.xml b/android/sdremote/res/menu/menu_action_bar_slide_show.xml
new file mode 100644
index 0000000..eaa2b3d
--- /dev/null
+++ b/android/sdremote/res/menu/menu_action_bar_slide_show.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/menu_slides_pager"
+ android:title="@string/menu_slides_pager"
+ android:icon="@drawable/ic_action_pager"
+ android:showAsAction="always"/>
+
+ <item
+ android:id="@+id/menu_slides_grid"
+ android:title="@string/menu_slides_grid"
+ android:icon="@drawable/ic_action_grid"
+ android:showAsAction="always"/>
+
+ <item
+ android:id="@+id/menu_timer"
+ android:title="@string/menu_timer"
+ android:icon="@drawable/ic_action_timer"
+ android:showAsAction="ifRoom"/>
+
+ <item
+ android:id="@+id/menu_stop_slide_show"
+ android:title="@string/menu_stop_slide_show"
+ android:showAsAction="never"/>
+
+</menu>
\ No newline at end of file
diff --git a/android/sdremote/res/menu/menu_action_bar_slide_show_grid.xml b/android/sdremote/res/menu/menu_action_bar_slide_show_grid.xml
deleted file mode 100644
index d65c782..0000000
--- a/android/sdremote/res/menu/menu_action_bar_slide_show_grid.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item
- android:id="@+id/menu_slides_pager"
- android:title="@string/menu_slides_pager"
- android:icon="@drawable/ic_action_pager"
- android:showAsAction="always"/>
-
-</menu>
\ No newline at end of file
diff --git a/android/sdremote/res/menu/menu_action_bar_slide_show_pager.xml b/android/sdremote/res/menu/menu_action_bar_slide_show_pager.xml
deleted file mode 100644
index 023dcd5..0000000
--- a/android/sdremote/res/menu/menu_action_bar_slide_show_pager.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item
- android:id="@+id/menu_slides_grid"
- android:title="@string/menu_slides_grid"
- android:icon="@drawable/ic_action_grid"
- android:showAsAction="always"/>
-
-</menu>
\ No newline at end of file
diff --git a/android/sdremote/res/values/strings.xml b/android/sdremote/res/values/strings.xml
index 16c1de8..f315add 100644
--- a/android/sdremote/res/values/strings.xml
+++ b/android/sdremote/res/values/strings.xml
@@ -10,6 +10,7 @@
<string name="title_connection">Connection</string>
<string name="title_creation">Creation</string>
<string name="title_slide_show">Slide Show</string>
+ <string name="title_timer">Timer</string>
<string name="menu_licenses">Open source licenses</string>
<string name="menu_reconnect">Reconnect</string>
@@ -17,9 +18,13 @@
<string name="menu_remove_computer">Remove</string>
<string name="menu_slides_grid">Slides grid</string>
<string name="menu_slides_pager">Slides pager</string>
+ <string name="menu_timer">Timer</string>
+ <string name="menu_stop_slide_show">Stop slide show</string>
<string name="button_cancel">Cancel</string>
<string name="button_save">Save</string>
+ <string name="button_start">Start</string>
+ <string name="button_reset">Reset</string>
<string name="message_impress_pin_validation">Go to âSlide Show â Impress Remoteâ in LibreOffice Impress and enter the code.</string>
<string name="message_connection_failed_title">Connection failed</string>
@@ -28,6 +33,7 @@
<string name="message_impress_pairing_check">If you have Bluetooth pairing issues check instructions related to your desktop OS.</string>
<string name="message_ip_address_validation">You should type a valid IP address.</string>
<string name="message_name_notice">Name is optional â IP address would be used instead if you wish.</string>
+ <string name="message_time_is_up">Time is up</string>
<string name="hint_ip_address">IP address</string>
<string name="hint_name">Name</string>
@@ -35,5 +41,9 @@
<string name="header_notes">Notes</string>
<string name="mask_slide_show_progress">Slide %1$d from %2$d</string>
+ <plurals name="mask_timer_progress">
+ <item quantity="one">One minute left</item>
+ <item quantity="other">%d minutes left</item>
+ </plurals>
</resources>
diff --git a/android/sdremote/res/values/themes.xml b/android/sdremote/res/values/themes.xml
index da70aa8..20a4b22 100644
--- a/android/sdremote/res/values/themes.xml
+++ b/android/sdremote/res/values/themes.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="Theme.ImpressRemote" parent="Theme.Sherlock.Light.DarkActionBar">
+ <style name="Theme.ImpressRemote" parent="Theme.Sherlock.Light.DarkActionBar.ForceOverflow">
<item name="android:actionBarStyle">@style/Theme.ImpressRemote.ActionBar</item>
<item name="actionBarStyle">@style/Theme.ImpressRemote.ActionBar</item>
diff --git a/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java b/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
index 3fa6173..2dd3b0b 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
@@ -110,7 +110,7 @@ public class ComputersActivity extends SherlockFragmentActivity implements Actio
private void setUpComputersList() {
Fragment aComputersFragment = ComputersFragment.newInstance(ComputersFragment.Type.WIFI);
- FragmentOperator.setUpFragment(this, aComputersFragment);
+ FragmentOperator.addFragment(this, aComputersFragment);
}
@Override
diff --git a/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java b/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
index 4b91a6a..06967d1 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
@@ -16,8 +16,8 @@ import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
+import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import com.actionbarsherlock.app.SherlockFragmentActivity;
@@ -26,8 +26,12 @@ import com.actionbarsherlock.view.MenuItem;
import org.libreoffice.impressremote.R;
import org.libreoffice.impressremote.communication.CommunicationService;
import org.libreoffice.impressremote.communication.SlideShow;
+import org.libreoffice.impressremote.communication.Timer;
import org.libreoffice.impressremote.fragment.SlidesGridFragment;
import org.libreoffice.impressremote.fragment.SlidesPagerFragment;
+import org.libreoffice.impressremote.fragment.TimerEditingDialog;
+import org.libreoffice.impressremote.fragment.TimerSettingDialog;
+import org.libreoffice.impressremote.util.FragmentOperator;
import org.libreoffice.impressremote.util.Intents;
public class SlideShowActivity extends SherlockFragmentActivity implements ServiceConnection {
@@ -57,7 +61,7 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
}
private void setUpFragment() {
- setUpFragment(buildFragment());
+ FragmentOperator.replaceFragmentAnimated(this, buildFragment());
}
private Fragment buildFragment() {
@@ -73,15 +77,6 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
}
}
- private void setUpFragment(Fragment aFragment) {
- FragmentTransaction aTransaction = getSupportFragmentManager().beginTransaction();
- aTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
-
- aTransaction.replace(android.R.id.content, aFragment);
-
- aTransaction.commit();
- }
-
private void bindService() {
Intent aIntent = Intents.buildCommunicationServiceIntent(this);
bindService(aIntent, this, Context.BIND_AUTO_CREATE);
@@ -124,6 +119,30 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
public void onReceive(Context aContext, Intent aIntent) {
if (Intents.Actions.SLIDE_CHANGED.equals(aIntent.getAction())) {
mSlideShowActivity.setUpSlideShowInformation();
+ return;
+ }
+
+ if (Intents.Actions.TIMER_UPDATED.equals(aIntent.getAction())) {
+ mSlideShowActivity.setUpSlideShowInformation();
+ return;
+ }
+
+ if (Intents.Actions.TIMER_STARTED.equals(aIntent.getAction())) {
+ int aMinutesLength = aIntent.getIntExtra(Intents.Extras.MINUTES, 0);
+ mSlideShowActivity.startTimer(aMinutesLength);
+ return;
+ }
+
+ if (Intents.Actions.TIMER_RESUMED.equals(aIntent.getAction())) {
+ mSlideShowActivity.resumeTimer();
+ return;
+ }
+
+ if (Intents.Actions.TIMER_CHANGED.equals(aIntent.getAction())) {
+ int aMinutesLength = aIntent.getIntExtra(Intents.Extras.MINUTES, 0);
+ mSlideShowActivity.changeTimer(aMinutesLength);
+ mSlideShowActivity.resumeTimer();
+ mSlideShowActivity.setUpSlideShowInformation();
}
}
}
@@ -131,6 +150,10 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
private IntentFilter buildIntentsReceiverFilter() {
IntentFilter aIntentFilter = new IntentFilter();
aIntentFilter.addAction(Intents.Actions.SLIDE_CHANGED);
+ aIntentFilter.addAction(Intents.Actions.TIMER_UPDATED);
+ aIntentFilter.addAction(Intents.Actions.TIMER_STARTED);
+ aIntentFilter.addAction(Intents.Actions.TIMER_RESUMED);
+ aIntentFilter.addAction(Intents.Actions.TIMER_CHANGED);
return aIntentFilter;
}
@@ -148,6 +171,10 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
getSupportActionBar().setSubtitle(buildSlideShowTimerProgress());
}
+ private boolean isServiceBound() {
+ return mCommunicationService != null;
+ }
+
private String buildSlideShowProgress() {
SlideShow aSlideShow = mCommunicationService.getSlideShow();
@@ -158,7 +185,38 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
}
private String buildSlideShowTimerProgress() {
- return null;
+ Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+
+ if (!aTimer.isSet()) {
+ return null;
+ }
+
+ if (aTimer.isTimeUp()) {
+ return getString(R.string.message_time_is_up);
+ }
+
+ int aMinutesLeft = aTimer.getMinutesLeft();
+
+ return getResources().getQuantityString(R.plurals.mask_timer_progress, aMinutesLeft, aMinutesLeft);
+ }
+
+ private void startTimer(int aMinutesLength) {
+ Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+
+ aTimer.setMinutesLength(aMinutesLength);
+ aTimer.start();
+
+ setUpSlideShowInformation();
+ }
+
+ private void resumeTimer() {
+ mCommunicationService.getSlideShow().getTimer().resume();
+ }
+
+ private void changeTimer(int aMinutesLength) {
+ Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+
+ aTimer.setMinutesLength(aMinutesLength);
}
@Override
@@ -170,27 +228,42 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
@Override
public boolean onCreateOptionsMenu(Menu aMenu) {
- getSupportMenuInflater().inflate(getActionBarMenuResourceId(), aMenu);
+ getSupportMenuInflater().inflate(R.menu.menu_action_bar_slide_show, aMenu);
return true;
}
- private int getActionBarMenuResourceId() {
+ @Override
+ public boolean onPrepareOptionsMenu(Menu aMenu) {
+ MenuItem aSlidesPagerMenuItem = aMenu.findItem(R.id.menu_slides_pager);
+ MenuItem aSlidesGridMenuItem = aMenu.findItem(R.id.menu_slides_grid);
+
switch (mMode) {
case PAGER:
- return R.menu.menu_action_bar_slide_show_pager;
+ aSlidesPagerMenuItem.setVisible(false);
+ aSlidesGridMenuItem.setVisible(true);
+ break;
case GRID:
- return R.menu.menu_action_bar_slide_show_grid;
+ aSlidesPagerMenuItem.setVisible(true);
+ aSlidesGridMenuItem.setVisible(false);
+ break;
default:
- return R.menu.menu_action_bar_slide_show_pager;
+ break;
}
+
+ return super.onPrepareOptionsMenu(aMenu);
}
@Override
public boolean onOptionsItemSelected(MenuItem aMenuItem) {
switch (aMenuItem.getItemId()) {
+ case android.R.id.home:
+ navigateUp();
+
+ return true;
+
case R.id.menu_slides_grid:
mMode = Mode.GRID;
@@ -207,8 +280,13 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
return true;
- case android.R.id.home:
- navigateUp();
+ case R.id.menu_timer:
+ callTimer();
+
+ return true;
+
+ case R.id.menu_stop_slide_show:
+ stopSlideShow();
return true;
@@ -217,11 +295,38 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
}
}
+ private void navigateUp() {
+ finish();
+ }
+
private void refreshActionBarMenu() {
supportInvalidateOptionsMenu();
}
- private void navigateUp() {
+ private void callTimer() {
+ Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+
+ if (aTimer.isSet()) {
+ int aTimerLength = aTimer.getMinutesLeft();
+
+ DialogFragment aFragment = TimerEditingDialog.newInstance(aTimerLength);
+ aFragment.show(getSupportFragmentManager(), TimerEditingDialog.TAG);
+
+ pauseTimer();
+ }
+ else {
+ DialogFragment aFragment = TimerSettingDialog.newInstance();
+ aFragment.show(getSupportFragmentManager(), TimerSettingDialog.TAG);
+ }
+ }
+
+ private void pauseTimer() {
+ mCommunicationService.getSlideShow().getTimer().pause();
+ }
+
+ private void stopSlideShow() {
+ mCommunicationService.getTransmitter().stopPresentation();
+
finish();
}
@@ -245,11 +350,17 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
protected void onDestroy() {
super.onDestroy();
+ stopTimer();
+
disconnectComputer();
unbindService();
}
+ private void stopTimer() {
+ mCommunicationService.getSlideShow().getTimer().stop();
+ }
+
private void disconnectComputer() {
if (!isServiceBound()) {
return;
@@ -258,10 +369,6 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
mCommunicationService.disconnect();
}
- private boolean isServiceBound() {
- return mCommunicationService != null;
- }
-
private void unbindService() {
if (!isServiceBound()) {
return;
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
index 2977921..6041190 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
@@ -19,7 +19,7 @@ import android.support.v4.content.LocalBroadcastManager;
import org.libreoffice.impressremote.util.Intents;
-public class CommunicationService extends Service implements Runnable, MessagesListener {
+public class CommunicationService extends Service implements Runnable, MessagesListener, Timer.TimerListener {
public static enum State {
DISCONNECTED, SEARCHING, CONNECTING, CONNECTED
}
@@ -58,7 +58,7 @@ public class CommunicationService extends Service implements Runnable, MessagesL
mServersManager = new ServersManager(this);
- mSlideShow = new SlideShow();
+ mSlideShow = new SlideShow(new Timer(this));
mThread = new Thread(this);
mThread.start();
@@ -279,6 +279,12 @@ public class CommunicationService extends Service implements Runnable, MessagesL
}
@Override
+ public void onTimerUpdated() {
+ Intent aIntent = Intents.buildTimerUpdatedIntent();
+ LocalBroadcastManager.getInstance(this).sendBroadcast(aIntent);
+ }
+
+ @Override
public void onDestroy() {
stopSearch();
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
index 0b9b1d6..f6aa6dd 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
@@ -20,14 +20,14 @@ public class SlideShow {
private final Timer mTimer;
- public SlideShow() {
+ public SlideShow(Timer aTimer) {
this.mSlidesCount = 0;
this.mCurrentSlideIndex = 0;
this.mSlidePreviewsBytes = new SparseArray<byte[]>();
this.mSlideNotes = new SparseArray<String>();
- this.mTimer = new Timer();
+ this.mTimer = aTimer;
}
public void setSlidesCount(int aSlidesCount) {
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/Timer.java b/android/sdremote/src/org/libreoffice/impressremote/communication/Timer.java
index 84a7932..9efc42e 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/Timer.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/Timer.java
@@ -8,116 +8,82 @@
*/
package org.libreoffice.impressremote.communication;
-public class Timer {
- /**
- * This stores the starting time of the timer if running.
- * <p/>
- * If paused this stores how long the timer was previously running.
- */
- private long mTime;
- private long mCountdownTime;
-
- private boolean mIsRunning;
- private boolean mIsCountdown;
-
- public Timer() {
- mTime = 0;
- mCountdownTime = 0;
-
- mIsRunning = false;
- mIsCountdown = false;
- }
+import java.util.concurrent.TimeUnit;
- /**
- * Set whether this timer should be a normal or a countdown timer.
- *
- * @param aIsCountdown Whether this should be a countdown timer.
- */
- public void setCountdown(boolean aIsCountdown) {
- mIsCountdown = aIsCountdown;
+import android.os.Handler;
- if (mIsRunning) {
- reset();
- }
+public class Timer implements Runnable {
+ public interface TimerListener {
+ public void onTimerUpdated();
}
- public boolean isCountdown() {
- return mIsCountdown;
- }
+ private static final long UPDATE_PERIOD_IN_MINUTES = 1;
+
+ private final Handler mTimerHandler;
+ private final TimerListener mTimerListener;
+
+ private int mTotalMinutes;
+ private int mPassedMinutes;
- /**
- * Set the countdown time. Can be set, and isn't lost, whatever mode
- * the timer is running in.
- *
- * @param aCountdownTime The countdown time.
- */
- public void setCountdownTime(long aCountdownTime) {
- mCountdownTime = aCountdownTime;
+ public Timer(TimerListener aTimerListener) {
+ mTimerHandler = new Handler();
+ mTimerListener = aTimerListener;
+
+ mTotalMinutes = 0;
+ mPassedMinutes = 0;
}
- public long getCountdownTime() {
- return mCountdownTime;
+ public void setMinutesLength(int aLengthInMinutes) {
+ mTotalMinutes = aLengthInMinutes;
}
- public boolean isRunning() {
- return mIsRunning;
+ public int getMinutesLength() {
+ return mTotalMinutes;
}
- /**
- * Reset the timer, and stop it it was running.
- */
- public void reset() {
- mIsRunning = false;
- mTime = 0;
+ public boolean isSet() {
+ return mTotalMinutes != 0;
}
public void start() {
- if (mIsRunning) {
+ if (!isSet()) {
return;
}
- mTime = System.currentTimeMillis() - mTime;
- mIsRunning = true;
+ mTimerHandler.postDelayed(this, TimeUnit.MINUTES.toMillis(UPDATE_PERIOD_IN_MINUTES));
}
- public void stop() {
- if (!mIsRunning)
- return;
+ @Override
+ public void run() {
+ updatePassedMinutes();
- mTime = System.currentTimeMillis() - mTime;
- mIsRunning = false;
- }
+ mTimerListener.onTimerUpdated();
- /**
- * Get either how long this timer has been running, or how long the
- * timer still has left to run.
- *
- * @return running time in millis.
- */
- public long getTimeMillis() {
- if (mIsCountdown) {
- return calculateCountdownRunningTime();
- }
+ start();
+ }
- return calculateRunningTime();
+ private void updatePassedMinutes() {
+ mPassedMinutes++;
}
- private long calculateCountdownRunningTime() {
- long aRunningTime = mCountdownTime - calculateRunningTime();
+ public void pause() {
+ stop();
+ }
- if (aRunningTime < 0) {
- reset();
- }
+ public void resume() {
+ start();
+ }
- return aRunningTime;
+ public void stop() {
+ mTimerHandler.removeCallbacks(this);
}
- private long calculateRunningTime() {
- if (mIsRunning) {
- return System.currentTimeMillis() - mTime;
- }
+ public boolean isTimeUp() {
+ return getMinutesLeft() <= 0;
+ }
- return mTime;
+ public int getMinutesLeft() {
+ return mTotalMinutes - mPassedMinutes;
}
}
diff --git a/android/sdremote/src/org/libreoffice/impressremote/fragment/TimerEditingDialog.java b/android/sdremote/src/org/libreoffice/impressremote/fragment/TimerEditingDialog.java
new file mode 100644
index 0000000..accfd8b
--- /dev/null
+++ b/android/sdremote/src/org/libreoffice/impressremote/fragment/TimerEditingDialog.java
@@ -0,0 +1,136 @@
+package org.libreoffice.impressremote.fragment;
+
+import java.util.concurrent.TimeUnit;
+
+import android.app.Dialog;
+import android.app.TimePickerDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.content.LocalBroadcastManager;
+import android.view.View;
+import android.widget.TimePicker;
+
+import com.actionbarsherlock.app.SherlockDialogFragment;
+import org.libreoffice.impressremote.R;
+import org.libreoffice.impressremote.util.Intents;
+
+public class TimerEditingDialog extends SherlockDialogFragment implements TimePickerDialog.OnTimeSetListener, DialogInterface.OnClickListener, DialogInterface.OnShowListener, View.OnClickListener {
+ public static final String TAG = "TIMER_EDITING";
+
+ private static final boolean IS_24_HOUR_VIEW = true;
+
+ private int mMinutes;
+
+ public static TimerEditingDialog newInstance(int aMinutes) {
+ TimerEditingDialog aDialog = new TimerEditingDialog();
+
+ aDialog.setArguments(buildArguments(aMinutes));
+
+ return aDialog;
+ }
+
+ private static Bundle buildArguments(int aMinutes) {
+ Bundle aArguments = new Bundle();
+
+ aArguments.putInt("MINUTES", aMinutes);
+
+ return aArguments;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mMinutes = getArguments().getInt("MINUTES");
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle aSavedInstanceState) {
+ TimePickerDialog aDialog = new TimePickerDialog(getActivity(), this,
+ getHours(mMinutes), getMinutes(mMinutes), IS_24_HOUR_VIEW);
+
+ aDialog.setTitle(R.string.title_timer);
+
+ aDialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.button_save), this);
+ aDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.button_cancel), this);
+ aDialog.setButton(DialogInterface.BUTTON_NEUTRAL, getString(R.string.button_reset), this);
+
+ aDialog.setOnShowListener(this);
+
+ return aDialog;
+ }
+
+ private int getMinutes(int aMinutes) {
+ return (int) (aMinutes - getHours(aMinutes) * TimeUnit.HOURS.toMinutes(1));
+ }
+
+ private int getHours(int aMinutes) {
+ return (int) (aMinutes / TimeUnit.HOURS.toMinutes(1));
+ }
+
+ @Override
+ public void onTimeSet(TimePicker aTimePicker, int aHour, int aMinute) {
+ mMinutes = getMinutes(aHour, aMinute);
+ }
+
+ private int getMinutes(int aHours, int aMinutes) {
+ return (int) (TimeUnit.HOURS.toMinutes(aHours) + aMinutes);
+ }
+
+ @Override
+ public void onClick(DialogInterface aDialogInterface, int aButtonId) {
+ getTimePickerDialog().onClick(aDialogInterface, aButtonId);
+
+ switch (aButtonId) {
+ case DialogInterface.BUTTON_NEGATIVE:
+ resumeTimer();
+ break;
+
+ case DialogInterface.BUTTON_POSITIVE:
+ changeTimer();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ private TimePickerDialog getTimePickerDialog() {
+ return (TimePickerDialog) getDialog();
+ }
+
+ private void resumeTimer() {
+ Intent aIntent = Intents.buildTimerResumedIntent();
+ LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(aIntent);
+ }
+
+ private void changeTimer() {
+ Intent aIntent = Intents.buildTimerChangedIntent(mMinutes);
+ LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(aIntent);
+ }
+
+ @Override
+ public void onShow(DialogInterface dialogInterface) {
+ setUpNeutralButton();
+ }
+
+ private void setUpNeutralButton() {
+ TimePickerDialog aDialog = (TimePickerDialog) getDialog();
+
+ aDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View aView) {
+ // Requires the additional listener to not close the dialog.
+
+ resetTime();
+ }
+
+ private void resetTime() {
+ TimePickerDialog aDialog = (TimePickerDialog) getDialog();
+
+ aDialog.updateTime(0, 0);
+ }
+}
diff --git a/android/sdremote/src/org/libreoffice/impressremote/fragment/TimerSettingDialog.java b/android/sdremote/src/org/libreoffice/impressremote/fragment/TimerSettingDialog.java
new file mode 100644
index 0000000..99374f8
--- /dev/null
+++ b/android/sdremote/src/org/libreoffice/impressremote/fragment/TimerSettingDialog.java
@@ -0,0 +1,72 @@
+package org.libreoffice.impressremote.fragment;
+
+import java.util.concurrent.TimeUnit;
+
+import android.app.Dialog;
+import android.app.TimePickerDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.content.LocalBroadcastManager;
+import android.widget.TimePicker;
+
+import com.actionbarsherlock.app.SherlockDialogFragment;
+import org.libreoffice.impressremote.R;
+import org.libreoffice.impressremote.util.Intents;
+
+public class TimerSettingDialog extends SherlockDialogFragment implements TimePickerDialog.OnTimeSetListener, DialogInterface.OnClickListener {
+ public static final String TAG = "TIMER_SETTING";
+
+ private static final int INITIAL_HOUR = 0;
+ private static final int INITIAL_MINUTE = 15;
+
+ private static final boolean IS_24_HOUR_VIEW = true;
+
+ private int mMinutes;
+
+ public static TimerSettingDialog newInstance() {
+ return new TimerSettingDialog();
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle aSavedInstanceState) {
+ TimePickerDialog aDialog = new TimePickerDialog(getActivity(), this,
+ INITIAL_HOUR, INITIAL_MINUTE, IS_24_HOUR_VIEW);
+
+ aDialog.setTitle(R.string.title_timer);
+
+ aDialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.button_start), this);
+ aDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.button_cancel), this);
+
+ return aDialog;
+ }
+
+ @Override
+ public void onTimeSet(TimePicker aTimePicker, int aHour, int aMinute) {
+ mMinutes = getMinutes(aHour, aMinute);
+ }
+
+ private int getMinutes(int aHours, int aMinutes) {
+ return (int) (TimeUnit.HOURS.toMinutes(aHours) + aMinutes);
+ }
+
+ @Override
+ public void onClick(DialogInterface aDialogInterface, int aButtonId) {
+ getTimePickerDialog().onClick(aDialogInterface, aButtonId);
+
+ if (aButtonId != DialogInterface.BUTTON_POSITIVE) {
+ return;
+ }
+
+ startTimer();
+ }
+
+ private TimePickerDialog getTimePickerDialog() {
+ return (TimePickerDialog) getDialog();
+ }
+
+ private void startTimer() {
+ Intent aIntent = Intents.buildTimerStartedIntent(mMinutes);
+ LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(aIntent);
+ }
+}
diff --git a/android/sdremote/src/org/libreoffice/impressremote/util/FragmentOperator.java b/android/sdremote/src/org/libreoffice/impressremote/util/FragmentOperator.java
index 3c65063..af7e47c 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/util/FragmentOperator.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/util/FragmentOperator.java
@@ -17,25 +17,35 @@ public final class FragmentOperator {
private FragmentOperator() {
}
- public static void setUpFragment(FragmentActivity aActivity, Fragment aFragment) {
- if (isFragmentSetUp(aActivity)) {
+ public static void addFragment(FragmentActivity aActivity, Fragment aFragment) {
+ if (isFragmentAdded(aActivity)) {
return;
}
- installFragment(aActivity, aFragment);
+ FragmentTransaction aFragmentTransaction = beginFragmentTransaction(aActivity);
+
+ aFragmentTransaction.add(android.R.id.content, aFragment);
+
+ aFragmentTransaction.commit();
}
- private static boolean isFragmentSetUp(FragmentActivity aActivity) {
+ private static boolean isFragmentAdded(FragmentActivity aActivity) {
FragmentManager aFragmentManager = aActivity.getSupportFragmentManager();
return aFragmentManager.findFragmentById(android.R.id.content) != null;
}
- private static void installFragment(FragmentActivity aActivity, Fragment aFragment) {
+ private static FragmentTransaction beginFragmentTransaction(FragmentActivity aActivity) {
FragmentManager aFragmentManager = aActivity.getSupportFragmentManager();
- FragmentTransaction aFragmentTransaction = aFragmentManager.beginTransaction();
- aFragmentTransaction.add(android.R.id.content, aFragment);
+ return aFragmentManager.beginTransaction();
+ }
+
+ public static void replaceFragmentAnimated(FragmentActivity aActivity, Fragment aFragment) {
+ FragmentTransaction aFragmentTransaction = beginFragmentTransaction(aActivity);
+ aFragmentTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
+
+ aFragmentTransaction.replace(android.R.id.content, aFragment);
aFragmentTransaction.commit();
}
diff --git a/android/sdremote/src/org/libreoffice/impressremote/util/Intents.java b/android/sdremote/src/org/libreoffice/impressremote/util/Intents.java
index ad7cfc1..eb85418 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/util/Intents.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/util/Intents.java
@@ -39,6 +39,11 @@ public final class Intents {
public static final String SLIDE_CHANGED = "SLIDE_CHANGED";
public static final String SLIDE_PREVIEW = "SLIDE_PREVIEW";
public static final String SLIDE_NOTES = "SLIDE_NOTES";
+
+ public static final String TIMER_UPDATED = "TIMER_UPDATED";
+ public static final String TIMER_STARTED = "TIMER_STARTED";
+ public static final String TIMER_RESUMED = "TIMER_RESUMED";
+ public static final String TIMER_CHANGED = "TIMER_CHANGED";
}
public static final class Extras {
@@ -52,6 +57,8 @@ public final class Intents {
public static final String SERVER_NAME = "SERVER_NAME";
public static final String SLIDE_INDEX = "SLIDE_INDEX";
+
+ public static final String MINUTES = "MINUTES";
}
public static final class RequestCodes {
@@ -139,6 +146,28 @@ public final class Intents {
public static Intent buildCommunicationServiceIntent(Context aContext) {
return new Intent(aContext, CommunicationService.class);
}
+
+ public static Intent buildTimerUpdatedIntent() {
+ return new Intent(Actions.TIMER_UPDATED);
+ }
+
+ public static Intent buildTimerStartedIntent(int aMinutesLength) {
+ Intent aIntent = new Intent(Actions.TIMER_STARTED);
+ aIntent.putExtra(Extras.MINUTES, aMinutesLength);
+
+ return aIntent;
+ }
+
+ public static Intent buildTimerResumedIntent() {
+ return new Intent(Actions.TIMER_RESUMED);
+ }
+
+ public static Intent buildTimerChangedIntent(int aMinutesLength) {
+ Intent aIntent = new Intent(Actions.TIMER_CHANGED);
+ aIntent.putExtra(Extras.MINUTES, aMinutesLength);
+
+ return aIntent;
+ }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 766b6f5b14b517e178c9b86611d0edb7582e1ede
Author: Artur Dryomov <artur.dryomov at gmail.com>
Date: Sat Jul 27 23:17:50 2013 +0300
Add notes support.
It is not possible at moment to add borders to slides previews because
ViewPager has no constant height and ignores wrap_content property. The
current solution seems to be the best.
Change-Id: I14b41e0bda578d2ffcdb1c887d633c6201aa383a
diff --git a/android/sdremote/res/drawable/underline_header.xml b/android/sdremote/res/drawable/underline_header.xml
new file mode 100644
index 0000000..cee5b99
--- /dev/null
+++ b/android/sdremote/res/drawable/underline_header.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <size
+ android:width="10000dp"
+ android:height="1dp"/>
+
+ <solid
+ android:color="@color/background_header"/>
+
+</shape>
\ No newline at end of file
diff --git a/android/sdremote/res/layout/fragment_slides_pager.xml b/android/sdremote/res/layout/fragment_slides_pager.xml
index 14e5cf1..20b4336 100644
--- a/android/sdremote/res/layout/fragment_slides_pager.xml
+++ b/android/sdremote/res/layout/fragment_slides_pager.xml
@@ -1,13 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingTop="@dimen/padding_slides_pager"
+ android:paddingBottom="@dimen/padding_slides_pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager_slides"
- android:padding="@dimen/padding_slides_pager"
- android:layout_centerInParent="true"
+ android:layout_weight="4"
android:layout_width="match_parent"
- android:layout_height="@dimen/height_slides_pager"/>
+ android:layout_height="0dp"/>
-</RelativeLayout>
+ <ViewAnimator
+ android:id="@+id/view_animator"
+ android:inAnimation="@android:anim/fade_in"
+ android:outAnimation="@android:anim/fade_out"
+ android:layout_weight="3"
+ android:layout_width="match_parent"
+ android:layout_height="0dp">
+
+ <View
+ android:id="@+id/view_empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
+ <LinearLayout
+ android:id="@+id/layout_notes"
+ android:orientation="vertical"
+ android:paddingLeft="@dimen/padding_slides_pager"
+ android:paddingRight="@dimen/padding_slides_pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:text="@string/header_notes"
+ android:textAllCaps="true"
+ android:textStyle="bold"
+ android:textColor="@color/background_header"
+ android:drawableBottom="@drawable/underline_header"
+ android:drawablePadding="4dp"
+ android:paddingLeft="@dimen/padding_header"
+ android:paddingTop="@dimen/padding_header"
+ android:gravity="left"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ <ScrollView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextSwitcher
+ android:id="@+id/text_switcher_notes"
+ android:inAnimation="@android:anim/fade_in"
+ android:outAnimation="@android:anim/fade_out"
+ android:paddingTop="@dimen/padding_slide_notes"
+ android:paddingLeft="@dimen/padding_slide_notes"
+ android:paddingRight="@dimen/padding_slide_notes"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ </TextSwitcher>
+
+ </ScrollView>
+
+ </LinearLayout>
+
+ </ViewAnimator>
+
+</LinearLayout>
diff --git a/android/sdremote/res/layout/view_pager_slide.xml b/android/sdremote/res/layout/view_pager_slide.xml
index 0ebb367..6ca8f91 100644
--- a/android/sdremote/res/layout/view_pager_slide.xml
+++ b/android/sdremote/res/layout/view_pager_slide.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/image_slide_preview"
- android:background="@drawable/background_pager_slide"
- android:adjustViewBounds="true"
+ android:scaleType="fitCenter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
\ No newline at end of file
diff --git a/android/sdremote/res/values/colors.xml b/android/sdremote/res/values/colors.xml
index ed05f91..f43e8f1 100644
--- a/android/sdremote/res/values/colors.xml
+++ b/android/sdremote/res/values/colors.xml
@@ -3,6 +3,7 @@
<color name="background_action_bar">#e46f1f</color>
<color name="background_action_bar_divider">#55ffffff</color>
+ <color name="background_header">@color/background_action_bar</color>
<color name="background_slide_index">#7f000000</color>
<color name="stroke_grid_slide">#65000000</color>
diff --git a/android/sdremote/res/values/dimens.xml b/android/sdremote/res/values/dimens.xml
index d4c2e5b..9a079a6 100644
--- a/android/sdremote/res/values/dimens.xml
+++ b/android/sdremote/res/values/dimens.xml
@@ -1,11 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
+ <!-- It is a good practice to follow official design metrics. -->
+ <!-- http://developer.android.com/design/style/metrics-grids.html -->
+
<dimen name="padding_action_bar_button_drawable">8dp</dimen>
<dimen name="padding_creation_layout">16dp</dimen>
<dimen name="padding_slides_grid">4dp</dimen>
<dimen name="padding_slides_pager">16dp</dimen>
<dimen name="padding_slide">4dp</dimen>
+ <dimen name="padding_header_underline">4dp</dimen>
+ <dimen name="padding_slides_pager_layout">8dp</dimen>
+ <dimen name="padding_header">8dp</dimen>
+ <dimen name="padding_slide_notes">8dp</dimen>
<dimen name="padding_horizontal_list_item">8dp</dimen>
<dimen name="padding_horizontal_connection_layout">40dp</dimen>
@@ -29,6 +36,4 @@
<dimen name="spacing_slides_grid">4dp</dimen>
- <dimen name="height_slides_pager">250dp</dimen>
-
</resources>
\ No newline at end of file
diff --git a/android/sdremote/res/values/strings.xml b/android/sdremote/res/values/strings.xml
index 5bc0298..16c1de8 100644
--- a/android/sdremote/res/values/strings.xml
+++ b/android/sdremote/res/values/strings.xml
@@ -32,6 +32,8 @@
<string name="hint_ip_address">IP address</string>
<string name="hint_name">Name</string>
+ <string name="header_notes">Notes</string>
+
<string name="mask_slide_show_progress">Slide %1$d from %2$d</string>
</resources>
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
index a216dfc..0b9b1d6 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
@@ -65,11 +65,11 @@ public class SlideShow {
public String getSlideNotes(int aSlideIndex) {
String aSlideNotes = mSlideNotes.get(aSlideIndex);
- if (aSlideNotes != null) {
- return aSlideNotes;
- } else {
+ if (aSlideNotes == null) {
return "";
}
+
+ return aSlideNotes;
}
public Timer getTimer() {
diff --git a/android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesPagerFragment.java b/android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesPagerFragment.java
index cb9872f..adbc74b 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesPagerFragment.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesPagerFragment.java
@@ -17,13 +17,21 @@ import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
+import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
+import android.text.Html;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextSwitcher;
+import android.widget.TextView;
+import android.widget.ViewAnimator;
import com.actionbarsherlock.app.SherlockFragment;
+import org.libreoffice.impressremote.communication.SlideShow;
import org.libreoffice.impressremote.util.Intents;
import org.libreoffice.impressremote.R;
import org.libreoffice.impressremote.adapter.SlidesPagerAdapter;
@@ -50,52 +58,94 @@ public class SlidesPagerFragment extends SherlockFragment implements ServiceConn
}
private void bindService() {
- Intent aServiceIntent = new Intent(getActivity(), CommunicationService.class);
-
+ Intent aServiceIntent = Intents.buildCommunicationServiceIntent(getActivity());
getActivity().bindService(aServiceIntent, this, Context.BIND_AUTO_CREATE);
}
@Override
public void onServiceConnected(ComponentName aComponentName, IBinder aBinder) {
CommunicationService.CBinder aServiceBinder = (CommunicationService.CBinder) aBinder;
-
mCommunicationService = aServiceBinder.getService();
setUpSlidesPager();
}
private void setUpSlidesPager() {
- SlidesPagerAdapter aSlidesPagerAdapter = new SlidesPagerAdapter(getActivity(),
- mCommunicationService.getSlideShow());
-
- getSlidesPager().setAdapter(aSlidesPagerAdapter);
-
- getSlidesPager().setCurrentItem(mCommunicationService.getSlideShow().getCurrentSlideIndex());
-
- getSlidesPager().setPageMargin(getSlidesMarginInPx());
+ ViewPager aSlidesPager = getSlidesPager();
- getSlidesPager().setOnPageChangeListener(this);
+ aSlidesPager.setAdapter(buildSlidesAdapter());
+ aSlidesPager.setCurrentItem(mCommunicationService.getSlideShow().getCurrentSlideIndex());
+ aSlidesPager.setPageMargin(getSlidesMarginInPx());
+ aSlidesPager.setOnPageChangeListener(this);
}
private ViewPager getSlidesPager() {
return (ViewPager) getView().findViewById(R.id.pager_slides);
}
+ private PagerAdapter buildSlidesAdapter() {
+ SlideShow aSlideShow = mCommunicationService.getSlideShow();
+
+ return new SlidesPagerAdapter(getActivity(), aSlideShow);
+ }
+
private int getSlidesMarginInPx() {
+ int aPxUnit = TypedValue.COMPLEX_UNIT_PX;
float aSlideMarginInDp = getResources().getDimension(R.dimen.margin_slide);
+ DisplayMetrics aDisplayMetrics = getResources().getDisplayMetrics();
- return (int) TypedValue
- .applyDimension(TypedValue.COMPLEX_UNIT_PX, aSlideMarginInDp,
- getResources().getDisplayMetrics());
+ return (int) TypedValue.applyDimension(aPxUnit, aSlideMarginInDp, aDisplayMetrics);
}
@Override
- public void onPageScrolled(int aPosition, float aPositionOffset, int aPositionOffsetPixels) {
+ public void onPageSelected(int aPosition) {
+ mCommunicationService.getTransmitter().setCurrentSlide(aPosition);
+
+ setUpSlideNotes(aPosition);
+ }
+
+ private void setUpSlideNotes(int aSlideIndex) {
+ if (areSlideNotesAvailable(aSlideIndex)) {
+ showSlideNotes(aSlideIndex);
+ }
+ else {
+ hideSlideNotes();
+ }
+ }
+
+ private boolean areSlideNotesAvailable(int aSlideIndex) {
+ String aSlideNotes = mCommunicationService.getSlideShow().getSlideNotes(aSlideIndex);
+
+ return !TextUtils.isEmpty(Html.fromHtml(aSlideNotes).toString().trim());
+ }
+
+ private void showSlideNotes(int aSlideIndex) {
+ ViewAnimator aViewAnimator = (ViewAnimator) getView().findViewById(R.id.view_animator);
+ ViewGroup aNotesLayout = (ViewGroup) getView().findViewById(R.id.layout_notes);
+
+ if (aViewAnimator.getDisplayedChild() != aViewAnimator.indexOfChild(aNotesLayout)) {
+ aViewAnimator.setDisplayedChild(aViewAnimator.indexOfChild(aNotesLayout));
+ }
+
+ setSlideNotes(aSlideIndex);
+ }
+
+ private void setSlideNotes(int aSlideIndex) {
+ TextSwitcher aSlideNotesTextSwitcher = (TextSwitcher) getView().findViewById(R.id.text_switcher_notes);
+ String aSlideNotes = mCommunicationService.getSlideShow().getSlideNotes(aSlideIndex);
+
+ aSlideNotesTextSwitcher.setText(Html.fromHtml(aSlideNotes));
+ }
+
+ private void hideSlideNotes() {
+ ViewAnimator aViewAnimator = (ViewAnimator) getView().findViewById(R.id.view_animator);
+ View aEmptyView = getView().findViewById(R.id.view_empty);
+
+ aViewAnimator.setDisplayedChild(aViewAnimator.indexOfChild(aEmptyView));
}
@Override
- public void onPageSelected(int aPosition) {
- mCommunicationService.getTransmitter().setCurrentSlide(aPosition);
+ public void onPageScrolled(int aPosition, float aPositionOffset, int aPositionOffsetPixels) {
}
@Override
@@ -131,7 +181,7 @@ public class SlidesPagerFragment extends SherlockFragment implements ServiceConn
@Override
public void onReceive(Context aContext, Intent aIntent) {
if (Intents.Actions.SLIDE_PREVIEW.equals(aIntent.getAction())) {
- mSlidesGridFragment.refreshSlidesGrid();
+ mSlidesGridFragment.refreshSlidesPager();
}
}
}
@@ -149,7 +199,7 @@ public class SlidesPagerFragment extends SherlockFragment implements ServiceConn
return LocalBroadcastManager.getInstance(aContext);
}
- private void refreshSlidesGrid() {
+ private void refreshSlidesPager() {
getSlidesPager().getAdapter().notifyDataSetChanged();
}
commit a92fa984ae24dc25283d4b6805cff01bf00117e5
Author: Artur Dryomov <artur.dryomov at gmail.com>
Date: Sat Jul 27 16:30:17 2013 +0300
Add async slide previews loading.
* The previews storage contains bytes arrays instead of Bitmaps which
should decrease memory footprint.
* All previews processing moved to the background thread.
This change should solve out of memory errors.
Change-Id: Idd4046020c8fe8f977858f1911e04c0ec095380a
diff --git a/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java b/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
index 7de2ee4..4b91a6a 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
@@ -245,21 +245,31 @@ public class SlideShowActivity extends SherlockFragmentActivity implements Servi
protected void onDestroy() {
super.onDestroy();
+ disconnectComputer();
+
unbindService();
}
- private void unbindService() {
+ private void disconnectComputer() {
if (!isServiceBound()) {
return;
}
- unbindService(this);
+ mCommunicationService.disconnect();
}
private boolean isServiceBound() {
return mCommunicationService != null;
}
+ private void unbindService() {
+ if (!isServiceBound()) {
+ return;
+ }
+
+ unbindService(this);
+ }
+
@Override
public void onServiceDisconnected(ComponentName aComponentName) {
mCommunicationService = null;
diff --git a/android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesGridAdapter.java b/android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesGridAdapter.java
index f7f7a01..846226f 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesGridAdapter.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesGridAdapter.java
@@ -18,14 +18,17 @@ import android.widget.TextView;
import org.libreoffice.impressremote.R;
import org.libreoffice.impressremote.communication.SlideShow;
+import org.libreoffice.impressremote.util.ImageLoader;
public class SlidesGridAdapter extends BaseAdapter {
private final LayoutInflater mLayoutInflater;
+ private final ImageLoader mImageLoader;
private final SlideShow mSlideShow;
public SlidesGridAdapter(Context aContext, SlideShow aSlideShow) {
mLayoutInflater = LayoutInflater.from(aContext);
+ mImageLoader = new ImageLoader(aContext.getResources(), R.drawable.slide_unknown);
mSlideShow = aSlideShow;
}
@@ -37,7 +40,7 @@ public class SlidesGridAdapter extends BaseAdapter {
@Override
public Object getItem(int aPosition) {
- return mSlideShow.getSlidePreview(aPosition);
+ return mSlideShow.getSlidePreviewBytes(aPosition);
}
@Override
@@ -51,12 +54,12 @@ public class SlidesGridAdapter extends BaseAdapter {
ViewHolder aSlideViewHolder = getViewHolder(aSlideView);
if (isSlidePreviewAvailable(aPosition)) {
- aSlideViewHolder.aSlidePreview.setImageBitmap(mSlideShow.getSlidePreview(aPosition));
+ setUpSlidePreview(aSlideViewHolder, aPosition);
} else {
- aSlideViewHolder.aSlidePreview.setImageResource(R.drawable.slide_unknown);
+ setUpUnknownSlidePreview(aSlideViewHolder);
}
- aSlideViewHolder.aSlideIndex.setText(buildSlideIndex(aPosition));
+ aSlideViewHolder.mSlideIndex.setText(buildSlideIndex(aPosition));
return aSlideView;
}
@@ -78,21 +81,31 @@ public class SlidesGridAdapter extends BaseAdapter {
}
private static final class ViewHolder {
- public ImageView aSlidePreview;
- public TextView aSlideIndex;
+ public ImageView mSlidePreview;
+ public TextView mSlideIndex;
}
private ViewHolder buildViewHolder(View aView) {
ViewHolder aViewHolder = new ViewHolder();
- aViewHolder.aSlidePreview = (ImageView) aView.findViewById(R.id.image_slide_preview);
- aViewHolder.aSlideIndex = (TextView) aView.findViewById(R.id.text_slide_index);
+ aViewHolder.mSlidePreview = (ImageView) aView.findViewById(R.id.image_slide_preview);
+ aViewHolder.mSlideIndex = (TextView) aView.findViewById(R.id.text_slide_index);
return aViewHolder;
}
private boolean isSlidePreviewAvailable(int aSlideIndex) {
- return mSlideShow.getSlidePreview(aSlideIndex) != null;
+ return mSlideShow.getSlidePreviewBytes(aSlideIndex) != null;
+ }
+
+ private void setUpSlidePreview(ViewHolder aSlideViewHolder, int aPosition) {
+ byte[] aSlidePreviewBytes = mSlideShow.getSlidePreviewBytes(aPosition);
+
+ mImageLoader.loadImage(aSlideViewHolder.mSlidePreview, aSlidePreviewBytes);
+ }
+
+ private void setUpUnknownSlidePreview(ViewHolder aSlideViewHolder) {
+ aSlideViewHolder.mSlidePreview.setImageResource(R.drawable.slide_unknown);
}
private String buildSlideIndex(int aPosition) {
diff --git a/android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesPagerAdapter.java b/android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesPagerAdapter.java
index 352e7a8..02097d2 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesPagerAdapter.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/adapter/SlidesPagerAdapter.java
@@ -17,14 +17,17 @@ import android.widget.ImageView;
import org.libreoffice.impressremote.R;
import org.libreoffice.impressremote.communication.SlideShow;
+import org.libreoffice.impressremote.util.ImageLoader;
public class SlidesPagerAdapter extends PagerAdapter {
private final LayoutInflater mLayoutInflater;
+ private final ImageLoader mImageLoader;
private final SlideShow mSlideShow;
public SlidesPagerAdapter(Context aContext, SlideShow aSlideShow) {
mLayoutInflater = LayoutInflater.from(aContext);
+ mImageLoader = new ImageLoader(aContext.getResources(), R.drawable.slide_unknown);
mSlideShow = aSlideShow;
}
@@ -39,10 +42,10 @@ public class SlidesPagerAdapter extends PagerAdapter {
ImageView aSlideView = (ImageView) getView(aViewGroup);
if (isSlidePreviewAvailable(aPosition)) {
- aSlideView.setImageBitmap(mSlideShow.getSlidePreview(aPosition));
+ setUpSlidePreview(aSlideView, aPosition);
}
else {
- aSlideView.setImageResource(R.drawable.slide_unknown);
+ setUpUnknownSlidePreview(aSlideView);
}
aViewGroup.addView(aSlideView);
@@ -55,7 +58,17 @@ public class SlidesPagerAdapter extends PagerAdapter {
}
private boolean isSlidePreviewAvailable(int aSlideIndex) {
- return mSlideShow.getSlidePreview(aSlideIndex) != null;
+ return mSlideShow.getSlidePreviewBytes(aSlideIndex) != null;
+ }
+
+ private void setUpSlidePreview(ImageView aSlideView, int aPosition) {
+ byte[] aSlidePreviewBytes = mSlideShow.getSlidePreviewBytes(aPosition);
+
+ mImageLoader.loadImage(aSlideView, aSlidePreviewBytes);
+ }
+
+ private void setUpUnknownSlidePreview(ImageView aSlideView) {
+ aSlideView.setImageResource(R.drawable.slide_unknown);
}
@Override
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
index 2e32813..2977921 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
@@ -264,7 +264,7 @@ public class CommunicationService extends Service implements Runnable, MessagesL
@Override
public void onSlidePreview(int aSlideIndex, byte[] aPreview) {
- mSlideShow.setSlidePreview(aSlideIndex, aPreview);
+ mSlideShow.setSlidePreviewBytes(aSlideIndex, aPreview);
Intent aIntent = Intents.buildSlidePreviewIntent(aSlideIndex);
LocalBroadcastManager.getInstance(this).sendBroadcast(aIntent);
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/MessagesReceiver.java b/android/sdremote/src/org/libreoffice/impressremote/communication/MessagesReceiver.java
index 4d226d8..bb6de8f 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/MessagesReceiver.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/MessagesReceiver.java
@@ -14,10 +14,12 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import android.text.TextUtils;
import android.util.Base64;
+import android.util.Log;
class MessagesReceiver implements Runnable {
private final BufferedReader mMessagesReader;
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
index 79852c5..a216dfc 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
@@ -8,8 +8,6 @@
*/
package org.libreoffice.impressremote.communication;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.util.SparseArray;
@@ -17,7 +15,7 @@ public class SlideShow {
private int mSlidesCount;
private int mCurrentSlideIndex;
- private final SparseArray<Bitmap> mSlidePreviews;
+ private final SparseArray<byte[]> mSlidePreviewsBytes;
private final SparseArray<String> mSlideNotes;
private final Timer mTimer;
@@ -26,7 +24,7 @@ public class SlideShow {
this.mSlidesCount = 0;
this.mCurrentSlideIndex = 0;
- this.mSlidePreviews = new SparseArray<Bitmap>();
+ this.mSlidePreviewsBytes = new SparseArray<byte[]>();
this.mSlideNotes = new SparseArray<String>();
this.mTimer = new Timer();
@@ -52,15 +50,12 @@ public class SlideShow {
return getCurrentSlideIndex() + 1;
}
- public void setSlidePreview(int aSlideIndex, byte[] aSlidePreviewBytes) {
- Bitmap aSlidePreview = BitmapFactory
- .decodeByteArray(aSlidePreviewBytes, 0, aSlidePreviewBytes.length);
-
- mSlidePreviews.put(aSlideIndex, aSlidePreview);
+ public void setSlidePreviewBytes(int aSlideIndex, byte[] aSlidePreviewBytes) {
+ mSlidePreviewsBytes.put(aSlideIndex, aSlidePreviewBytes);
}
- public Bitmap getSlidePreview(int aSlideIndex) {
- return mSlidePreviews.get(aSlideIndex);
+ public byte[] getSlidePreviewBytes(int aSlideIndex) {
+ return mSlidePreviewsBytes.get(aSlideIndex);
}
public void setSlideNotes(int aSlideIndex, String aSlideNotes) {
@@ -85,7 +80,7 @@ public class SlideShow {
mSlidesCount = 0;
mCurrentSlideIndex = 0;
- mSlidePreviews.clear();
+ mSlidePreviewsBytes.clear();
mSlideNotes.clear();
}
}
diff --git a/android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesGridFragment.java b/android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesGridFragment.java
index ebc9a24..25e2819 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesGridFragment.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/fragment/SlidesGridFragment.java
@@ -51,14 +51,12 @@ public class SlidesGridFragment extends SherlockFragment implements ServiceConne
private void bindService() {
Intent aServiceIntent = new Intent(getActivity(), CommunicationService.class);
-
getActivity().bindService(aServiceIntent, this, Context.BIND_AUTO_CREATE);
}
@Override
public void onServiceConnected(ComponentName aComponentName, IBinder aBinder) {
CommunicationService.CBinder aServiceBinder = (CommunicationService.CBinder) aBinder;
-
mCommunicationService = aServiceBinder.getService();
setUpSlidesGrid();
@@ -109,14 +107,23 @@ public class SlidesGridFragment extends SherlockFragment implements ServiceConne
@Override
public void onReceive(Context aContext, Intent aIntent) {
- if (Intents.Actions.SLIDE_PREVIEW.equals(aIntent.getAction())) {
+ if (Intents.Actions.SLIDE_SHOW_RUNNING.equals(aIntent.getAction())) {
mSlidesGridFragment.refreshSlidesGrid();
+
+ return;
+ }
+
+ if (Intents.Actions.SLIDE_PREVIEW.equals(aIntent.getAction())) {
+ int aSlideIndex = aIntent.getIntExtra(Intents.Extras.SLIDE_INDEX, 0);
+
+ mSlidesGridFragment.refreshSlidePreview(aSlideIndex);
}
}
}
private IntentFilter buildIntentsReceiverFilter() {
IntentFilter aIntentFilter = new IntentFilter();
+ aIntentFilter.addAction(Intents.Actions.SLIDE_SHOW_RUNNING);
aIntentFilter.addAction(Intents.Actions.SLIDE_PREVIEW);
return aIntentFilter;
@@ -132,6 +139,17 @@ public class SlidesGridFragment extends SherlockFragment implements ServiceConne
getSlidesGrid().invalidateViews();
}
+ private void refreshSlidePreview(int aSlideIndex) {
+ GridView aSlidesGrid = getSlidesGrid();
+ View aSlideView = aSlidesGrid.getChildAt(aSlideIndex);
+
+ if (aSlideView == null) {
+ return;
+ }
+
+ aSlidesGrid.getAdapter().getView(aSlideIndex, aSlideView, aSlidesGrid);
+ }
+
@Override
public void onPause() {
super.onPause();
diff --git a/android/sdremote/src/org/libreoffice/impressremote/util/ImageLoader.java b/android/sdremote/src/org/libreoffice/impressremote/util/ImageLoader.java
new file mode 100644
index 0000000..1bd2f4f
--- /dev/null
+++ b/android/sdremote/src/org/libreoffice/impressremote/util/ImageLoader.java
@@ -0,0 +1,154 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+package org.libreoffice.impressremote.util;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.widget.ImageView;
+
+public final class ImageLoader {
+ private final Resources mResources;
+ private final Bitmap mLoadingImage;
+
+ public ImageLoader(Resources aResources, int aLoadingImageResourceId) {
+ mResources = aResources;
+ mLoadingImage = BitmapFactory.decodeResource(mResources, aLoadingImageResourceId);
+ }
+
+ public void loadImage(ImageView aImageView, byte[] aImageBytes) {
+ if (isSameImageLoading(aImageView, aImageBytes)) {
+ return;
+ }
+
+ if (isImageLoadingCancellationRequired(aImageView, aImageBytes)) {
+ cancelImageLoading(aImageView);
+ }
+
+ startImageLoading(aImageView, aImageBytes);
+ }
+
+ private boolean isSameImageLoading(ImageView aImageView, byte[] aImageBytes) {
+ if (!isImageLoading(aImageView)) {
+ return false;
+ }
+
+ ImageLoadingTask aImageLoadingTask = getImageLoadingTask(aImageView);
+
+ return Arrays.equals(aImageBytes, aImageLoadingTask.getImageBytes());
+ }
+
+ private boolean isImageLoading(ImageView aImageView) {
+ ImageLoadingTask aImageLoadingTask = getImageLoadingTask(aImageView);
+
+ return aImageLoadingTask != null;
+ }
+
+ private ImageLoadingTask getImageLoadingTask(ImageView aImageView) {
+ if (aImageView == null) {
+ return null;
+ }
+
+ Drawable aImageDrawable = aImageView.getDrawable();
+
+ if (!(aImageDrawable instanceof AsyncDrawable)) {
+ return null;
+ }
+
+ AsyncDrawable aAsyncImageDrawable = (AsyncDrawable) aImageDrawable;
+
+ return aAsyncImageDrawable.getImageLoadingTask();
+ }
+
+ private boolean isImageLoadingCancellationRequired(ImageView aImageView, byte[] aImageBytes) {
+ return isImageLoading(aImageView) && !isSameImageLoading(aImageView, aImageBytes);
+ }
+
+ private void cancelImageLoading(ImageView aImageView) {
+ ImageLoadingTask aImageLoadingTask = getImageLoadingTask(aImageView);
+
+ aImageLoadingTask.cancel(true);
+ }
+
+ private void startImageLoading(ImageView aImageView, byte[] aImageBytes) {
+ ImageLoadingTask aImageLoadingTask = new ImageLoadingTask(aImageView, aImageBytes);
+ AsyncDrawable aAsyncDrawable = new AsyncDrawable(mResources, mLoadingImage, aImageLoadingTask);
+
+ aImageView.setImageDrawable(aAsyncDrawable);
+ aImageLoadingTask.execute();
+ }
+
+ private static class ImageLoadingTask extends AsyncTask<Void, Void, Bitmap> {
+ private final WeakReference<ImageView> mImageViewReference;
+ private final byte[] mImageBytes;
+
+ public ImageLoadingTask(ImageView aImageView, byte[] aImageBytes) {
+ mImageViewReference = new WeakReference<ImageView>(aImageView);
+ mImageBytes = aImageBytes;
+ }
+
+ public byte[] getImageBytes() {
+ return mImageBytes;
+ }
+
+ @Override
+ protected Bitmap doInBackground(Void... aParameters) {
+ return BitmapFactory.decodeByteArray(mImageBytes, 0, mImageBytes.length);
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap aBitmap) {
+ super.onPostExecute(aBitmap);
+
+ if (isCancelled()) {
+ return;
+ }
+
+ if (aBitmap == null) {
+ return;
+ }
+
+ if (mImageViewReference == null) {
+ return;
+ }
+
+ if (getImageView() == null) {
+ return;
+ }
+
+ getImageView().setImageBitmap(aBitmap);
+ }
+
+ private ImageView getImageView() {
+ return mImageViewReference.get();
+ }
+ }
+
+ private static class AsyncDrawable extends BitmapDrawable {
+ private final WeakReference<ImageLoadingTask> mImageLoadingTaskReference;
+
+ public AsyncDrawable(Resources aResources, Bitmap aBitmap, ImageLoadingTask aImageLoadingTask) {
+ super(aResources, aBitmap);
+
+ mImageLoadingTaskReference = new WeakReference<ImageLoadingTask>(aImageLoadingTask);
+ }
+
+ public ImageLoadingTask getImageLoadingTask() {
+ return mImageLoadingTaskReference.get();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit ff5c113531ce9819927ecacbbb5853393eff501d
Author: Artur Dryomov <artur.dryomov at gmail.com>
Date: Fri Jul 26 02:47:40 2013 +0300
Add auto-hiding tabs when Bluetooth is not available.
Introduce a helper class for Bluetooth as well.
Change-Id: I89b0b4c42ef56ce3f5c2be3a1ea9d443aec04fce
diff --git a/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java b/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
index 3a5bbb6..3fa6173 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
@@ -10,6 +10,7 @@ package org.libreoffice.impressremote.activity;
import android.content.Intent;
import android.os.Bundle;
+import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
@@ -19,6 +20,9 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import org.libreoffice.impressremote.adapter.ComputersPagerAdapter;
+import org.libreoffice.impressremote.fragment.ComputersFragment;
+import org.libreoffice.impressremote.util.BluetoothOperator;
+import org.libreoffice.impressremote.util.FragmentOperator;
import org.libreoffice.impressremote.util.Intents;
import org.libreoffice.impressremote.R;
@@ -26,6 +30,20 @@ public class ComputersActivity extends SherlockFragmentActivity implements Actio
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ setUpContent();
+ }
+
+ private void setUpContent() {
+ if (BluetoothOperator.isAvailable()) {
+ setUpComputersLists();
+ }
+ else {
+ setUpComputersList();
+ }
+ }
+
+ private void setUpComputersLists() {
setContentView(R.layout.activity_computers);
setUpTabs();
@@ -35,12 +53,8 @@ public class ComputersActivity extends SherlockFragmentActivity implements Actio
private void setUpTabs() {
ActionBar aActionBar = getSupportActionBar();
- aActionBar.addTab(buildBluetoothServersTab());
- aActionBar.addTab(buildWiFiServersTab());
- }
-
- private ActionBar.Tab buildBluetoothServersTab() {
- return buildActionBarTab(R.string.title_bluetooth);
+ aActionBar.addTab(buildActionBarTab(R.string.title_bluetooth));
+ aActionBar.addTab(buildActionBarTab(R.string.title_wifi));
}
private ActionBar.Tab buildActionBarTab(int aTitleResourceId) {
@@ -69,13 +83,11 @@ public class ComputersActivity extends SherlockFragmentActivity implements Actio
public void onTabReselected(ActionBar.Tab aTab, FragmentTransaction aTransaction) {
}
- private ActionBar.Tab buildWiFiServersTab() {
- return buildActionBarTab(R.string.title_wifi);
- }
-
private void setUpComputersPager() {
- getComputersPager().setAdapter(buildComputersPagerAdapter());
- getComputersPager().setOnPageChangeListener(this);
+ ViewPager aComputersPager = getComputersPager();
+
+ aComputersPager.setAdapter(buildComputersPagerAdapter());
+ aComputersPager.setOnPageChangeListener(this);
}
private PagerAdapter buildComputersPagerAdapter() {
@@ -95,6 +107,12 @@ public class ComputersActivity extends SherlockFragmentActivity implements Actio
public void onPageScrollStateChanged(int aPosition) {
}
+ private void setUpComputersList() {
+ Fragment aComputersFragment = ComputersFragment.newInstance(ComputersFragment.Type.WIFI);
+
+ FragmentOperator.setUpFragment(this, aComputersFragment);
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu aMenu) {
getSupportMenuInflater().inflate(R.menu.menu_action_bar_computers, aMenu);
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothServersFinder.java b/android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothServersFinder.java
index 60cf3df..a236ac5 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothServersFinder.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothServersFinder.java
@@ -22,6 +22,7 @@ import android.content.IntentFilter;
import android.os.Handler;
import android.support.v4.content.LocalBroadcastManager;
+import org.libreoffice.impressremote.util.BluetoothOperator;
import org.libreoffice.impressremote.util.Intents;
import org.libreoffice.impressremote.communication.Server.Protocol;
@@ -40,28 +41,23 @@ class BluetoothServersFinder extends BroadcastReceiver implements ServersFinder,
@Override
public void startSearch() {
- if (!isBluetoothAvailable()) {
+ if (!BluetoothOperator.isAvailable()) {
return;
}
- if (BluetoothAdapter.getDefaultAdapter().isDiscovering()) {
+ if (BluetoothOperator.getAdapter().isDiscovering()) {
return;
}
setUpSearchResultsReceiver();
- BluetoothAdapter.getDefaultAdapter().startDiscovery();
- }
-
- private boolean isBluetoothAvailable() {
- return BluetoothAdapter.getDefaultAdapter() != null;
+ BluetoothOperator.getAdapter().startDiscovery();
}
private void setUpSearchResultsReceiver() {
- IntentFilter aSearchResultsFilter = new IntentFilter(
- BluetoothDevice.ACTION_FOUND);
- aSearchResultsFilter
- .addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
+ IntentFilter aSearchResultsFilter = new IntentFilter();
+ aSearchResultsFilter.addAction(BluetoothDevice.ACTION_FOUND);
+ aSearchResultsFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
mContext.registerReceiver(this, aSearchResultsFilter);
}
@@ -73,15 +69,12 @@ class BluetoothServersFinder extends BroadcastReceiver implements ServersFinder,
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
addServer(buildServer(aBluetoothDevice));
-
callUpdatingServersList();
return;
}
- if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
- .equals(aIntent.getAction())) {
-
+ if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(aIntent.getAction())) {
startDiscoveryDelayed();
}
}
@@ -107,7 +100,7 @@ class BluetoothServersFinder extends BroadcastReceiver implements ServersFinder,
// but check whether device is on in case the user manually
// disabled bluetooth
- if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
+ if (!BluetoothOperator.getAdapter().isEnabled()) {
return;
}
@@ -117,18 +110,18 @@ class BluetoothServersFinder extends BroadcastReceiver implements ServersFinder,
@Override
public void run() {
- BluetoothAdapter.getDefaultAdapter().startDiscovery();
+ BluetoothOperator.getAdapter().startDiscovery();
}
@Override
public void stopSearch() {
- if (!isBluetoothAvailable()) {
+ if (!BluetoothOperator.isAvailable()) {
return;
}
tearDownSearchResultsReceiver();
- BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
+ BluetoothOperator.getAdapter().cancelDiscovery();
}
private void tearDownSearchResultsReceiver() {
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/Server.java b/android/sdremote/src/org/libreoffice/impressremote/communication/Server.java
index bc11d92..4e94b6c 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/Server.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/Server.java
@@ -32,6 +32,10 @@ public class Server implements Parcelable {
return new Server(Protocol.TCP, aAddress, aName);
}
+ public static Server newBluetoothInstance(String aAddress, String aName) {
+ return new Server(Protocol.BLUETOOTH, aAddress, aName);
+ }
+
public Protocol getProtocol() {
return mProtocol;
}
diff --git a/android/sdremote/src/org/libreoffice/impressremote/util/BluetoothOperator.java b/android/sdremote/src/org/libreoffice/impressremote/util/BluetoothOperator.java
new file mode 100644
index 0000000..5a1167e
--- /dev/null
+++ b/android/sdremote/src/org/libreoffice/impressremote/util/BluetoothOperator.java
@@ -0,0 +1,26 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+package org.libreoffice.impressremote.util;
+
+import android.bluetooth.BluetoothAdapter;
+
+public final class BluetoothOperator {
+ private BluetoothOperator() {
+ }
+
+ public static boolean isAvailable() {
+ return BluetoothAdapter.getDefaultAdapter() != null;
+ }
+
+ public static BluetoothAdapter getAdapter() {
+ return BluetoothAdapter.getDefaultAdapter();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/sdremote/src/org/libreoffice/impressremote/util/FragmentOperator.java b/android/sdremote/src/org/libreoffice/impressremote/util/FragmentOperator.java
new file mode 100644
index 0000000..3c65063
--- /dev/null
+++ b/android/sdremote/src/org/libreoffice/impressremote/util/FragmentOperator.java
@@ -0,0 +1,44 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+package org.libreoffice.impressremote.util;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+
+public final class FragmentOperator {
+ private FragmentOperator() {
+ }
+
+ public static void setUpFragment(FragmentActivity aActivity, Fragment aFragment) {
+ if (isFragmentSetUp(aActivity)) {
+ return;
+ }
+
+ installFragment(aActivity, aFragment);
+ }
+
+ private static boolean isFragmentSetUp(FragmentActivity aActivity) {
+ FragmentManager aFragmentManager = aActivity.getSupportFragmentManager();
+
+ return aFragmentManager.findFragmentById(android.R.id.content) != null;
+ }
+
+ private static void installFragment(FragmentActivity aActivity, Fragment aFragment) {
+ FragmentManager aFragmentManager = aActivity.getSupportFragmentManager();
+ FragmentTransaction aFragmentTransaction = aFragmentManager.beginTransaction();
+
+ aFragmentTransaction.add(android.R.id.content, aFragment);
+
+ aFragmentTransaction.commit();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list