Kaydet (Commit) 6b873439 authored tarafından Ximeng Zu's avatar Ximeng Zu Kaydeden (comit) Tomaž Vajngerl

Presentation Mode

Adding fullscreen presentation mode.

Change-Id: Id07416ce204d1d7dd917fbd33a4d9f5072ac1703
Reviewed-on: https://gerrit.libreoffice.org/38006Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarTomaž Vajngerl <quikee@gmail.com>
Tested-by: 's avatarTomaž Vajngerl <quikee@gmail.com>
üst ff10bc47
......@@ -125,6 +125,13 @@
android:windowSoftInputMode="stateHidden">
</activity>
<activity android:name=".PresentationActivity"
android:screenOrientation="landscape" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".LibreOfficeMainActivity" />
</activity>
</application>
</manifest>
......
<?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">
<WebView
android:id="@+id/presentation_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:id="@+id/presentation_gesture_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<ImageButton
android:id="@+id/slide_show_nav_prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic_search_direction_up" />
<ImageButton
android:id="@+id/slide_show_nav_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:src="@drawable/ic_search_direction_down" />
<Button
android:id="@+id/slide_show_nav_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:text="@string/slideshow_action_back" />
</RelativeLayout>
</RelativeLayout>
\ No newline at end of file
......@@ -42,6 +42,11 @@
android:orderInCategory="100" />
</group>
<item android:id="@+id/action_presentation"
android:title="@string/action_presentation"
android:orderInCategory="100"
android:enabled="false" />
<item android:id="@+id/action_parts"
android:title="@string/action_parts"
android:orderInCategory="100" />
......
......@@ -130,5 +130,9 @@
<!-- Create New Document Dialog Strings -->
<string name="create_new_document_title">Enter file name</string>
<string name="action_create">CREATE</string>
<string name="action_presentation">Slide show</string>
<string name="alert_copy_svg_slide_show_to_clipboard">Your Android device doesn\'t support in-app svg slideshow. We copied the slideshow link to clipboard. Please press home button, open a modern web browser, paste in the address bar, and go.</string>
<string name="alert_copy_svg_slide_show_to_clipboard_dismiss">OK</string>
<string name="slideshow_action_back">Back</string>
</resources>
......@@ -101,6 +101,10 @@ class LOKitTileProvider implements TileProvider {
Log.i(LOGTAG, "Document parts: " + parts);
mContext.getDocumentPartView().clear();
if (mDocument.getDocumentType() == Document.DOCTYPE_PRESENTATION) {
mContext.getToolbarController().disableMenuItem(R.id.action_presentation, false);
}
// Writer documents always have one part, so hide the navigation drawer.
if (mDocument.getDocumentType() != Document.DOCTYPE_TEXT) {
for (int i = 0; i < parts; i++) {
......@@ -134,26 +138,44 @@ class LOKitTileProvider implements TileProvider {
@Override
public void saveDocumentAs(String filePath, String format) {
String newFilePath = "file://" + filePath;
final String newFilePath = "file://" + filePath;
Log.d("saveFilePathURL", newFilePath);
LOKitShell.showProgressSpinner(mContext);
mDocument.saveAs(newFilePath, format, "");
if (!mOffice.getError().isEmpty()){
Log.e("Save Error", mOffice.getError());
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
// There was some error
mContext.showSaveStatusMessage(true);
}
});
}
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
// There was no error
mContext.showSaveStatusMessage(false);
if (format.equals("svg")) {
// error in creating temp slideshow svg file
Log.d(LOGTAG, "Error in creating temp slideshow svg file");
} else {
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
// There was some error
mContext.showSaveStatusMessage(true);
}
});
}
});
} else {
if (format.equals("svg")) {
// successfully created temp slideshow svg file
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
mContext.startPresentation(newFilePath);
}
});
} else {
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
// There was no error
mContext.showSaveStatusMessage(false);
}
});
}
}
LOKitShell.hideProgressSpinner(mContext);
}
private void setupDocumentFonts() {
......
......@@ -2,6 +2,8 @@ package org.libreoffice;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
......@@ -10,12 +12,14 @@ import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.graphics.RectF;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.design.widget.Snackbar;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
......@@ -79,6 +83,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
private File mInputFile;
private DocumentOverlay mDocumentOverlay;
private File mTempFile = null;
private File mTempSlideShowFile = null;
private String newDocumentType = null;
BottomSheetBehavior bottomToolbarSheetBehavior;
......@@ -407,6 +412,10 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
// noinspection ResultOfMethodCallIgnored
mTempFile.delete();
}
if (mTempSlideShowFile.exists()) {
// noinspection ResultOfMethodCallIgnored
mTempSlideShowFile.delete();
}
}
}
@Override
......@@ -749,6 +758,36 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
Snackbar.make(mDrawerLayout, getString(R.string.create_new_file_success) + mInputFile.getName(), Snackbar.LENGTH_LONG).show();
else
Snackbar.make(mDrawerLayout, getString(R.string.create_new_file_error) + mInputFile.getName(), Snackbar.LENGTH_LONG).show(); }
public void preparePresentation() {
if (getExternalCacheDir() != null) {
String tempPath = getExternalCacheDir().getPath() + "/" + mInputFile.getName() + ".svg";
mTempSlideShowFile = new File(tempPath);
if (mTempSlideShowFile.exists() && !isDocumentChanged) {
startPresentation("file://" + tempPath);
} else {
LOKitShell.sendSaveAsEvent(tempPath, "svg");
}
}
}
public void startPresentation(String tempPath) {
// pre-KitKat android doesn't have chrome-based WebView, which is needed to show svg slideshow
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Intent intent = new Intent(this, PresentationActivity.class);
intent.setData(Uri.parse(tempPath));
startActivity(intent);
} else {
// copy the svg file path to clipboard for the user to paste in a browser
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("temp svg file path", tempPath);
clipboard.setPrimaryClip(clip);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.alert_copy_svg_slide_show_to_clipboard)
.setPositiveButton(R.string.alert_copy_svg_slide_show_to_clipboard_dismiss, null).show();
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
package org.libreoffice;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageButton;
public class PresentationActivity extends AppCompatActivity {
private static final String LOGTAG = PresentationActivity.class.getSimpleName();
WebView mWebView;
View mGestureView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// First we hide the status bar
if (Build.VERSION.SDK_INT < 16) {
// If the Android version is lower than Jellybean, use this call to hide
// the status bar.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
// If higher than Jellybean
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
}
setContentView(R.layout.presentation_mode);
// get intent and url
Intent intent = getIntent();
String filePath = intent.getDataString();
// set up WebView
mWebView = (WebView) findViewById(R.id.presentation_view);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
// set up buttons within presentation_gesture_view
ImageButton prevButton = (ImageButton) findViewById(R.id.slide_show_nav_prev);
ImageButton nextButton = (ImageButton) findViewById(R.id.slide_show_nav_next);
Button backButton = (Button) findViewById(R.id.slide_show_nav_back);
prevButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pageLeft();
}
});
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pageRight();
}
});
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
// set up presentation_gesture_view
mGestureView = findViewById(R.id.presentation_gesture_view);
final GestureDetectorCompat gestureDetector =
new GestureDetectorCompat(this, new presentationGestureViewListener());
mGestureView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
// load url
mWebView.loadUrl(filePath);
}
private class presentationGestureViewListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
private static final int SCROLL_THRESHOLD = 10; // if scrollCounter is larger than this, a page switch is triggered
private int scrollCounter = 0; // a counter for measuring scrolling distance
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
pageRight();
} else {
pageLeft();
}
result = true;
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) < Math.abs(diffY)) {
if (distanceY > 0) {
scrollCounter++;
if (scrollCounter >= SCROLL_THRESHOLD) {
pageRight();
scrollCounter = 0;
}
} else {
scrollCounter--;
if (scrollCounter <= -SCROLL_THRESHOLD) {
pageLeft();
scrollCounter = 0;
}
}
result = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (e.getX() < mGestureView.getWidth()/3) {
pageLeft();
} else if (e.getX() < mGestureView.getWidth()*2/3) {
hideControlButtons();
} else {
pageRight();
}
return true;
}
}
private void hideControlButtons() {
View[] views= {findViewById(R.id.slide_show_nav_prev),findViewById(R.id.slide_show_nav_next),findViewById(R.id.slide_show_nav_back)} ;
for (View view : views) {
if (view.getVisibility() == View.GONE) {
view.setVisibility(View.VISIBLE);
} else if (view.getVisibility() == View.VISIBLE) {
view.setVisibility(View.GONE);
}
}
}
private void pageLeft() {
mWebView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT));
}
private void pageRight() {
mWebView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT));
}
}
\ No newline at end of file
......@@ -132,6 +132,9 @@ public class ToolbarController implements Toolbar.OnMenuItemClickListener {
case R.id.action_redo:
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Redo"));
return true;
case R.id.action_presentation:
mContext.preparePresentation();
return true;
}
return false;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment