diff options
Diffstat (limited to 'android/source/src/java/org/libreoffice/ui')
5 files changed, 813 insertions, 0 deletions
diff --git a/android/source/src/java/org/libreoffice/ui/FileUtilities.java b/android/source/src/java/org/libreoffice/ui/FileUtilities.java new file mode 100644 index 000000000..902b30ed7 --- /dev/null +++ b/android/source/src/java/org/libreoffice/ui/FileUtilities.java @@ -0,0 +1,153 @@ +/* -*- 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.ui; + +import java.util.Map; +import java.util.HashMap; + +import android.content.ContentResolver; +import android.database.Cursor; +import android.net.Uri; +import android.provider.OpenableColumns; +import android.util.Log; + +public class FileUtilities { + + private static final String LOGTAG = FileUtilities.class.getSimpleName(); + + // These have to be in sync with the file_view_modes resource. + static final int DOC = 0; + static final int CALC = 1; + static final int IMPRESS = 2; + static final int DRAWING = 3; + + static final int UNKNOWN = 10; + + public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text"; + public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet"; + public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION = "application/vnd.oasis.opendocument.presentation"; + public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS = "application/vnd.oasis.opendocument.graphics"; + public static final String MIMETYPE_PDF = "application/pdf"; + + private static final Map<String, Integer> mExtnMap = new HashMap<String, Integer>(); + static { + // Please keep this in sync with AndroidManifest.xml + // and 'SUPPORTED_MIME_TYPES' in LibreOfficeUIActivity.java + + // ODF + mExtnMap.put(".odt", DOC); + mExtnMap.put(".odg", DRAWING); + mExtnMap.put(".odp", IMPRESS); + mExtnMap.put(".ods", CALC); + mExtnMap.put(".fodt", DOC); + mExtnMap.put(".fodg", DRAWING); + mExtnMap.put(".fodp", IMPRESS); + mExtnMap.put(".fods", CALC); + + // ODF templates + mExtnMap.put(".ott", DOC); + mExtnMap.put(".otg", DRAWING); + mExtnMap.put(".otp", IMPRESS); + mExtnMap.put(".ots", CALC); + + // MS + mExtnMap.put(".rtf", DOC); + mExtnMap.put(".doc", DOC); + mExtnMap.put(".vsd", DRAWING); + mExtnMap.put(".vsdx", DRAWING); + mExtnMap.put(".pub", DRAWING); + mExtnMap.put(".ppt", IMPRESS); + mExtnMap.put(".pps", IMPRESS); + mExtnMap.put(".xls", CALC); + + // MS templates + mExtnMap.put(".dot", DOC); + mExtnMap.put(".pot", IMPRESS); + mExtnMap.put(".xlt", CALC); + + // OOXML + mExtnMap.put(".docx", DOC); + mExtnMap.put(".pptx", IMPRESS); + mExtnMap.put(".ppsx", IMPRESS); + mExtnMap.put(".xlsx", CALC); + + // OOXML templates + mExtnMap.put(".dotx", DOC); + mExtnMap.put(".potx", IMPRESS); + mExtnMap.put(".xltx", CALC); + + // Other + mExtnMap.put(".csv", CALC); + mExtnMap.put(".wps", DOC); + mExtnMap.put(".key", IMPRESS); + mExtnMap.put(".abw", DOC); + mExtnMap.put(".pmd", DRAWING); + mExtnMap.put(".emf", DRAWING); + mExtnMap.put(".svm", DRAWING); + mExtnMap.put(".wmf", DRAWING); + mExtnMap.put(".svg", DRAWING); + } + + public static String getExtension(String filename) { + if (filename == null) + return ""; + int nExt = filename.lastIndexOf('.'); + if (nExt < 0) + return ""; + return filename.substring(nExt); + } + + private static int lookupExtension(String filename) { + String extn = getExtension(filename); + if (!mExtnMap.containsKey(extn)) + return UNKNOWN; + return mExtnMap.get(extn); + } + + static int getType(String filename) { + int type = lookupExtension (filename); + Log.d(LOGTAG, "extn : " + filename + " -> " + type); + return type; + } + + /** + * Returns whether the passed MIME type is one for a document template. + */ + public static boolean isTemplateMimeType(final String mimeType) { + // this works for ODF and OOXML template MIME types + return mimeType != null && mimeType.endsWith("template"); + } + + /** + * Tries to retrieve the display (which should be the document name) + * for the given URI using the given resolver. + */ + public static String retrieveDisplayNameForDocumentUri(ContentResolver resolver, Uri docUri) { + String displayName = ""; + // try to retrieve original file name + Cursor cursor = null; + try { + String[] columns = {OpenableColumns.DISPLAY_NAME}; + cursor = resolver.query(docUri, columns, null, null, null); + if (cursor != null && cursor.moveToFirst()) { + displayName = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)); + } + } catch (SecurityException e) { + // thrown e.g. when Uri has become invalid, e.g. corresponding file has been deleted + Log.i(LOGTAG, "SecurityException when trying to receive display name for Uri " + docUri); + } finally { + if (cursor != null) { + cursor.close(); + } + } + return displayName; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java new file mode 100644 index 000000000..a5fa78f22 --- /dev/null +++ b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java @@ -0,0 +1,473 @@ +/* -*- 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.ui; + +import android.Manifest; +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; +import android.graphics.drawable.Icon; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.preference.PreferenceManager; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.core.view.ViewCompat; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.appcompat.widget.Toolbar; +import android.text.TextUtils; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.animation.OvershootInterpolator; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import org.libreoffice.AboutDialogFragment; +import org.libreoffice.LibreOfficeMainActivity; +import org.libreoffice.LocaleHelper; +import org.libreoffice.R; +import org.libreoffice.SettingsActivity; +import org.libreoffice.SettingsListenerModel; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class LibreOfficeUIActivity extends AppCompatActivity implements SettingsListenerModel.OnSettingsPreferenceChangedListener, View.OnClickListener{ + public enum DocumentType { + WRITER, + CALC, + IMPRESS, + DRAW, + INVALID + } + + private static final String LOGTAG = LibreOfficeUIActivity.class.getSimpleName(); + + public static final String EXPLORER_PREFS_KEY = "EXPLORER_PREFS"; + private static final String RECENT_DOCUMENTS_KEY = "RECENT_DOCUMENT_URIS"; + // delimiter used for storing multiple URIs in a string + private static final String RECENT_DOCUMENTS_DELIMITER = " "; + private static final String DISPLAY_LANGUAGE = "DISPLAY_LANGUAGE"; + + 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"; + + // keep this in sync with 'AndroidManifext.xml' + private static final String[] SUPPORTED_MIME_TYPES = { + "application/vnd.oasis.opendocument.text", + "application/vnd.oasis.opendocument.graphics", + "application/vnd.oasis.opendocument.presentation", + "application/vnd.oasis.opendocument.spreadsheet", + "application/vnd.oasis.opendocument.text-flat-xml", + "application/vnd.oasis.opendocument.graphics-flat-xml", + "application/vnd.oasis.opendocument.presentation-flat-xml", + "application/vnd.oasis.opendocument.spreadsheet-flat-xml", + "application/vnd.oasis.opendocument.text-template", + "application/vnd.oasis.opendocument.spreadsheet-template", + "application/vnd.oasis.opendocument.graphics-template", + "application/vnd.oasis.opendocument.presentation-template", + "application/rtf", + "text/rtf", + "application/msword", + "application/vnd.ms-powerpoint", + "application/vnd.ms-excel", + "application/vnd.visio", + "application/vnd.visio.xml", + "application/x-mspublisher", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.openxmlformats-officedocument.presentationml.slideshow", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.openxmlformats-officedocument.wordprocessingml.template", + "application/vnd.openxmlformats-officedocument.spreadsheetml.template", + "application/vnd.openxmlformats-officedocument.presentationml.template", + "text/csv", + "text/comma-separated-values", + "application/vnd.ms-works", + "application/vnd.apple.keynote", + "application/x-abiword", + "application/x-pagemaker", + "image/x-emf", + "image/x-svm", + "image/x-wmf", + "image/svg+xml", + }; + + private static final int REQUEST_CODE_OPEN_FILECHOOSER = 12345; + + private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0; + + 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); + + readPreferences(); + SettingsListenerModel.getInstance().setListener(this); + + // init UI + createUI(); + fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open); + fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close); + } + + @Override + protected void onStart() { + super.onStart(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + Log.i(LOGTAG, "no permission to read external storage - asking for permission"); + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + PERMISSION_WRITE_EXTERNAL_STORAGE); + } + } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.onAttach(newBase)); + } + + public void createUI() { + setContentView(R.layout.activity_document_browser); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + ActionBar actionBar = getSupportActionBar(); + + if (actionBar != null) { + actionBar.setIcon(R.drawable.lo_icon); + } + + editFAB = findViewById(R.id.editFAB); + editFAB.setOnClickListener(this); + impressFAB = findViewById(R.id.newImpressFAB); + impressFAB.setOnClickListener(this); + writerFAB = findViewById(R.id.newWriterFAB); + writerFAB.setOnClickListener(this); + calcFAB = findViewById(R.id.newCalcFAB); + calcFAB.setOnClickListener(this); + drawFAB = findViewById(R.id.newDrawFAB); + drawFAB.setOnClickListener(this); + writerLayout = findViewById(R.id.writerLayout); + impressLayout = findViewById(R.id.impressLayout); + calcLayout = findViewById(R.id.calcLayout); + drawLayout = findViewById(R.id.drawLayout); + TextView openFileView = findViewById(R.id.open_file_view); + openFileView.setOnClickListener(this); + + + RecyclerView recentRecyclerView = findViewById(R.id.list_recent); + + SharedPreferences prefs = getSharedPreferences(EXPLORER_PREFS_KEY, MODE_PRIVATE); + String recentPref = prefs.getString(RECENT_DOCUMENTS_KEY, ""); + String[] recentFileStrings = recentPref.split(RECENT_DOCUMENTS_DELIMITER); + + final List<RecentFile> recentFiles = new ArrayList<>(); + for (String recentFileString : recentFileStrings) { + Uri uri = Uri.parse(recentFileString); + String filename = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), uri); + if (!filename.isEmpty()) { + recentFiles.add(new RecentFile(uri, filename)); + } + } + + recentRecyclerView.setLayoutManager(new GridLayoutManager(this, 2)); + recentRecyclerView.setAdapter(new RecentFilesAdapter(this, recentFiles)); + } + + 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; + } + + @Override + public void onBackPressed() { + if (isFabMenuOpen) { + collapseFabMenu(); + } else { + super.onBackPressed(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_CODE_OPEN_FILECHOOSER && resultCode == RESULT_OK) { + final Uri fileUri = data.getData(); + openDocument(fileUri); + } + } + + private void showSystemFilePickerAndOpenFile() { + Intent intent = new Intent(); + if (Build.VERSION.SDK_INT >= 19) { + intent.setAction(Intent.ACTION_OPEN_DOCUMENT); + } + else { + // Intent.ACTION_OPEN_DOCUMENT added in API level 19, but minSdkVersion is currently 16 + intent.setAction(Intent.ACTION_GET_CONTENT); + } + + intent.setType("*/*"); + intent.putExtra(Intent.EXTRA_MIME_TYPES, SUPPORTED_MIME_TYPES); + + try { + startActivityForResult(intent, REQUEST_CODE_OPEN_FILECHOOSER); + } catch (ActivityNotFoundException e) { + Log.w(LOGTAG, "No activity available that can handle the intent to open a document."); + } + } + + public void openDocument(final Uri documentUri) { + // "forward" to LibreOfficeMainActivity to open the file + Intent intent = new Intent(Intent.ACTION_VIEW, documentUri); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + + addDocumentToRecents(documentUri); + + String packageName = getApplicationContext().getPackageName(); + ComponentName componentName = new ComponentName(packageName, + LibreOfficeMainActivity.class.getName()); + intent.setComponent(componentName); + startActivity(intent); + } + + private void loadNewDocument(DocumentType docType) { + final String newDocumentType; + if (docType == DocumentType.WRITER) { + newDocumentType = NEW_WRITER_STRING_KEY; + } else if (docType == DocumentType.CALC) { + newDocumentType = NEW_CALC_STRING_KEY; + } else if (docType == DocumentType.IMPRESS) { + newDocumentType = NEW_IMPRESS_STRING_KEY; + } else if (docType == DocumentType.DRAW) { + newDocumentType = NEW_DRAW_STRING_KEY; + } else { + Log.w(LOGTAG, "invalid document type passed to loadNewDocument method. Ignoring request"); + return; + } + + Intent intent = new Intent(LibreOfficeUIActivity.this, LibreOfficeMainActivity.class); + intent.putExtra(NEW_DOC_TYPE_KEY, newDocumentType); + startActivity(intent); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.view_menu, menu); + + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + final int itemId = item.getItemId(); + if (itemId == R.id.action_about) { + AboutDialogFragment aboutDialogFragment = new AboutDialogFragment(); + aboutDialogFragment.show(getSupportFragmentManager(), "AboutDialogFragment"); + return true; + } + if (itemId == R.id.action_settings) { + startActivity(new Intent(getApplicationContext(), SettingsActivity.class)); + return true; + } + + return super.onOptionsItemSelected(item); + } + + public void readPreferences(){ + SharedPreferences defaultPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); + final String displayLanguage = defaultPrefs.getString(DISPLAY_LANGUAGE, LocaleHelper.SYSTEM_DEFAULT_LANGUAGE); + LocaleHelper.setLocale(this, displayLanguage); + } + + @Override + public void settingsPreferenceChanged(SharedPreferences sharedPreferences, String key) { + readPreferences(); + } + + @Override + protected void onResume() { + super.onResume(); + Log.d(LOGTAG, "onResume"); + createUI(); + } + + private void addDocumentToRecents(Uri fileUri) { + SharedPreferences prefs = getSharedPreferences(EXPLORER_PREFS_KEY, MODE_PRIVATE); + if (Build.VERSION.SDK_INT < 19) { + // ContentResolver#takePersistableUriPermission only available from SDK level 19 on + Log.i(LOGTAG, "Recently used files not supported, requires SDK version >= 19."); + // drop potential entries + prefs.edit().putString(RECENT_DOCUMENTS_KEY, "").apply(); + return; + } + + // preserve permissions across device reboots, + // s. https://developer.android.com/training/data-storage/shared/documents-files#persist-permissions + getContentResolver().takePersistableUriPermission(fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + + String newRecent = fileUri.toString(); + List<String> recentsList = new ArrayList<>(Arrays.asList(prefs.getString(RECENT_DOCUMENTS_KEY, "").split(RECENT_DOCUMENTS_DELIMITER))); + + // remove string if present, so that it doesn't appear multiple times + recentsList.remove(newRecent); + + // put the new value in the first place + recentsList.add(0, newRecent); + + /* + * 4 because the number of recommended items in App Shortcuts is 4, and also + * because it's a good number of recent items in general + */ + final int RECENTS_SIZE = 4; + + while (recentsList.size() > RECENTS_SIZE) { + recentsList.remove(RECENTS_SIZE); + } + + // serialize to String that can be set for pref + String value = TextUtils.join(RECENT_DOCUMENTS_DELIMITER, recentsList); + prefs.edit().putString(RECENT_DOCUMENTS_KEY, value).apply(); + + //update app shortcuts (7.0 and above) + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) { + ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); + + //Remove all shortcuts, and apply new ones. + shortcutManager.removeAllDynamicShortcuts(); + + ArrayList<ShortcutInfo> shortcuts = new ArrayList<>(); + for (String recentDoc : recentsList) { + Uri docUri = Uri.parse(recentDoc); + String filename = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), docUri); + if (filename.isEmpty()) { + continue; + } + + //find the appropriate drawable + int drawable = 0; + switch (FileUtilities.getType(filename)) { + case FileUtilities.DOC: + drawable = R.drawable.writer; + break; + case FileUtilities.CALC: + drawable = R.drawable.calc; + break; + case FileUtilities.DRAWING: + drawable = R.drawable.draw; + break; + case FileUtilities.IMPRESS: + drawable = R.drawable.impress; + break; + } + + Intent intent = new Intent(Intent.ACTION_VIEW, docUri); + String packageName = this.getApplicationContext().getPackageName(); + ComponentName componentName = new ComponentName(packageName, LibreOfficeMainActivity.class.getName()); + intent.setComponent(componentName); + + ShortcutInfo shortcut = new ShortcutInfo.Builder(this, filename) + .setShortLabel(filename) + .setLongLabel(filename) + .setIcon(Icon.createWithResource(this, drawable)) + .setIntent(intent) + .build(); + + shortcuts.add(shortcut); + } + shortcutManager.setDynamicShortcuts(shortcuts); + } + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.editFAB) { + // Intent.ACTION_CREATE_DOCUMENT, used in 'createNewFileDialog' requires SDK version 19 + if (Build.VERSION.SDK_INT < 19) { + Toast.makeText(this, + getString(R.string.creating_new_files_not_supported), Toast.LENGTH_SHORT).show(); + return; + } + if (isFabMenuOpen) { + collapseFabMenu(); + } else { + expandFabMenu(); + } + } else if (id == R.id.open_file_view) { + showSystemFilePickerAndOpenFile(); + } else if (id == R.id.newWriterFAB) { + loadNewDocument(DocumentType.WRITER); + } else if (id == R.id.newImpressFAB) { + loadNewDocument(DocumentType.IMPRESS); + } else if (id == R.id.newCalcFAB) { + loadNewDocument(DocumentType.CALC); + } else if (id == R.id.newDrawFAB) { + loadNewDocument(DocumentType.DRAW); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/android/source/src/java/org/libreoffice/ui/PageView.java b/android/source/src/java/org/libreoffice/ui/PageView.java new file mode 100644 index 000000000..4c3f69562 --- /dev/null +++ b/android/source/src/java/org/libreoffice/ui/PageView.java @@ -0,0 +1,69 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +package org.libreoffice.ui; + +import org.libreoffice.R; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; + +public class PageView extends View{ + private Bitmap bmp; + private Paint mPaintBlack; + private static final String LOGTAG = "PageView"; + + public PageView(Context context ) { + super(context); + bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page); + initialise(); + } + public PageView(Context context, AttributeSet attrs) { + super(context, attrs); + bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page); + Log.d(LOGTAG, bmp.toString()); + initialise(); + } + public PageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page);//load a "page" + initialise(); + } + + private void initialise(){ + mPaintBlack = new Paint(); + mPaintBlack.setARGB(255, 0, 0, 0); + Log.d(LOGTAG, " Doing some set-up"); + } + + public void setBitmap(Bitmap bmp){ + this.bmp = bmp; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + Log.d(LOGTAG, "Draw"); + Log.d(LOGTAG, Integer.toString(bmp.getHeight())); + if( bmp != null ){ + int horizontalMargin = (int) (canvas.getWidth()*0.1); + //int verticalMargin = (int) (canvas.getHeight()*0.1); + int verticalMargin = horizontalMargin; + canvas.drawBitmap(bmp, new Rect(0, 0, bmp.getWidth(), bmp.getHeight()), + new Rect(horizontalMargin,verticalMargin,canvas.getWidth()-horizontalMargin, + canvas.getHeight()-verticalMargin), + mPaintBlack);// + } + if( bmp == null) + canvas.drawText(getContext().getString(R.string.bmp_null), 100, 100, new Paint()); + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/android/source/src/java/org/libreoffice/ui/RecentFile.java b/android/source/src/java/org/libreoffice/ui/RecentFile.java new file mode 100644 index 000000000..fdcc688aa --- /dev/null +++ b/android/source/src/java/org/libreoffice/ui/RecentFile.java @@ -0,0 +1,25 @@ +package org.libreoffice.ui; + +import android.net.Uri; + +/** + * An entry for a recently used file in the RecentFilesAdapter. + */ +public class RecentFile { + + private final Uri uri; + private final String displayName; + + public RecentFile(Uri docUri, String name) { + uri = docUri; + displayName = name; + } + + public Uri getUri() { + return uri; + } + + public String getDisplayName() { + return displayName; + } +} diff --git a/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java b/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java new file mode 100644 index 000000000..ef00b9fb6 --- /dev/null +++ b/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java @@ -0,0 +1,93 @@ +/* -*- 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.ui; + +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import org.libreoffice.R; + +import java.util.List; + +class RecentFilesAdapter extends RecyclerView.Adapter<RecentFilesAdapter.ViewHolder> { + + private final LibreOfficeUIActivity mActivity; + private final List<RecentFile> recentFiles; + + RecentFilesAdapter(LibreOfficeUIActivity activity, List<RecentFile> recentFiles) { + this.mActivity = activity; + this.recentFiles = recentFiles; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_recent_files, parent, false); + return new ViewHolder(item); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + final RecentFile entry = recentFiles.get(position); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mActivity.openDocument(entry.getUri()); + } + }); + + final String filename = entry.getDisplayName(); + holder.textView.setText(filename); + + int compoundDrawableInt = 0; + + switch (FileUtilities.getType(filename)) { + case FileUtilities.DOC: + compoundDrawableInt = R.drawable.writer; + break; + case FileUtilities.CALC: + compoundDrawableInt = R.drawable.calc; + break; + case FileUtilities.DRAWING: + compoundDrawableInt = R.drawable.draw; + break; + case FileUtilities.IMPRESS: + compoundDrawableInt = R.drawable.impress; + break; + } + + // set icon if known filetype was detected + if (compoundDrawableInt != 0) + holder.imageView.setImageDrawable(ContextCompat.getDrawable(mActivity, compoundDrawableInt)); + } + + @Override + public int getItemCount() { + return recentFiles.size(); + } + + class ViewHolder extends RecyclerView.ViewHolder { + + TextView textView; + ImageView imageView; + + ViewHolder(View itemView) { + super(itemView); + this.textView = itemView.findViewById(R.id.textView); + this.imageView = itemView.findViewById(R.id.imageView); + } + } +} |