summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorbrainbreaker <gautamprajapati06@gmail.com>2017-03-14 19:12:20 +0530
committerTomaž Vajngerl <quikee@gmail.com>2017-03-30 19:59:10 +0000
commit1503769fe15c122ff2bb8f6f7e7b4ab72656ddc2 (patch)
treec839a253bebc30893e94887d80d48f7c0182a38f /android
parent0466d0c815f8b0f60497faec8b60a18d35a61eca (diff)
tdf#106325 - No way to create a new Document
This commit will add the ability to create a new document. A FAB is used in home screen which on expansion gives four options namely new writer document, new impress, new Sheet or new Draw. Two new events loadNewDocument and saveDocumentAs have been added. Another major change includes the use of constraint layout in LOUIActivity layout as it decreases nesting of views and improves the app performance. This was needed because of the new FAB layouts being added. Support for vector drawables has been enabled. Change-Id: Ia3ea17f73c0d8514f8ddb7b9a1cbd2ce7de6ac08 Reviewed-on: https://gerrit.libreoffice.org/35183 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'android')
-rw-r--r--android/Bootstrap/src/org/libreoffice/kit/Document.java2
-rw-r--r--android/source/build.gradle2
-rw-r--r--android/source/res/anim/fab_close.xml18
-rw-r--r--android/source/res/anim/fab_open.xml19
-rw-r--r--android/source/res/drawable/ic_add_black_24dp.xml9
-rw-r--r--android/source/res/layout/activity_document_browser.xml213
-rw-r--r--android/source/res/values/strings.xml9
-rw-r--r--android/source/src/java/org/libreoffice/LOEvent.java17
-rw-r--r--android/source/src/java/org/libreoffice/LOKitShell.java12
-rw-r--r--android/source/src/java/org/libreoffice/LOKitThread.java58
-rw-r--r--android/source/src/java/org/libreoffice/LOKitTileProvider.java24
-rwxr-xr-xandroid/source/src/java/org/libreoffice/LibreOfficeMainActivity.java132
-rw-r--r--android/source/src/java/org/libreoffice/TileProvider.java6
-rw-r--r--android/source/src/java/org/libreoffice/ToolbarController.java6
-rw-r--r--android/source/src/java/org/libreoffice/ui/FileUtilities.java2
-rw-r--r--android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java123
16 files changed, 585 insertions, 67 deletions
diff --git a/android/Bootstrap/src/org/libreoffice/kit/Document.java b/android/Bootstrap/src/org/libreoffice/kit/Document.java
index a7d3f04938bb..7cf99413644c 100644
--- a/android/Bootstrap/src/org/libreoffice/kit/Document.java
+++ b/android/Bootstrap/src/org/libreoffice/kit/Document.java
@@ -147,7 +147,7 @@ public class Document {
public native void setClientZoom(int nTilePixelWidth, int nTilePixelHeight, int nTileTwipWidth, int nTileTwipHeight);
- private native void saveAs(String url, String format, String options);
+ public native void saveAs(String url, String format, String options);
private native void paintTileNative(ByteBuffer buffer, int canvasWidth, int canvasHeight, int tilePositionX, int tilePositionY, int tileWidth, int tileHeight);
diff --git a/android/source/build.gradle b/android/source/build.gradle
index d5fc5c932be0..302d34a54754 100644
--- a/android/source/build.gradle
+++ b/android/source/build.gradle
@@ -26,6 +26,7 @@ dependencies {
compile files("${liboWorkdir}/UnpackedTarball/owncloud_android_lib/bin/owncloud-android-library.jar")
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:design:25.1.0'
+ compile 'com.android.support.constraint:constraint-layout:1.0.2'
}
android {
@@ -64,6 +65,7 @@ android {
// ToDo: fix openssl stuff to not block targeting 23 or later
targetSdkVersion 22
manifestPlaceholders = [installLocation: "preferExternal"]
+ vectorDrawables.useSupportLibrary = true
}
buildTypes {
debug {
diff --git a/android/source/res/anim/fab_close.xml b/android/source/res/anim/fab_close.xml
new file mode 100644
index 000000000000..ba13b0f038be
--- /dev/null
+++ b/android/source/res/anim/fab_close.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fillAfter="true">
+ <scale
+ android:duration="300"
+ android:fromXScale="0.8"
+ android:fromYScale="0.8"
+ android:interpolator="@android:anim/linear_interpolator"
+ android:toXScale="0.0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:toYScale="0.0" />
+
+ <alpha android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:duration="300"/>
+</set>
diff --git a/android/source/res/anim/fab_open.xml b/android/source/res/anim/fab_open.xml
new file mode 100644
index 000000000000..9099d8b53c80
--- /dev/null
+++ b/android/source/res/anim/fab_open.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fillAfter="true">
+ <scale
+ android:duration="300"
+ android:fromXScale="0.0"
+ android:fromYScale="0.0"
+ android:interpolator="@android:anim/linear_interpolator"
+ android:toXScale="0.8"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:toYScale="0.8"/>
+
+ <alpha
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:duration="300"/>
+</set>
diff --git a/android/source/res/drawable/ic_add_black_24dp.xml b/android/source/res/drawable/ic_add_black_24dp.xml
new file mode 100644
index 000000000000..0258249cc482
--- /dev/null
+++ b/android/source/res/drawable/ic_add_black_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+</vector>
diff --git a/android/source/res/layout/activity_document_browser.xml b/android/source/res/layout/activity_document_browser.xml
index 20ca14125003..fab1b095035e 100644
--- a/android/source/res/layout/activity_document_browser.xml
+++ b/android/source/res/layout/activity_document_browser.xml
@@ -6,32 +6,45 @@
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/.
-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical" >
+ android:orientation="vertical">
<!-- The toolbar -->
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
android:elevation="3dp"
android:background="@color/toolbar_background"
app:theme="@style/LibreOfficeTheme.Toolbar"
tools:theme="@style/LibreOfficeTheme.Toolbar"
- app:popupTheme="@style/LibreOfficeTheme">
+ app:popupTheme="@style/LibreOfficeTheme"
+ tools:layout_constraintTop_creator="1"
+ tools:layout_constraintRight_creator="1"
+ app:layout_constraintRight_toRightOf="parent"
+ tools:layout_constraintLeft_creator="1"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ tools:layout_constraintTop_creator="1"
+ tools:layout_constraintRight_creator="1"
+ tools:layout_constraintBottom_creator="1"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/toolbar"
+ tools:layout_constraintLeft_creator="1"
+ app:layout_constraintLeft_toLeftOf="parent">
<!-- The content -->
<ScrollView
@@ -53,7 +66,7 @@
android:gravity="center_vertical"
android:textSize="14sp"
android:padding="16dp"
- android:textStyle="bold"/>
+ android:textStyle="bold" />
<!--Recent files-->
<android.support.v7.widget.RecyclerView
@@ -61,7 +74,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp"/>
+ android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
@@ -82,19 +95,177 @@
android:background="@color/background_normal"
android:orientation="vertical" />
- </LinearLayout>
+ </LinearLayout>
- </ScrollView>
+ </ScrollView>
- <!-- The navigation drawer -->
- <android.support.design.widget.NavigationView
- android:id="@+id/navigation_drawer"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="start"
- android:background="@color/background_normal"
- app:menu="@menu/navigation_menu"
- android:theme="@style/LibreOfficeTheme.NavigationView" />
+ <!-- The navigation drawer -->
+ <android.support.design.widget.NavigationView
+ android:id="@+id/navigation_drawer"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:background="@color/background_normal"
+ app:menu="@menu/navigation_menu"
+ android:theme="@style/LibreOfficeTheme.NavigationView" />
</android.support.v4.widget.DrawerLayout>
-</LinearLayout>
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/editFAB"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginRight="16dp"
+ android:clickable="true"
+ app:fabSize="normal"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:backgroundTint="@color/background_normal"
+ app:srcCompat="@drawable/ic_add_black_24dp" />
+
+ <LinearLayout
+ android:id="@+id/writerLayout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:visibility="invisible"
+ app:layout_constraintBottom_toTopOf="@+id/editFAB"
+ app:layout_constraintRight_toRightOf="parent">
+
+ <TextView
+ android:id="@+id/newWriterTextView"
+ android:layout_width="120dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginRight="8dp"
+ android:elevation="2dp"
+ android:gravity="center_horizontal"
+ android:text="@string/new_write"
+ android:textSize="18sp"
+ android:textStyle="bold"
+ android:background="@color/background_normal"
+ android:typeface="normal" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/newWriterFAB"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ app:fabSize="normal"
+ app:backgroundTint="@color/background_normal"
+ app:srcCompat="@drawable/writer" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/impressLayout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:visibility="invisible"
+ app:layout_constraintBottom_toTopOf="@+id/writerLayout"
+ app:layout_constraintLeft_toLeftOf="@+id/writerLayout"
+ app:layout_constraintRight_toRightOf="parent">
+
+ <TextView
+ android:id="@+id/newImpressTextView"
+ android:layout_width="120dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginRight="8dp"
+ android:elevation="2dp"
+ android:gravity="center_horizontal"
+ android:text="@string/new_impress"
+ android:textSize="18sp"
+ android:textStyle="bold"
+ android:background="@color/background_normal"
+ android:typeface="normal" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/newImpressFAB"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ app:fabSize="normal"
+ app:backgroundTint="@color/background_normal"
+ app:srcCompat="@drawable/impress" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/calcLayout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:visibility="invisible"
+ app:layout_constraintBottom_toTopOf="@+id/impressLayout"
+ app:layout_constraintLeft_toLeftOf="@+id/impressLayout"
+ app:layout_constraintRight_toRightOf="parent">
+
+ <TextView
+ android:id="@+id/newCalcTextView"
+ android:layout_width="120dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginRight="8dp"
+ android:elevation="2dp"
+ android:gravity="center_horizontal"
+ android:text="@string/new_spreadsheet"
+ android:background="@color/background_normal"
+ android:textSize="18sp"
+ android:textStyle="bold"
+ android:typeface="normal" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/newCalcFAB"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ app:fabSize="normal"
+ app:backgroundTint="@color/background_normal"
+ app:srcCompat="@drawable/calc" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/drawLayout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:visibility="invisible"
+ app:layout_constraintBottom_toTopOf="@+id/calcLayout"
+ app:layout_constraintLeft_toLeftOf="@+id/calcLayout"
+ app:layout_constraintRight_toRightOf="parent">
+
+ <TextView
+ android:id="@+id/newDrawTextView"
+ android:layout_width="120dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginRight="8dp"
+ android:elevation="2dp"
+ android:gravity="center_horizontal"
+ android:text="@string/new_draw"
+ android:background="@color/background_normal"
+ android:textSize="18sp"
+ android:textStyle="bold"
+ android:typeface="normal" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/newDrawFAB"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ app:fabSize="normal"
+ app:backgroundTint="@color/background_normal"
+ app:srcCompat="@drawable/draw" />
+
+ </LinearLayout>
+
+</android.support.constraint.ConstraintLayout>
diff --git a/android/source/res/values/strings.xml b/android/source/res/values/strings.xml
index 9832d8b72eb2..ce3754ee3d15 100644
--- a/android/source/res/values/strings.xml
+++ b/android/source/res/values/strings.xml
@@ -16,6 +16,10 @@
<string name="about_moreinfo">More Info</string>
<string name="back_again_to_quit">Press back again to quit</string>
+ <string name="new_impress">New Impress</string>
+ <string name="new_spreadsheet">New Sheet</string>
+ <string name="new_draw">New Draw</string>
+
<string name="browser_app_name">LibreOffice Browser</string>
<string name="menu_search">Search</string>
<string name="list_view">List</string>
@@ -89,6 +93,7 @@
<string name="message_saved">Save complete</string>
<string name="message_saving">Saving the document…</string>
<string name="message_save_incomplete">Save incomplete. Were there any changes?</string>
+ <string name="new_file_created">File created in Documents folder</string>
<!-- Document provider settings -->
<string name="storage_provider_settings">Storage provider settings</string>
@@ -117,6 +122,10 @@
<string name="save_document">SAVE</string>
<string name="cancel_save_document">CANCEL</string>
<string name="no_save_document">NO</string>
+ <string name="new_write">New Write</string>
+
+ <string name="save_as_success">Saved file -</string>
+ <string name="save_as_error">Unable to create new file, please check entered file name.</string>
</resources>
diff --git a/android/source/src/java/org/libreoffice/LOEvent.java b/android/source/src/java/org/libreoffice/LOEvent.java
index 23109e8d7f6a..3e058c8c035e 100644
--- a/android/source/src/java/org/libreoffice/LOEvent.java
+++ b/android/source/src/java/org/libreoffice/LOEvent.java
@@ -34,6 +34,8 @@ public class LOEvent implements Comparable<LOEvent> {
public static final int NAVIGATION_CLICK = 13;
public static final int UNO_COMMAND = 14;
public static final int RESUME = 15;
+ public static final int LOAD_NEW = 16;
+ public static final int SAVE_AS = 17;
public final int mType;
public int mPriority = 0;
@@ -42,6 +44,8 @@ public class LOEvent implements Comparable<LOEvent> {
public ThumbnailCreator.ThumbnailCreationTask mTask;
public int mPartIndex;
public String mString;
+ public String filePath;
+ public String fileType;
public ComposedTileLayer mComposedTileLayer;
public String mTouchType;
public PointF mDocumentCoordinate;
@@ -81,6 +85,19 @@ public class LOEvent implements Comparable<LOEvent> {
mPartIndex = value;
}
+ public LOEvent(String filePath, int type) {
+ mType = type;
+ mTypeString = "Load";
+ this.filePath = filePath;
+ }
+
+ public LOEvent(String filePath, String fileType, int type) {
+ mType = type;
+ mTypeString = "Load New/Save As";
+ this.filePath = filePath;
+ this.fileType = fileType;
+ }
+
public LOEvent(int type, int partIndex) {
mType = type;
mPartIndex = partIndex;
diff --git a/android/source/src/java/org/libreoffice/LOKitShell.java b/android/source/src/java/org/libreoffice/LOKitShell.java
index 35a8fd009dc2..7b7525722250 100644
--- a/android/source/src/java/org/libreoffice/LOKitShell.java
+++ b/android/source/src/java/org/libreoffice/LOKitShell.java
@@ -106,8 +106,16 @@ public class LOKitShell {
LOKitShell.sendEvent(new LOEvent(LOEvent.CHANGE_PART, part));
}
- public static void sendLoadEvent(String inputFile) {
- LOKitShell.sendEvent(new LOEvent(LOEvent.LOAD, inputFile));
+ public static void sendLoadEvent(String inputFilePath) {
+ LOKitShell.sendEvent(new LOEvent(inputFilePath, LOEvent.LOAD));
+ }
+
+ public static void sendNewDocumentLoadEvent(String newDocumentPath, String newDocumentType) {
+ LOKitShell.sendEvent(new LOEvent(newDocumentPath, newDocumentType, LOEvent.LOAD_NEW));
+ }
+
+ public static void sendSaveAsEvent(String filePath, String fileFormat) {
+ LOKitShell.sendEvent(new LOEvent(filePath, fileFormat, LOEvent.SAVE_AS));
}
public static void sendResumeEvent(String inputFile, int partIndex) {
diff --git a/android/source/src/java/org/libreoffice/LOKitThread.java b/android/source/src/java/org/libreoffice/LOKitThread.java
index 742b1cb6e34c..31d3b96440ed 100644
--- a/android/source/src/java/org/libreoffice/LOKitThread.java
+++ b/android/source/src/java/org/libreoffice/LOKitThread.java
@@ -3,9 +3,11 @@ package org.libreoffice;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
+import android.util.Log;
import android.view.KeyEvent;
import org.libreoffice.canvas.SelectionHandle;
+import org.libreoffice.ui.LibreOfficeUIActivity;
import org.mozilla.gecko.gfx.CairoImage;
import org.mozilla.gecko.gfx.ComposedTileLayer;
import org.mozilla.gecko.gfx.GeckoLayerClient;
@@ -171,8 +173,6 @@ class LOKitThread extends Thread {
} else {
closeDocument();
}
-
-
}
/**
@@ -189,25 +189,65 @@ class LOKitThread extends Thread {
/**
* Handle load document event.
- * @param filename - filename where the document is located
+ * @param filePath - filePath to where the document is located
*/
- private void loadDocument(String filename) {
+ private void loadDocument(String filePath) {
+ mLayerClient = mContext.getLayerClient();
+ mInvalidationHandler = new InvalidationHandler(mContext);
+ mTileProvider = TileProviderFactory.create(mContext, mInvalidationHandler, filePath);
+
+ if (mTileProvider.isReady()) {
+ LOKitShell.showProgressSpinner(mContext);
+ refresh();
+ LOKitShell.hideProgressSpinner(mContext);
+ } else {
+ closeDocument();
+ }
+ }
+
+ /**
+ * Handle load new document event.
+ * @param filePath - filePath to where new document is to be created
+ * @param fileType - fileType what type of new document is to be loaded
+ */
+ private void loadNewDocument(String filePath, String fileType) {
mLayerClient = mContext.getLayerClient();
mInvalidationHandler = new InvalidationHandler(mContext);
- mTileProvider = TileProviderFactory.create(mContext, mInvalidationHandler, filename);
+ mTileProvider = TileProviderFactory.create(mContext, mInvalidationHandler, fileType);
if (mTileProvider.isReady()) {
LOKitShell.showProgressSpinner(mContext);
refresh();
LOKitShell.hideProgressSpinner(mContext);
+
+ if (fileType.matches(LibreOfficeUIActivity.NEW_WRITER_STRING_KEY))
+ mTileProvider.saveDocumentAs(filePath, "odt");
+ else if (fileType.matches(LibreOfficeUIActivity.NEW_CALC_STRING_KEY))
+ mTileProvider.saveDocumentAs(filePath, "ods");
+ else if (fileType.matches(LibreOfficeUIActivity.NEW_IMPRESS_STRING_KEY))
+ mTileProvider.saveDocumentAs(filePath, "odp");
+ else
+ mTileProvider.saveDocumentAs(filePath, "odg");
+
} else {
closeDocument();
}
}
/**
+ * Save the currently loaded document.
+ */
+ private void saveDocumentAs(String filePath, String fileType) {
+ if (mTileProvider == null) {
+ Log.e(LOGTAG, "Error in saving, Tile Provider instance is null");
+ } else {
+ mTileProvider.saveDocumentAs(filePath, fileType);
+ }
+ }
+
+ /**
* Close the currently loaded document.
*/
private void closeDocument() {
@@ -223,7 +263,13 @@ class LOKitThread extends Thread {
private void processEvent(LOEvent event) {
switch (event.mType) {
case LOEvent.LOAD:
- loadDocument(event.mString);
+ loadDocument(event.filePath);
+ break;
+ case LOEvent.LOAD_NEW:
+ loadNewDocument(event.filePath, event.fileType);
+ break;
+ case LOEvent.SAVE_AS:
+ saveDocumentAs(event.filePath, event.fileType);
break;
case LOEvent.RESUME:
resumeDocument(event.mString, event.mPartIndex);
diff --git a/android/source/src/java/org/libreoffice/LOKitTileProvider.java b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
index d0fbe9431de7..6ed73ee32805 100644
--- a/android/source/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
@@ -131,6 +131,30 @@ class LOKitTileProvider implements TileProvider {
});
}
+ @Override
+ public void saveDocumentAs(String filePath, String format) {
+ String newFilePath = "file://" + filePath;
+ Log.d("saveFilePathURL", newFilePath);
+ 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.showSaveStatusToast(true);
+ }
+ });
+ }
+ LOKitShell.getMainHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ // There was no error
+ mContext.showSaveStatusToast(false);
+ }
+ });
+ }
+
private void setupDocumentFonts() {
String values = mDocument.getCommandValues(".uno:CharFontName");
if (values == null || values.isEmpty())
diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 02129e50a7e8..fb41762af342 100755
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -10,8 +10,10 @@ 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.Bundle;
+import android.os.Environment;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v4.widget.DrawerLayout;
@@ -23,12 +25,13 @@ import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ListView;
-import android.widget.TabHost;
import android.widget.Toast;
import org.libreoffice.overlay.DocumentOverlay;
import org.libreoffice.storage.DocumentProviderFactory;
import org.libreoffice.storage.IFile;
+import org.libreoffice.ui.FileUtilities;
+import org.libreoffice.ui.LibreOfficeUIActivity;
import org.mozilla.gecko.ZoomConstraints;
import org.mozilla.gecko.gfx.GeckoLayerClient;
import org.mozilla.gecko.gfx.LayerView;
@@ -66,19 +69,23 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
private URI documentUri;
private DrawerLayout mDrawerLayout;
+ Toolbar toolbarTop;
private ListView mDrawerList;
private List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>();
private DocumentPartViewListAdapter mDocumentPartViewListAdapter;
private int partIndex=-1;
private File mInputFile;
+ private String newFileName = "untitled";
+ private String newFilePath = "/storage/emulated/0/Documents/";
private DocumentOverlay mDocumentOverlay;
private File mTempFile = null;
-
+ private String newDocumentType = null;
private FormattingController mFormattingController;
private ToolbarController mToolbarController;
private FontController mFontController;
private SearchController mSearchController;
+ private static final int PICKFOLDER_RESULT_CODE = 1;
public GeckoLayerClient getLayerClient() {
return mLayerClient;
@@ -96,7 +103,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
private boolean isFormattingToolbarOpen = false;
private boolean isSearchToolbarOpen = false;
private boolean isDocumentChanged = false;
-
+ public boolean isNewDocument = false;
@Override
public void onCreate(Bundle savedInstanceState) {
Log.w(LOGTAG, "onCreate..");
@@ -112,7 +119,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
}
setContentView(R.layout.activity_main);
- Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar);
+ toolbarTop = (Toolbar) findViewById(R.id.toolbar);
hideBottomToolbar();
mToolbarController = new ToolbarController(this, toolbarTop);
@@ -127,32 +134,48 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
mFontController = new FontController(this);
mSearchController = new SearchController(this);
+ // New document type string is not null, it means we want to open a new document
+ if (getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY) != null) {
+ newDocumentType = getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY);
+ if (newDocumentType.matches(LibreOfficeUIActivity.NEW_WRITER_STRING_KEY))
+ newFileName = newFileName + ".odt";
+ else if (newDocumentType.matches(LibreOfficeUIActivity.NEW_IMPRESS_STRING_KEY))
+ newFileName = newFileName + ".odp";
+ else if (newDocumentType.matches(LibreOfficeUIActivity.NEW_CALC_STRING_KEY))
+ newFileName = newFileName + ".ods";
+ else
+ newFileName = newFileName + ".odg";
+ // We want to create a new Document, create an alert dialogue to name the new file.
+ openSelectPathIntent();
+ isNewDocument = true;
+ }
+
if (getIntent().getData() != null) {
if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
if (copyFileToTemp() && mTempFile != null) {
mInputFile = mTempFile;
- Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath());
+ Log.e(LOGTAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath());
+ toolbarTop.setTitle(mInputFile.getName());
} else {
// TODO: can't open the file
Log.e(LOGTAG, "couldn't create temporary file from " + getIntent().getData());
}
} else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) {
mInputFile = new File(getIntent().getData().getPath());
- Log.d(LOGTAG, "SCHEME_FILE: getPath(): " + getIntent().getData().getPath());
-
+ Log.e(LOGTAG, "SCHEME_FILE: getPath(): " + getIntent().getData().getPath());
+ toolbarTop.setTitle(mInputFile.getName());
// Gather data to rebuild IFile object later
providerId = getIntent().getIntExtra(
"org.libreoffice.document_provider_id", 0);
documentUri = (URI) getIntent().getSerializableExtra(
"org.libreoffice.document_uri");
}
+ } else if (isNewDocument){
+ toolbarTop.setTitle(newFileName);
} else {
mInputFile = new File(DEFAULT_DOC_PATH);
}
- toolbarTop.setTitle(mInputFile.getName());
-
-
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
if (mDocumentPartViewListAdapter == null) {
@@ -187,24 +210,42 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
mDocumentOverlay = new DocumentOverlay(this, layerView);
mToolbarController.setupToolbars();
+ }
- TabHost host = (TabHost) findViewById(R.id.toolbarTabHost);
- host.setup();
-
- TabHost.TabSpec spec = host.newTabSpec("Character");
- spec.setContent(R.id.tab_character);
- spec.setIndicator("Character");
- host.addTab(spec);
-
- spec = host.newTabSpec("Paragraph");
- spec.setContent(R.id.tab_paragraph);
- spec.setIndicator("Paragraph");
- host.addTab(spec);
+ private void openSelectPathIntent() {
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT)
+ .addCategory(Intent.CATEGORY_OPENABLE)
+ .setType("*/*")
+ .putExtra(Intent.EXTRA_TITLE, newFileName);
+ startActivityForResult(intent, PICKFOLDER_RESULT_CODE);
+ }
- spec = host.newTabSpec("Insert");
- spec.setContent(R.id.tab_insert);
- spec.setIndicator("Insert");
- host.addTab(spec);
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch(requestCode){
+ case PICKFOLDER_RESULT_CODE:
+ if(resultCode==RESULT_OK){
+ Uri fileURI = data.getData();
+ newFilePath = fileURI.getPath();
+ if (newFilePath.contains("primary")) {
+ /* When file is being saved in primary storage folder other than Documents home.
+ * newFilePath content is similar to this - /document/primary:Downloads/untitled1.odt */
+ newFilePath = Environment.getExternalStorageDirectory().getPath() + "/" + newFilePath.split(":")[1];
+ } else if (newFilePath.contains("home")) {
+ /* When file is being saved in documents folder itself i.e. Document home.
+ * newFilePath content is similar to this - /document/home:untitled1.odt */
+ newFilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + "/" + newFilePath.split(":")[1];
+ } else {
+ newFilePath = Environment.getExternalStorageDirectory().getPath() + "/";
+ }
+ Log.d("newFilePath", newFilePath);
+ }
+ // Now set the input file variable to new file created
+ mInputFile = new File(newFilePath);
+ // and load the new document
+ LOKitShell.sendNewDocumentLoadEvent(newFilePath, newDocumentType);
+ break;
+ }
}
public RectF getCurrentCursorPosition() {
@@ -252,10 +293,21 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
}
/**
+ * Save a new document
+ * */
+ public void saveAs(){
+ LOKitShell.sendSaveAsEvent(mInputFile.getPath(), FileUtilities.getExtension(mInputFile.getPath()).substring(1));
+ }
+
+ /**
* Save the document and invoke save on document provider to upload the file
* to the cloud if necessary.
*/
public void saveDocument() {
+ if (!mInputFile.exists()) {
+ // Needed for handling null in case new document is not created.
+ mInputFile = new File(DEFAULT_DOC_PATH);
+ }
final long lastModified = mInputFile.lastModified();
final Activity activity = LibreOfficeMainActivity.this;
Toast.makeText(this, R.string.message_saving, Toast.LENGTH_SHORT).show();
@@ -341,10 +393,12 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
protected void onStart() {
Log.i(LOGTAG, "onStart..");
super.onStart();
- if(partIndex == -1)
- LOKitShell.sendLoadEvent(mInputFile.getPath());
- else
- LOKitShell.sendResumeEvent(mInputFile.getPath(), partIndex);
+ if (!isNewDocument){
+ if (partIndex == -1)
+ LOKitShell.sendLoadEvent(mInputFile.getPath());
+ else
+ LOKitShell.sendResumeEvent(mInputFile.getPath(), partIndex);
+ }
}
@Override
@@ -381,12 +435,14 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
- //SAVE
- saveDocument();
+ if (isNewDocument) {
+ saveAs();
+ } else {
+ saveDocument();
+ }
isDocumentChanged=false;
onBackPressed();
break;
-
case DialogInterface.BUTTON_NEGATIVE:
//CANCEL
break;
@@ -640,7 +696,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
}
private static boolean copyFromAssets(AssetManager assetManager,
- String fromAssetPath, String targetDir) {
+ String fromAssetPath, String targetDir) {
try {
String[] files = assetManager.list(fromAssetPath);
@@ -695,6 +751,14 @@ public class LibreOfficeMainActivity extends AppCompatActivity {
return false;
}
}
+
+ // This method is used in LOKitTileProvider.java to show status of new file creation.
+ public void showSaveStatusToast(boolean error) {
+ if (!error)
+ Toast.makeText(this, getString(R.string.save_as_success) + newFilePath, Toast.LENGTH_SHORT).show();
+ else
+ Toast.makeText(this, R.string.save_as_error, Toast.LENGTH_SHORT).show();
+ }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/TileProvider.java b/android/source/src/java/org/libreoffice/TileProvider.java
index 0ab5a1f641c9..e84127cb0715 100644
--- a/android/source/src/java/org/libreoffice/TileProvider.java
+++ b/android/source/src/java/org/libreoffice/TileProvider.java
@@ -20,6 +20,12 @@ import org.mozilla.gecko.gfx.IntSize;
* Provides the tiles and other document information.
*/
public interface TileProvider {
+
+ /**
+ * Save the current document.
+ */
+ void saveDocumentAs(String filePath, String format);
+
/**
* Returns the page width in pixels.
*/
diff --git a/android/source/src/java/org/libreoffice/ToolbarController.java b/android/source/src/java/org/libreoffice/ToolbarController.java
index e4a55dd424b6..0012fdbeae06 100644
--- a/android/source/src/java/org/libreoffice/ToolbarController.java
+++ b/android/source/src/java/org/libreoffice/ToolbarController.java
@@ -98,7 +98,11 @@ public class ToolbarController implements Toolbar.OnMenuItemClickListener {
mContext.showAbout();
return true;
case R.id.action_save:
- mContext.saveDocument();
+ if (mContext.isNewDocument) {
+ mContext.saveAs();
+ } else {
+ mContext.saveDocument();
+ }
return true;
case R.id.action_parts:
mContext.openDrawer();
diff --git a/android/source/src/java/org/libreoffice/ui/FileUtilities.java b/android/source/src/java/org/libreoffice/ui/FileUtilities.java
index 811fc4562dc7..aff6e0bfd7f3 100644
--- a/android/source/src/java/org/libreoffice/ui/FileUtilities.java
+++ b/android/source/src/java/org/libreoffice/ui/FileUtilities.java
@@ -121,7 +121,7 @@ public class FileUtilities {
extensionToMimeTypeMap.put("oth", "application/vnd.oasis.opendocument.text-web");
}
- private static final String getExtension(String filename) {
+ public static final String getExtension(String filename) {
if (filename == null)
return "";
int nExt = filename.lastIndexOf('.');
diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
index f2f408a7c331..01585b1077be 100644
--- a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
+++ b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
@@ -23,11 +23,14 @@ import android.hardware.usb.UsbManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Environment;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
+import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.v4.content.ContextCompat;
+import android.support.v4.view.ViewCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
@@ -47,7 +50,11 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.OvershootInterpolator;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -60,10 +67,12 @@ import org.libreoffice.storage.DocumentProviderFactory;
import org.libreoffice.storage.DocumentProviderSettingsActivity;
import org.libreoffice.storage.IDocumentProvider;
import org.libreoffice.storage.IFile;
+import org.libreoffice.storage.local.LocalFile;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
+import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
@@ -74,7 +83,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-public class LibreOfficeUIActivity extends AppCompatActivity implements SettingsListenerModel.OnSettingsPreferenceChangedListener{
+public class LibreOfficeUIActivity extends AppCompatActivity implements SettingsListenerModel.OnSettingsPreferenceChangedListener, View.OnClickListener{
private String LOGTAG = LibreOfficeUIActivity.class.getSimpleName();
private SharedPreferences prefs;
private int filterMode = FileUtilities.ALL;
@@ -98,6 +107,12 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
public static final String SORT_MODE_KEY = "SORT_MODE";
private static final String RECENT_DOCUMENTS_KEY = "RECENT_DOCUMENTS";
+ public static final String NEW_DOC_TYPE_KEY = "NEW_DOC_TYPE_KEY";
+ public static final String NEW_WRITER_STRING_KEY = "private:factory/swriter";
+ public static final String NEW_IMPRESS_STRING_KEY = "private:factory/simpress";
+ public static final String NEW_CALC_STRING_KEY = "private:factory/scalc";
+ public static final String NEW_DRAW_STRING_KEY = "private:factory/sdraw";
+
public static final int GRID_VIEW = 0;
public static final int LIST_VIEW = 1;
@@ -110,6 +125,20 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
private boolean canQuit = false;
+ private Animation fabOpenAnimation;
+ private Animation fabCloseAnimation;
+ private boolean isFabMenuOpen = false;
+ private FloatingActionButton editFAB;
+ private FloatingActionButton writerFAB;
+ private FloatingActionButton drawFAB;
+ private FloatingActionButton impressFAB;
+ private FloatingActionButton calcFAB;
+ private LinearLayout drawLayout;
+ private LinearLayout writerLayout;
+ private LinearLayout impressLayout;
+ private LinearLayout calcLayout;
+
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -129,6 +158,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
// init UI and populate with contents from the provider
switchToDocumentProvider(documentProviderFactory.getDefaultProvider());
createUI();
+ getAnimations();
}
public void createUI() {
@@ -143,6 +173,21 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
actionBar.setDisplayHomeAsUpEnabled(true);
}
+ editFAB = (FloatingActionButton) findViewById(R.id.editFAB);
+ editFAB.setOnClickListener(this);
+ impressFAB = (FloatingActionButton) findViewById(R.id.newImpressFAB);
+ impressFAB.setOnClickListener(this);
+ writerFAB = (FloatingActionButton) findViewById(R.id.newWriterFAB);
+ writerFAB.setOnClickListener(this);
+ calcFAB = (FloatingActionButton) findViewById(R.id.newCalcFAB);
+ calcFAB.setOnClickListener(this);
+ drawFAB = (FloatingActionButton) findViewById(R.id.newDrawFAB);
+ drawFAB.setOnClickListener(this);
+ writerLayout = (LinearLayout) findViewById(R.id.writerLayout);
+ impressLayout = (LinearLayout) findViewById(R.id.impressLayout);
+ calcLayout = (LinearLayout) findViewById(R.id.calcLayout);
+ drawLayout = (LinearLayout) findViewById(R.id.drawLayout);
+
recentRecyclerView = (RecyclerView) findViewById(R.id.list_recent);
Set<String> recentFileStrings = prefs.getStringSet(RECENT_DOCUMENTS_KEY, new HashSet<String>());
@@ -235,6 +280,9 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
super.onDrawerOpened(drawerView);
supportInvalidateOptionsMenu();
navigationDrawer.requestFocus(); // Make keypad navigation easier
+ if (isFabMenuOpen) {
+ collapseFabMenu(); //Collapse FAB Menu when drawer is opened
+ }
}
@Override
@@ -248,6 +296,37 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
drawerToggle.syncState();
}
+ private void getAnimations() {
+ fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open);
+ fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close);
+ }
+
+ private void expandFabMenu() {
+ ViewCompat.animate(editFAB).rotation(45.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
+ drawLayout.startAnimation(fabOpenAnimation);
+ impressLayout.startAnimation(fabOpenAnimation);
+ writerLayout.startAnimation(fabOpenAnimation);
+ calcLayout.startAnimation(fabOpenAnimation);
+ writerFAB.setClickable(true);
+ impressFAB.setClickable(true);
+ drawFAB.setClickable(true);
+ calcFAB.setClickable(true);
+ isFabMenuOpen = true;
+ }
+
+ private void collapseFabMenu() {
+ ViewCompat.animate(editFAB).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
+ writerLayout.startAnimation(fabCloseAnimation);
+ impressLayout.startAnimation(fabCloseAnimation);
+ drawLayout.startAnimation(fabCloseAnimation);
+ calcLayout.startAnimation(fabCloseAnimation);
+ writerFAB.setClickable(false);
+ impressFAB.setClickable(false);
+ drawFAB.setClickable(false);
+ calcFAB.setClickable(false);
+ isFabMenuOpen = false;
+ }
+
private boolean checkDocumentProviderAvailability(IDocumentProvider provider) {
return provider.checkProviderAvailability();
}
@@ -273,15 +352,23 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
fileRecyclerView.setAdapter(new ExplorerItemAdapter(this, filePaths));
// close drawer if it was open
drawerLayout.closeDrawer(navigationDrawer);
+ if (isFabMenuOpen) {
+ collapseFabMenu();
+ }
}
@Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(navigationDrawer)) {
drawerLayout.closeDrawer(navigationDrawer);
+ if (isFabMenuOpen) {
+ collapseFabMenu();
+ }
} else if (!currentDirectory.equals(homeDirectory)) {
// navigate upwards in directory hierarchy
openParentDirectory();
+ } else if (isFabMenuOpen) {
+ collapseFabMenu();
} else {
// only exit if warning has been shown
if (canQuit) {
@@ -460,6 +547,13 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
}.execute(document);
}
+ // For opening a new Document
+ private void open(String newDocumentType) {
+ Intent intent = new Intent(this, LibreOfficeMainActivity.class);
+ intent.putExtra(NEW_DOC_TYPE_KEY, newDocumentType);
+ startActivity(intent);
+ }
+
private void open(int position) {
IFile file = filePaths.get(position);
if (!file.isDirectory()) {
@@ -884,6 +978,33 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
}
}
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+ switch (id){
+ case R.id.editFAB:
+ if (isFabMenuOpen) {
+ collapseFabMenu();
+ } else {
+ expandFabMenu();
+ }
+ break;
+ case R.id.newWriterFAB:
+ open(NEW_WRITER_STRING_KEY);
+ break;
+ case R.id.newImpressFAB:
+ open(NEW_IMPRESS_STRING_KEY);
+ break;
+ case R.id.newCalcFAB:
+ open(NEW_CALC_STRING_KEY);
+ break;
+ case R.id.newDrawFAB:
+ open(NEW_DRAW_STRING_KEY);
+ break;
+ }
+ }
+
+
class ExplorerItemAdapter extends RecyclerView.Adapter<ExplorerItemAdapter.ViewHolder> {
private Activity mActivity;