diff options
author | Tor Lillqvist <tml@collabora.com> | 2015-05-21 16:54:28 +0100 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2015-05-21 16:56:48 +0100 |
commit | 1b53066433d1db9c3bfc3c6e6618565c15642b59 (patch) | |
tree | 9e2d440ff0520c800a6670dbdb01bc587e47742c /android | |
parent | dae9a386bacc08a55eda96e1e8925883a4fa494d (diff) |
Bin the 'DocumentLoader' Android test app
It is the wrong approach, from the time before tiled rendering, and has
not been built for a long time.
Diffstat (limited to 'android')
22 files changed, 0 insertions, 3437 deletions
diff --git a/android/experimental/DocumentLoader/AndroidManifest.xml b/android/experimental/DocumentLoader/AndroidManifest.xml deleted file mode 100644 index 366a1c909b3e..000000000000 --- a/android/experimental/DocumentLoader/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> <!-- -*- indent-tabs-mode: nil -*- --> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="org.libreoffice.android.examples" - android:installLocation="preferExternal" - android:versionCode="1" - android:versionName="1.0"> - <uses-sdk android:minSdkVersion="15" - android:targetSdkVersion="15"/> - <application android:label="LO Experimental DocumentLoader" - android:debuggable="true" - android:largeHeap="true" - android:hardwareAccelerated="true"> - <activity android:name=".DocumentLoader" - android:label="LO DocumentLoader" - android:configChanges="keyboardHidden"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> -<!-- vim:set expandtab: --> diff --git a/android/experimental/DocumentLoader/Makefile b/android/experimental/DocumentLoader/Makefile deleted file mode 100644 index dbe2b5ce051c..000000000000 --- a/android/experimental/DocumentLoader/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -ifeq ($(BUILDDIR),) -include ../../../config_host.mk -endif - -# The default target just builds. -all: build-ant - -# The package of this app -APP_PACKAGE=org.libreoffice.android.examples - -BOOTSTRAPDIR=../../Bootstrap -include $(BOOTSTRAPDIR)/Makefile.shared - -native-code.cxx: $(SRCDIR)/solenv/bin/native-code.py - $< \ - -g core -g writer \ - > $@ - -build-ant: android_version_setup copy-stuff link-so properties -# -# Copy jar files we need -# - for F in java_uno \ - juh \ - jurt \ - ridl \ - unoloader; do \ - $(call COPYJAR,$(INSTDIR)/$(LIBO_URE_SHARE_JAVA_FOLDER)/$${F}.jar); \ - done - for F in unoil; do \ - $(call COPYJAR,$(INSTDIR)/$(LIBO_SHARE_JAVA_FOLDER)/$${F}.jar); \ - done -# - unset JAVA_HOME && $(ANT) $(if $(VERBOSE)$(verbose),,-quiet) debug - -run: - adb shell am start -n org.libreoffice.android.examples/.DocumentLoader -e input /assets/test1.odt diff --git a/android/experimental/DocumentLoader/build.xml b/android/experimental/DocumentLoader/build.xml deleted file mode 100644 index a35fbcc5de74..000000000000 --- a/android/experimental/DocumentLoader/build.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project name="LibreOfficeDocumentLoader" default="help"> - - <!-- The local.properties file is created and updated by the 'android' tool. - It contains the path to the SDK. It should *NOT* be checked into - Version Control Systems. --> - <loadproperties srcFile="local.properties" /> - - <!-- The ant.properties file can be created by you. It is only edited by the - 'android' tool to add properties to it. - This is the place to change some Ant specific build properties. - Here are some properties you may want to change/update: - - source.dir - The name of the source directory. Default is 'src'. - out.dir - The name of the output directory. Default is 'bin'. - - For other overridable properties, look at the beginning of the rules - files in the SDK, at tools/ant/build.xml - - Properties related to the SDK location or the project target should - be updated using the 'android' tool with the 'update' action. - - This file is an integral part of the build system for your - application and should be checked into Version Control Systems. - - --> - <property file="ant.properties" /> - - <!-- The project.properties file is created and updated by the 'android' - tool, as well as ADT. - - This contains project specific properties such as project target, and library - dependencies. Lower level build properties are stored in ant.properties - (or in .classpath for Eclipse projects). - - This file is an integral part of the build system for your - application and should be checked into Version Control Systems. --> - <loadproperties srcFile="project.properties" /> - - <!-- quick check on sdk.dir --> - <fail - message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" - unless="sdk.dir" - /> - - -<!-- extension targets. Uncomment the ones where you want to do custom work - in between standard targets --> -<!-- - <target name="-pre-build"> - </target> - <target name="-pre-compile"> - </target> - - /* This is typically used for code obfuscation. - Compiled code location: ${out.classes.absolute.dir} - If this is not done in place, override ${out.dex.input.absolute.dir} */ - <target name="-post-compile"> - </target> ---> - - <!-- Import the actual build file. - - To customize existing targets, there are two options: - - Customize only one target: - - copy/paste the target into this file, *before* the - <import> task. - - customize it to your needs. - - Customize the whole content of build.xml - - copy/paste the content of the rules files (minus the top node) - into this file, replacing the <import> task. - - customize to your needs. - - *********************** - ****** IMPORTANT ****** - *********************** - In all cases you must update the value of version-tag below to read 'custom' instead of an integer, - in order to avoid having your file be overridden by tools such as "android update project" - --> - <!-- version-tag: custom --> - <import file="${android.library.reference.1}/no-resource-compress.xml" /> -</project> diff --git a/android/experimental/DocumentLoader/fonts.conf b/android/experimental/DocumentLoader/fonts.conf deleted file mode 100644 index 699e9d101048..000000000000 --- a/android/experimental/DocumentLoader/fonts.conf +++ /dev/null @@ -1,154 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE fontconfig SYSTEM "fonts.dtd"> -<!-- /etc/fonts/fonts.conf file to configure system font access --> -<fontconfig> - -<!-- Font directory list --> - - <dir>/system/fonts</dir> - - <alias> - <family>serif</family> - <prefer> - <family>Droid Serif</family> - </prefer> - </alias> - <alias> - <family>sans-serif</family> - <prefer> - <family>Roboto</family> - <family>Droid Sans Fallback</family> - </prefer> - </alias> - <alias> - <family>monospace</family> - <prefer> - <family>Droid Sans Mono</family> - </prefer> - </alias> - -<!-- - Accept deprecated 'mono' alias, replacing it with 'monospace' ---> - <match target="pattern"> - <test qual="any" name="family"> - <string>mono</string> - </test> - <edit name="family" mode="assign"> - <string>monospace</string> - </edit> - </match> - -<!-- - Accept alternate 'sans serif' spelling, replacing it with 'sans-serif' ---> - <match target="pattern"> - <test qual="any" name="family"> - <string>sans serif</string> - </test> - <edit name="family" mode="assign"> - <string>sans-serif</string> - </edit> - </match> - -<!-- - Accept deprecated 'sans' alias, replacing it with 'sans-serif' ---> - <match target="pattern"> - <test qual="any" name="family"> - <string>sans</string> - </test> - <edit name="family" mode="assign"> - <string>sans-serif</string> - </edit> - </match> - -<!-- - Load local system customization file ---> - <include ignore_missing="yes">conf.d</include> - -<!-- Font cache directory list --> - - <!-- Yeah this hardcoding is wrong of course, will have to fix - later to patch in proper code in fontonfig on Android to - find out a good place. - --> - <cachedir>/data/data/org.libreoffice.android.examples/fontconfig</cachedir> - - <config> -<!-- - These are the default Unicode chars that are expected to be blank - in fonts. All other blank chars are assumed to be broken and - won't appear in the resulting charsets - --> - <blank> - <int>0x0020</int> <!-- SPACE --> - <int>0x00A0</int> <!-- NO-BREAK SPACE --> - <int>0x00AD</int> <!-- SOFT HYPHEN --> - <int>0x034F</int> <!-- COMBINING GRAPHEME JOINER --> - <int>0x0600</int> <!-- ARABIC NUMBER SIGN --> - <int>0x0601</int> <!-- ARABIC SIGN SANAH --> - <int>0x0602</int> <!-- ARABIC FOOTNOTE MARKER --> - <int>0x0603</int> <!-- ARABIC SIGN SAFHA --> - <int>0x06DD</int> <!-- ARABIC END OF AYAH --> - <int>0x070F</int> <!-- SYRIAC ABBREVIATION MARK --> - <int>0x115F</int> <!-- HANGUL CHOSEONG FILLER --> - <int>0x1160</int> <!-- HANGUL JUNGSEONG FILLER --> - <int>0x1680</int> <!-- OGHAM SPACE MARK --> - <int>0x17B4</int> <!-- KHMER VOWEL INHERENT AQ --> - <int>0x17B5</int> <!-- KHMER VOWEL INHERENT AA --> - <int>0x180E</int> <!-- MONGOLIAN VOWEL SEPARATOR --> - <int>0x2000</int> <!-- EN QUAD --> - <int>0x2001</int> <!-- EM QUAD --> - <int>0x2002</int> <!-- EN SPACE --> - <int>0x2003</int> <!-- EM SPACE --> - <int>0x2004</int> <!-- THREE-PER-EM SPACE --> - <int>0x2005</int> <!-- FOUR-PER-EM SPACE --> - <int>0x2006</int> <!-- SIX-PER-EM SPACE --> - <int>0x2007</int> <!-- FIGURE SPACE --> - <int>0x2008</int> <!-- PUNCTUATION SPACE --> - <int>0x2009</int> <!-- THIN SPACE --> - <int>0x200A</int> <!-- HAIR SPACE --> - <int>0x200B</int> <!-- ZERO WIDTH SPACE --> - <int>0x200C</int> <!-- ZERO WIDTH NON-JOINER --> - <int>0x200D</int> <!-- ZERO WIDTH JOINER --> - <int>0x200E</int> <!-- LEFT-TO-RIGHT MARK --> - <int>0x200F</int> <!-- RIGHT-TO-LEFT MARK --> - <int>0x2028</int> <!-- LINE SEPARATOR --> - <int>0x2029</int> <!-- PARAGRAPH SEPARATOR --> - <int>0x202A</int> <!-- LEFT-TO-RIGHT EMBEDDING --> - <int>0x202B</int> <!-- RIGHT-TO-LEFT EMBEDDING --> - <int>0x202C</int> <!-- POP DIRECTIONAL FORMATTING --> - <int>0x202D</int> <!-- LEFT-TO-RIGHT OVERRIDE --> - <int>0x202E</int> <!-- RIGHT-TO-LEFT OVERRIDE --> - <int>0x202F</int> <!-- NARROW NO-BREAK SPACE --> - <int>0x205F</int> <!-- MEDIUM MATHEMATICAL SPACE --> - <int>0x2060</int> <!-- WORD JOINER --> - <int>0x2061</int> <!-- FUNCTION APPLICATION --> - <int>0x2062</int> <!-- INVISIBLE TIMES --> - <int>0x2063</int> <!-- INVISIBLE SEPARATOR --> - <int>0x206A</int> <!-- INHIBIT SYMMETRIC SWAPPING --> - <int>0x206B</int> <!-- ACTIVATE SYMMETRIC SWAPPING --> - <int>0x206C</int> <!-- INHIBIT ARABIC FORM SHAPING --> - <int>0x206D</int> <!-- ACTIVATE ARABIC FORM SHAPING --> - <int>0x206E</int> <!-- NATIONAL DIGIT SHAPES --> - <int>0x206F</int> <!-- NOMINAL DIGIT SHAPES --> - <int>0x2800</int> <!-- BRAILLE PATTERN BLANK --> - <int>0x3000</int> <!-- IDEOGRAPHIC SPACE --> - <int>0x3164</int> <!-- HANGUL FILLER --> - <int>0xFEFF</int> <!-- ZERO WIDTH NO-BREAK SPACE --> - <int>0xFFA0</int> <!-- HALFWIDTH HANGUL FILLER --> - <int>0xFFF9</int> <!-- INTERLINEAR ANNOTATION ANCHOR --> - <int>0xFFFA</int> <!-- INTERLINEAR ANNOTATION SEPARATOR --> - <int>0xFFFB</int> <!-- INTERLINEAR ANNOTATION TERMINATOR --> - </blank> -<!-- - Rescan configuration every 3600 seconds when FcFontSetList is called - --> - <rescan> - <int>3600</int> - </rescan> - </config> - -</fontconfig> diff --git a/android/experimental/DocumentLoader/jni/Android.mk b/android/experimental/DocumentLoader/jni/Android.mk deleted file mode 100644 index 939a1ea503bb..000000000000 --- a/android/experimental/DocumentLoader/jni/Android.mk +++ /dev/null @@ -1,8 +0,0 @@ -# Needed just to satisfy ndk-gdb for now, but maybe later we will actually add -# some JNI code here - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -include $(BUILD_SHARED_LIBRARY) diff --git a/android/experimental/DocumentLoader/project.properties b/android/experimental/DocumentLoader/project.properties deleted file mode 100644 index 3b686189734d..000000000000 --- a/android/experimental/DocumentLoader/project.properties +++ /dev/null @@ -1,14 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -# Project target. -target=android-21 - -# Use the Bootstrap class -android.library.reference.1=../../Bootstrap diff --git a/android/experimental/DocumentLoader/res/menu/option.xml b/android/experimental/DocumentLoader/res/menu/option.xml deleted file mode 100644 index 3230d83fe0cc..000000000000 --- a/android/experimental/DocumentLoader/res/menu/option.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:id="@+id/go_to_page" - android:title="@string/go_to_page"/> -</menu> diff --git a/android/experimental/DocumentLoader/res/values/strings.xml b/android/experimental/DocumentLoader/res/values/strings.xml deleted file mode 100644 index 148461bfd621..000000000000 --- a/android/experimental/DocumentLoader/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> - <string name="go_to_page">Go to page</string> -</resources> diff --git a/android/experimental/DocumentLoader/src/com/polites/android/Animation.java b/android/experimental/DocumentLoader/src/com/polites/android/Animation.java deleted file mode 100644 index a0d218b1e552..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/Animation.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -public interface Animation { - - /** - * Transforms the view. - * @param view - * @param diffTime - * @return true if this animation should remain active. False otherwise. - */ - public boolean update(GestureImageView view, long time); - -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/Animator.java b/android/experimental/DocumentLoader/src/com/polites/android/Animator.java deleted file mode 100644 index 6fc82f127503..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/Animator.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -public class Animator extends Thread { - - private GestureImageView view; - private Animation animation; - private boolean running = false; - private boolean active = false; - private long lastTime = -1L; - - public Animator(GestureImageView view, String threadName) { - super(threadName); - this.view = view; - } - - @Override - public void run() { - - running = true; - - while(running) { - - while(active && animation != null) { - long time = System.currentTimeMillis(); - active = animation.update(view, time - lastTime); - view.redraw(); - lastTime = time; - - while(active) { - try { - if(view.waitForDraw(32)) { // 30Htz - break; - } - } - catch (InterruptedException ignore) { - active = false; - } - } - } - - synchronized(this) { - if(running) { - try { - wait(); - } - catch (InterruptedException ignore) {} - } - } - } - } - - public synchronized void finish() { - running = false; - active = false; - notifyAll(); - } - - public void play(Animation transformer) { - if(active) { - cancel(); - } - this.animation = transformer; - - activate(); - } - - public synchronized void activate() { - lastTime = System.currentTimeMillis(); - active = true; - notifyAll(); - } - - public void cancel() { - active = false; - } -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/FlingAnimation.java b/android/experimental/DocumentLoader/src/com/polites/android/FlingAnimation.java deleted file mode 100644 index 9afd54969b50..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/FlingAnimation.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -public class FlingAnimation implements Animation { - - private float velocityX; - private float velocityY; - - private float factor = 0.85f; - - private float threshold = 10; - - private FlingAnimationListener listener; - - /* (non-Javadoc) - * @see com.polites.android.Transformer#update(com.polites.android.GestureImageView, long) - */ - @Override - public boolean update(GestureImageView view, long time) { - float seconds = (float) time / 1000.0f; - - float dx = velocityX * seconds; - float dy = velocityY * seconds; - - velocityX *= factor; - velocityY *= factor; - - boolean active = (Math.abs(velocityX) > threshold && Math.abs(velocityY) > threshold); - - if(listener != null) { - listener.onMove(dx, dy); - - if(!active) { - listener.onComplete(); - } - } - - return active; - } - - public void setVelocityX(float velocityX) { - this.velocityX = velocityX; - } - - public void setVelocityY(float velocityY) { - this.velocityY = velocityY; - } - - public void setFactor(float factor) { - this.factor = factor; - } - - public void setListener(FlingAnimationListener listener) { - this.listener = listener; - } -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/FlingAnimationListener.java b/android/experimental/DocumentLoader/src/com/polites/android/FlingAnimationListener.java deleted file mode 100644 index 8f0dd3d77e79..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/FlingAnimationListener.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -public interface FlingAnimationListener { - - public void onMove(float x, float y); - - public void onComplete(); - -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/GestureImageView.java b/android/experimental/DocumentLoader/src/com/polites/android/GestureImageView.java deleted file mode 100644 index 4b9278c1cf35..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/GestureImageView.java +++ /dev/null @@ -1,718 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -import java.io.InputStream; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import android.content.Context; -import android.content.res.Configuration; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Matrix; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.provider.MediaStore; -import android.util.AttributeSet; -import android.util.Log; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.widget.ImageView; - -public class GestureImageView extends ImageView { - - public static final String GLOBAL_NS = "http://schemas.android.com/apk/res/android"; - public static final String LOCAL_NS = "http://schemas.polites.com/android"; - - private final Semaphore drawLock = new Semaphore(0); - private Animator animator; - - private Drawable drawable; - - private float x = 0, y = 0; - - private boolean layout = false; - - private float scaleAdjust = 1.0f; - private float startingScale = -1.0f; - - private float scale = 1.0f; - private float maxScale = 5.0f; - private float minScale = 0.75f; - private float fitScaleHorizontal = 1.0f; - private float fitScaleVertical = 1.0f; - private float rotation = 0.0f; - - private float centerX; - private float centerY; - - private Float startX, startY; - - private int hWidth; - private int hHeight; - - private int resId = -1; - private boolean recycle = false; - private boolean strict = false; - - private int displayHeight; - private int displayWidth; - - private int alpha = 255; - private ColorFilter colorFilter; - - private int deviceOrientation = -1; - private int imageOrientation; - - private GestureImageViewListener gestureImageViewListener; - private GestureImageViewTouchListener gestureImageViewTouchListener; - - private OnTouchListener customOnTouchListener; - private OnClickListener onClickListener; - - GestureDetector.OnGestureListener overflowGestureListener; - - public GestureImageView(Context context, GestureDetector.OnGestureListener overflowGestureListener, AttributeSet attrs, int defStyle) { - this(context, overflowGestureListener, attrs); - } - - public GestureImageView(Context context, GestureDetector.OnGestureListener overflowGestureListener, AttributeSet attrs) { - super(context, attrs); - - this.overflowGestureListener = overflowGestureListener; - String scaleType = attrs.getAttributeValue(GLOBAL_NS, "scaleType"); - - if(scaleType == null || scaleType.trim().length() == 0) { - setScaleType(ScaleType.CENTER_INSIDE); - } - - String strStartX = attrs.getAttributeValue(LOCAL_NS, "start-x"); - String strStartY = attrs.getAttributeValue(LOCAL_NS, "start-y"); - - if(strStartX != null && strStartX.trim().length() > 0) { - startX = Float.parseFloat(strStartX); - } - - if(strStartY != null && strStartY.trim().length() > 0) { - startY = Float.parseFloat(strStartY); - } - - setStartingScale(attrs.getAttributeFloatValue(LOCAL_NS, "start-scale", startingScale)); - setMinScale(attrs.getAttributeFloatValue(LOCAL_NS, "min-scale", minScale)); - setMaxScale(attrs.getAttributeFloatValue(LOCAL_NS, "max-scale", maxScale)); - setStrict(attrs.getAttributeBooleanValue(LOCAL_NS, "strict", strict)); - setRecycle(attrs.getAttributeBooleanValue(LOCAL_NS, "recycle", recycle)); - - initImage(); - } - - public GestureImageView(Context context, GestureDetector.OnGestureListener overflowGestureListener) { - super(context); - - this.overflowGestureListener = overflowGestureListener; - setScaleType(ScaleType.CENTER_INSIDE); - initImage(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - - if(drawable != null) { - int orientation = getResources().getConfiguration().orientation; - if(orientation == Configuration.ORIENTATION_LANDSCAPE) { - displayHeight = MeasureSpec.getSize(heightMeasureSpec); - - if(getLayoutParams().width == LayoutParams.WRAP_CONTENT) { - float ratio = (float) getImageWidth() / (float) getImageHeight(); - displayWidth = Math.round( (float) displayHeight * ratio) ; - } - else { - displayWidth = MeasureSpec.getSize(widthMeasureSpec); - } - } - else { - displayWidth = MeasureSpec.getSize(widthMeasureSpec); - if(getLayoutParams().height == LayoutParams.WRAP_CONTENT) { - float ratio = (float) getImageHeight() / (float) getImageWidth(); - displayHeight = Math.round( (float) displayWidth * ratio) ; - } - else { - displayHeight = MeasureSpec.getSize(heightMeasureSpec); - } - } - } - else { - displayHeight = MeasureSpec.getSize(heightMeasureSpec); - displayWidth = MeasureSpec.getSize(widthMeasureSpec); - } - - setMeasuredDimension(displayWidth, displayHeight); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if(changed || !layout) { - setupCanvas(displayWidth, displayHeight, getResources().getConfiguration().orientation); - } - } - - protected void setupCanvas(int measuredWidth, int measuredHeight, int orientation) { - - if(deviceOrientation != orientation) { - layout = false; - deviceOrientation = orientation; - } - - if(drawable != null && !layout) { - int imageWidth = getImageWidth(); - int imageHeight = getImageHeight(); - - hWidth = Math.round(((float)imageWidth / 2.0f)); - hHeight = Math.round(((float)imageHeight / 2.0f)); - - measuredWidth -= (getPaddingLeft() + getPaddingRight()); - measuredHeight -= (getPaddingTop() + getPaddingBottom()); - - computeCropScale(imageWidth, imageHeight, measuredWidth, measuredHeight); - - if(startingScale <= 0.0f) { - computeStartingScale(imageWidth, imageHeight, measuredWidth, measuredHeight); - } - - scaleAdjust = startingScale; - - this.centerX = (float) measuredWidth / 2.0f; - this.centerY = (float) measuredHeight / 2.0f; - - if(startX == null) { - x = centerX; - } - else { - x = startX; - } - - if(startY == null) { - y = centerY; - } - else { - y = startY; - } - - gestureImageViewTouchListener = new GestureImageViewTouchListener(this, measuredWidth, measuredHeight); - - if(isLandscape()) { - gestureImageViewTouchListener.setMinScale(minScale * fitScaleHorizontal); - } - else { - gestureImageViewTouchListener.setMinScale(minScale * fitScaleVertical); - } - - - gestureImageViewTouchListener.setMaxScale(maxScale * startingScale); - - gestureImageViewTouchListener.setFitScaleHorizontal(fitScaleHorizontal); - gestureImageViewTouchListener.setFitScaleVertical(fitScaleVertical); - gestureImageViewTouchListener.setCanvasWidth(measuredWidth); - gestureImageViewTouchListener.setCanvasHeight(measuredHeight); - gestureImageViewTouchListener.setOnClickListener(onClickListener); - - drawable.setBounds(-hWidth,-hHeight,hWidth,hHeight); - - super.setOnTouchListener(new OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - if(customOnTouchListener != null) { - customOnTouchListener.onTouch(v, event); - } - return gestureImageViewTouchListener.onTouch(v, event); - } - }); - - layout = true; - } - } - - protected void computeCropScale(int imageWidth, int imageHeight, int measuredWidth, int measuredHeight) { - fitScaleHorizontal = (float) measuredWidth / (float) imageWidth; - fitScaleVertical = (float) measuredHeight / (float) imageHeight; - } - - protected void computeStartingScale(int imageWidth, int imageHeight, int measuredWidth, int measuredHeight) { - switch(getScaleType()) { - case CENTER: - // Center the image in the view, but perform no scaling. - startingScale = 1.0f; - break; - - case CENTER_CROP: - startingScale = Math.max((float) measuredHeight / (float) imageHeight, (float) measuredWidth/ (float) imageWidth); - break; - - case CENTER_INSIDE: - if(isLandscape()) { - startingScale = fitScaleHorizontal; - } - else { - startingScale = fitScaleVertical; - } - break; - } - } - - protected boolean isRecycled() { - if(drawable != null && drawable instanceof BitmapDrawable) { - Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap(); - if(bitmap != null) { - return bitmap.isRecycled(); - } - } - return false; - } - - protected void recycle() { - if(recycle && drawable != null && drawable instanceof BitmapDrawable) { - Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap(); - if(bitmap != null) { - bitmap.recycle(); - } - } - } - - @Override - protected void onDraw(Canvas canvas) { - if(layout) { - if(drawable != null && !isRecycled()) { - canvas.save(); - - float adjustedScale = scale * scaleAdjust; - - canvas.translate(x, y); - - if(rotation != 0.0f) { - canvas.rotate(rotation); - } - - if(adjustedScale != 1.0f) { - canvas.scale(adjustedScale, adjustedScale); - } - - drawable.draw(canvas); - - canvas.restore(); - } - - if(drawLock.availablePermits() <= 0) { - drawLock.release(); - } - } - } - - /** - * Waits for a draw - * @param max time to wait for draw (ms) - * @throws InterruptedException - */ - public boolean waitForDraw(long timeout) throws InterruptedException { - return drawLock.tryAcquire(timeout, TimeUnit.MILLISECONDS); - } - - @Override - protected void onAttachedToWindow() { - animator = new Animator(this, "GestureImageViewAnimator"); - animator.start(); - - if(resId >= 0 && drawable == null) { - setImageResource(resId); - } - - super.onAttachedToWindow(); - } - - public void animationStart(Animation animation) { - if(animator != null) { - animator.play(animation); - } - } - - public void animationStop() { - if(animator != null) { - animator.cancel(); - } - } - - @Override - protected void onDetachedFromWindow() { - if(animator != null) { - animator.finish(); - } - if(recycle && drawable != null && !isRecycled()) { - recycle(); - drawable = null; - } - super.onDetachedFromWindow(); - } - - protected void initImage() { - if(this.drawable != null) { - this.drawable.setAlpha(alpha); - this.drawable.setFilterBitmap(true); - if(colorFilter != null) { - this.drawable.setColorFilter(colorFilter); - } - } - - if(!layout) { - requestLayout(); - redraw(); - } - } - - public void setImageBitmap(Bitmap image) { - this.drawable = new BitmapDrawable(getResources(), image); - initImage(); - } - - @Override - public void setImageDrawable(Drawable drawable) { - this.drawable = drawable; - initImage(); - } - - public void setImageResource(int id) { - if(this.drawable != null) { - this.recycle(); - } - if(id >= 0) { - this.resId = id; - setImageDrawable(getContext().getResources().getDrawable(id)); - } - } - - public int getScaledWidth() { - return Math.round(getImageWidth() * getScale()); - } - - public int getScaledHeight() { - return Math.round(getImageHeight() * getScale()); - } - - public int getImageWidth() { - if(drawable != null) { - return drawable.getIntrinsicWidth(); - } - return 0; - } - - public int getImageHeight() { - if(drawable != null) { - return drawable.getIntrinsicHeight(); - } - return 0; - } - - public void moveBy(float x, float y) { - this.x += x; - this.y += y; - } - - public void setPosition(float x, float y) { - this.x = x; - this.y = y; - } - - public void redraw() { - postInvalidate(); - } - - public void setMinScale(float min) { - this.minScale = min; - if(gestureImageViewTouchListener != null) { - gestureImageViewTouchListener.setMinScale(min * fitScaleHorizontal); - } - } - - public void setMaxScale(float max) { - this.maxScale = max; - if(gestureImageViewTouchListener != null) { - gestureImageViewTouchListener.setMaxScale(max * startingScale); - } - } - - public void setScale(float scale) { - scaleAdjust = scale; - } - - public float getScale() { - return scaleAdjust; - } - - public float getImageX() { - return x; - } - - public float getImageY() { - return y; - } - - public boolean isStrict() { - return strict; - } - - public void setStrict(boolean strict) { - this.strict = strict; - } - - public boolean isRecycle() { - return recycle; - } - - public void setRecycle(boolean recycle) { - this.recycle = recycle; - } - - public void reset() { - x = centerX; - y = centerY; - scaleAdjust = startingScale; - redraw(); - } - - public void setRotation(float rotation) { - this.rotation = rotation; - } - - public void setGestureImageViewListener(GestureImageViewListener pinchImageViewListener) { - this.gestureImageViewListener = pinchImageViewListener; - } - - public GestureImageViewListener getGestureImageViewListener() { - return gestureImageViewListener; - } - - @Override - public Drawable getDrawable() { - return drawable; - } - - @Override - public void setAlpha(int alpha) { - this.alpha = alpha; - if(drawable != null) { - drawable.setAlpha(alpha); - } - } - - @Override - public void setColorFilter(ColorFilter cf) { - this.colorFilter = cf; - if(drawable != null) { - drawable.setColorFilter(cf); - } - } - - @Override - public void setImageURI(Uri mUri) { - if ("content".equals(mUri.getScheme())) { - try { - String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION}; - - Cursor cur = getContext().getContentResolver().query(mUri, orientationColumn, null, null, null); - - if (cur != null && cur.moveToFirst()) { - imageOrientation = cur.getInt(cur.getColumnIndex(orientationColumn[0])); - } - - InputStream in = null; - - try { - in = getContext().getContentResolver().openInputStream(mUri); - Bitmap bmp = BitmapFactory.decodeStream(in); - - if(imageOrientation != 0) { - Matrix m = new Matrix(); - m.postRotate(imageOrientation); - Bitmap rotated = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true); - bmp.recycle(); - setImageDrawable(new BitmapDrawable(getResources(), rotated)); - } - else { - setImageDrawable(new BitmapDrawable(getResources(), bmp)); - } - } - finally { - if(in != null) { - in.close(); - } - - if(cur != null) { - cur.close(); - } - } - } - catch (Exception e) { - Log.w("GestureImageView", "Unable to open content: " + mUri, e); - } - } - else { - setImageDrawable(Drawable.createFromPath(mUri.toString())); - } - - if (drawable == null) { - Log.e("GestureImageView", "resolveUri failed on bad bitmap uri: " + mUri); - // Don't try again. - mUri = null; - } - } - - @Override - public Matrix getImageMatrix() { - if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - return super.getImageMatrix(); - } - - @Override - public void setScaleType(ScaleType scaleType) { - if(scaleType == ScaleType.CENTER || - scaleType == ScaleType.CENTER_CROP || - scaleType == ScaleType.CENTER_INSIDE) { - - super.setScaleType(scaleType); - } - else if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - } - - @Override - public void invalidateDrawable(Drawable dr) { - if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - super.invalidateDrawable(dr); - } - - @Override - public int[] onCreateDrawableState(int extraSpace) { - if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - return super.onCreateDrawableState(extraSpace); - } - - @Override - public void setAdjustViewBounds(boolean adjustViewBounds) { - if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - super.setAdjustViewBounds(adjustViewBounds); - } - - @Override - public void setImageLevel(int level) { - if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - super.setImageLevel(level); - } - - @Override - public void setImageMatrix(Matrix matrix) { - if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - } - - @Override - public void setImageState(int[] state, boolean merge) { - if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - } - - @Override - public void setSelected(boolean selected) { - if(strict) { - throw new UnsupportedOperationException("Not supported"); - } - super.setSelected(selected); - } - - @Override - public void setOnTouchListener(OnTouchListener l) { - this.customOnTouchListener = l; - } - - public float getCenterX() { - return centerX; - } - - public float getCenterY() { - return centerY; - } - - public boolean isLandscape() { - return getImageWidth() >= getImageHeight(); - } - - public boolean isPortrait() { - return getImageWidth() <= getImageHeight(); - } - - public void setStartingScale(float startingScale) { - this.startingScale = startingScale; - } - - public void setStartingPosition(float x, float y) { - this.startX = x; - this.startY = y; - } - - @Override - public void setOnClickListener(OnClickListener l) { - this.onClickListener = l; - - if(gestureImageViewTouchListener != null) { - gestureImageViewTouchListener.setOnClickListener(l); - } - } - - /** - * Returns true if the image dimensions are aligned with the orientation of the device. - * @return - */ - public boolean isOrientationAligned() { - if(deviceOrientation == Configuration.ORIENTATION_LANDSCAPE) { - return isLandscape(); - } - else if(deviceOrientation == Configuration.ORIENTATION_PORTRAIT) { - return isPortrait(); - } - return true; - } - - public int getDeviceOrientation() { - return deviceOrientation; - } -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/GestureImageViewListener.java b/android/experimental/DocumentLoader/src/com/polites/android/GestureImageViewListener.java deleted file mode 100644 index 487620a7c225..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/GestureImageViewListener.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -public interface GestureImageViewListener { - - public void onTouch(float x, float y); - - public void onScale(float scale); - - public void onPosition(float x, float y); - -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/GestureImageViewTouchListener.java b/android/experimental/DocumentLoader/src/com/polites/android/GestureImageViewTouchListener.java deleted file mode 100644 index f39840b60a79..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/GestureImageViewTouchListener.java +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -import android.content.res.Configuration; -import android.graphics.PointF; -import android.view.GestureDetector; -import android.view.GestureDetector.SimpleOnGestureListener; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnTouchListener; - -public class GestureImageViewTouchListener implements OnTouchListener { - - private GestureImageView image; - private OnClickListener onClickListener; - - private final PointF current = new PointF(); - private final PointF last = new PointF(); - private final PointF next = new PointF(); - private final PointF midpoint = new PointF(); - - private final VectorF scaleVector = new VectorF(); - private final VectorF pinchVector = new VectorF(); - - private boolean touched = false; - private boolean inZoom = false; - - private float initialDistance; - private float lastScale = 1.0f; - private float currentScale = 1.0f; - - private float boundaryLeft = 0; - private float boundaryTop = 0; - private float boundaryRight = 0; - private float boundaryBottom = 0; - - private float maxScale = 5.0f; - private float minScale = 0.25f; - private float fitScaleHorizontal = 1.0f; - private float fitScaleVertical = 1.0f; - - private int canvasWidth = 0; - private int canvasHeight = 0; - - private float centerX = 0; - private float centerY = 0; - - private float startingScale = 0; - - private boolean canDragX = false; - private boolean canDragY = false; - - private boolean multiTouch = false; - - private int displayWidth; - private int displayHeight; - - private int imageWidth; - private int imageHeight; - - private FlingListener flingListener; - private FlingAnimation flingAnimation; - private ZoomAnimation zoomAnimation; - private MoveAnimation moveAnimation; - private GestureDetector tapDetector; - private GestureDetector flingDetector; - private GestureImageViewListener imageListener; - - class FlingListener extends SimpleOnGestureListener { - - private float velocityX; - private float velocityY; - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - this.velocityX = velocityX; - this.velocityY = velocityY; - if (image.overflowGestureListener != null && !canDragX && !canDragY) { - return image.overflowGestureListener.onFling(e1, e2, velocityX, velocityY); - } - - return true; - } - - public float getVelocityX() { - return velocityX; - } - - public float getVelocityY() { - return velocityY; - } - } - - public GestureImageViewTouchListener(final GestureImageView image, int displayWidth, int displayHeight) { - super(); - - this.image = image; - - this.displayWidth = displayWidth; - this.displayHeight = displayHeight; - - this.centerX = (float) displayWidth / 2.0f; - this.centerY = (float) displayHeight / 2.0f; - - this.imageWidth = image.getImageWidth(); - this.imageHeight = image.getImageHeight(); - - startingScale = image.getScale(); - - currentScale = startingScale; - lastScale = startingScale; - - boundaryRight = displayWidth; - boundaryBottom = displayHeight; - boundaryLeft = 0; - boundaryTop = 0; - - next.x = image.getImageX(); - next.y = image.getImageY(); - - flingListener = new FlingListener(); - flingAnimation = new FlingAnimation(); - zoomAnimation = new ZoomAnimation(); - moveAnimation = new MoveAnimation(); - - flingAnimation.setListener(new FlingAnimationListener() { - @Override - public void onMove(float x, float y) { - handleDrag(current.x + x, current.y + y); - } - - @Override - public void onComplete() {} - }); - - zoomAnimation.setZoom(2.0f); - zoomAnimation.setZoomAnimationListener(new ZoomAnimationListener() { - @Override - public void onZoom(float scale, float x, float y) { - if(scale <= maxScale && scale >= minScale) { - handleScale(scale, x, y); - } - } - - @Override - public void onComplete() { - inZoom = false; - handleUp(); - } - }); - - moveAnimation.setMoveAnimationListener(new MoveAnimationListener() { - - @Override - public void onMove(float x, float y) { - image.setPosition(x, y); - image.redraw(); - } - }); - - tapDetector = new GestureDetector(image.getContext(), new SimpleOnGestureListener() { - @Override - public boolean onDoubleTap(MotionEvent e) { - startZoom(e); - return true; - } - - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - if(!inZoom) { - if(onClickListener != null) { - onClickListener.onClick(image); - return true; - } - } - - return false; - } - }); - - flingDetector = new GestureDetector(image.getContext(), flingListener); - imageListener = image.getGestureImageViewListener(); - - calculateBoundaries(); - } - - private void startFling() { - flingAnimation.setVelocityX(flingListener.getVelocityX()); - flingAnimation.setVelocityY(flingListener.getVelocityY()); - image.animationStart(flingAnimation); - } - - private void startZoom(MotionEvent e) { - inZoom = true; - zoomAnimation.reset(); - - float zoomTo = 1.0f; - - if(image.isLandscape()) { - if(image.getDeviceOrientation() == Configuration.ORIENTATION_PORTRAIT) { - int scaledHeight = image.getScaledHeight(); - - if(scaledHeight < canvasHeight) { - zoomTo = fitScaleVertical / currentScale; - zoomAnimation.setTouchX(e.getX()); - zoomAnimation.setTouchY(image.getCenterY()); - } - else { - zoomTo = fitScaleHorizontal / currentScale; - zoomAnimation.setTouchX(image.getCenterX()); - zoomAnimation.setTouchY(image.getCenterY()); - } - } - else { - int scaledWidth = image.getScaledWidth(); - - if(scaledWidth == canvasWidth) { - zoomTo = currentScale*4.0f; - zoomAnimation.setTouchX(e.getX()); - zoomAnimation.setTouchY(e.getY()); - } - else if(scaledWidth < canvasWidth) { - zoomTo = fitScaleHorizontal / currentScale; - zoomAnimation.setTouchX(image.getCenterX()); - zoomAnimation.setTouchY(e.getY()); - } - else { - zoomTo = fitScaleHorizontal / currentScale; - zoomAnimation.setTouchX(image.getCenterX()); - zoomAnimation.setTouchY(image.getCenterY()); - } - } - } - else { - if(image.getDeviceOrientation() == Configuration.ORIENTATION_PORTRAIT) { - - int scaledHeight = image.getScaledHeight(); - - if(scaledHeight == canvasHeight) { - zoomTo = currentScale*4.0f; - zoomAnimation.setTouchX(e.getX()); - zoomAnimation.setTouchY(e.getY()); - } - else if(scaledHeight < canvasHeight) { - zoomTo = fitScaleVertical / currentScale; - zoomAnimation.setTouchX(e.getX()); - zoomAnimation.setTouchY(image.getCenterY()); - } - else { - zoomTo = fitScaleVertical / currentScale; - zoomAnimation.setTouchX(image.getCenterX()); - zoomAnimation.setTouchY(image.getCenterY()); - } - } - else { - int scaledWidth = image.getScaledWidth(); - - if(scaledWidth < canvasWidth) { - zoomTo = fitScaleHorizontal / currentScale; - zoomAnimation.setTouchX(image.getCenterX()); - zoomAnimation.setTouchY(e.getY()); - } - else { - zoomTo = fitScaleVertical / currentScale; - zoomAnimation.setTouchX(image.getCenterX()); - zoomAnimation.setTouchY(image.getCenterY()); - } - } - } - - zoomAnimation.setZoom(zoomTo); - image.animationStart(zoomAnimation); - } - - - private void stopAnimations() { - image.animationStop(); - } - - @Override - public boolean onTouch(View v, MotionEvent event) { - - if(!inZoom) { - - if(!tapDetector.onTouchEvent(event)) { - if(event.getPointerCount() == 1 && flingDetector.onTouchEvent(event)) { - startFling(); - } - - if(event.getAction() == MotionEvent.ACTION_UP) { - handleUp(); - } - else if(event.getAction() == MotionEvent.ACTION_DOWN) { - stopAnimations(); - - last.x = event.getX(); - last.y = event.getY(); - - if(imageListener != null) { - imageListener.onTouch(last.x, last.y); - } - - touched = true; - } - else if(event.getAction() == MotionEvent.ACTION_MOVE) { - if(event.getPointerCount() > 1) { - multiTouch = true; - if(initialDistance > 0) { - - pinchVector.set(event); - pinchVector.calculateLength(); - - float distance = pinchVector.length; - - if(initialDistance != distance) { - - float newScale = (distance / initialDistance) * lastScale; - - if(newScale <= maxScale) { - scaleVector.length *= newScale; - - scaleVector.calculateEndPoint(); - - scaleVector.length /= newScale; - - float newX = scaleVector.end.x; - float newY = scaleVector.end.y; - - handleScale(newScale, newX, newY); - } - } - } - else { - initialDistance = MathUtils.distance(event); - - MathUtils.midpoint(event, midpoint); - - scaleVector.setStart(midpoint); - scaleVector.setEnd(next); - - scaleVector.calculateLength(); - scaleVector.calculateAngle(); - - scaleVector.length /= lastScale; - } - } - else { - if(!touched) { - touched = true; - last.x = event.getX(); - last.y = event.getY(); - next.x = image.getImageX(); - next.y = image.getImageY(); - } - else if(!multiTouch) { - if(handleDrag(event.getX(), event.getY())) { - image.redraw(); - } - } - } - } - } - } - - return true; - } - - protected void handleUp() { - - multiTouch = false; - - initialDistance = 0; - lastScale = currentScale; - - if(!canDragX) { - next.x = centerX; - } - - if(!canDragY) { - next.y = centerY; - } - - boundCoordinates(); - - if(!canDragX && !canDragY) { - - if(image.isLandscape()) { - currentScale = fitScaleHorizontal; - lastScale = fitScaleHorizontal; - } - else { - currentScale = fitScaleVertical; - lastScale = fitScaleVertical; - } - } - - image.setScale(currentScale); - image.setPosition(next.x, next.y); - - if(imageListener != null) { - imageListener.onScale(currentScale); - imageListener.onPosition(next.x, next.y); - } - - image.redraw(); - } - - protected void handleScale(float scale, float x, float y) { - - currentScale = scale; - - if(currentScale > maxScale) { - currentScale = maxScale; - } - else if (currentScale < minScale) { - currentScale = minScale; - } - else { - next.x = x; - next.y = y; - } - - calculateBoundaries(); - - image.setScale(currentScale); - image.setPosition(next.x, next.y); - - if(imageListener != null) { - imageListener.onScale(currentScale); - imageListener.onPosition(next.x, next.y); - } - - image.redraw(); - } - - protected boolean handleDrag(float x, float y) { - current.x = x; - current.y = y; - - float diffX = (current.x - last.x); - float diffY = (current.y - last.y); - - if(diffX != 0 || diffY != 0) { - - if(canDragX) next.x += diffX; - if(canDragY) next.y += diffY; - - boundCoordinates(); - - last.x = current.x; - last.y = current.y; - - if(canDragX || canDragY) { - image.setPosition(next.x, next.y); - - if(imageListener != null) { - imageListener.onPosition(next.x, next.y); - } - - return true; - } - } - - return false; - } - - public void reset() { - currentScale = startingScale; - next.x = centerX; - next.y = centerY; - calculateBoundaries(); - image.setScale(currentScale); - image.setPosition(next.x, next.y); - image.redraw(); - } - - - public float getMaxScale() { - return maxScale; - } - - public void setMaxScale(float maxScale) { - this.maxScale = maxScale; - } - - public float getMinScale() { - return minScale; - } - - public void setMinScale(float minScale) { - this.minScale = minScale; - } - - public void setOnClickListener(OnClickListener onClickListener) { - this.onClickListener = onClickListener; - } - - protected void setCanvasWidth(int canvasWidth) { - this.canvasWidth = canvasWidth; - } - - protected void setCanvasHeight(int canvasHeight) { - this.canvasHeight = canvasHeight; - } - - protected void setFitScaleHorizontal(float fitScale) { - this.fitScaleHorizontal = fitScale; - } - - protected void setFitScaleVertical(float fitScaleVertical) { - this.fitScaleVertical = fitScaleVertical; - } - - protected void boundCoordinates() { - if(next.x < boundaryLeft) { - next.x = boundaryLeft; - } - else if(next.x > boundaryRight) { - next.x = boundaryRight; - } - - if(next.y < boundaryTop) { - next.y = boundaryTop; - } - else if(next.y > boundaryBottom) { - next.y = boundaryBottom; - } - } - - protected void calculateBoundaries() { - - int effectiveWidth = Math.round( (float) imageWidth * currentScale ); - int effectiveHeight = Math.round( (float) imageHeight * currentScale ); - - canDragX = effectiveWidth > displayWidth; - canDragY = effectiveHeight > displayHeight; - - if(canDragX) { - float diff = (float)(effectiveWidth - displayWidth) / 2.0f; - boundaryLeft = centerX - diff; - boundaryRight = centerX + diff; - } - - if(canDragY) { - float diff = (float)(effectiveHeight - displayHeight) / 2.0f; - boundaryTop = centerY - diff; - boundaryBottom = centerY + diff; - } - } -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/MathUtils.java b/android/experimental/DocumentLoader/src/com/polites/android/MathUtils.java deleted file mode 100644 index df7f30db54a7..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/MathUtils.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -import android.graphics.PointF; -import android.util.FloatMath; -import android.view.MotionEvent; - -public class MathUtils { - - public static float distance(MotionEvent event) { - float x = event.getX(0) - event.getX(1); - float y = event.getY(0) - event.getY(1); - return FloatMath.sqrt(x * x + y * y); - } - - public static float distance(PointF p1, PointF p2) { - float x = p1.x - p2.x; - float y = p1.y - p2.y; - return FloatMath.sqrt(x * x + y * y); - } - - public static float distance(float x1, float y1, float x2, float y2) { - float x = x1 - x2; - float y = y1 - y2; - return FloatMath.sqrt(x * x + y * y); - } - - public static void midpoint(MotionEvent event, PointF point) { - float x1 = event.getX(0); - float y1 = event.getY(0); - float x2 = event.getX(1); - float y2 = event.getY(1); - midpoint(x1, y1, x2, y2, point); - } - - public static void midpoint(float x1, float y1, float x2, float y2, PointF point) { - point.x = (x1 + x2) / 2.0f; - point.y = (y1 + y2) / 2.0f; - } - /** - * Rotates p1 around p2 by angle degrees. - * @param p1 - * @param p2 - * @param angle - */ - public void rotate(PointF p1, PointF p2, float angle) { - float px = p1.x; - float py = p1.y; - float ox = p2.x; - float oy = p2.y; - p1.x = (FloatMath.cos(angle) * (px-ox) - FloatMath.sin(angle) * (py-oy) + ox); - p1.y = (FloatMath.sin(angle) * (px-ox) + FloatMath.cos(angle) * (py-oy) + oy); - } - - public static float angle(PointF p1, PointF p2) { - return angle(p1.x, p1.y, p2.x, p2.y); - } - - public static float angle(float x1, float y1, float x2, float y2) { - return (float) Math.atan2(y2 - y1, x2 - x1); - } -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/MoveAnimation.java b/android/experimental/DocumentLoader/src/com/polites/android/MoveAnimation.java deleted file mode 100644 index 8cdebb61838a..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/MoveAnimation.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -public class MoveAnimation implements Animation { - - private boolean firstFrame = true; - - private float startX; - private float startY; - - private float targetX; - private float targetY; - private long animationTimeMS = 100; - private long totalTime = 0; - - private MoveAnimationListener moveAnimationListener; - - /* (non-Javadoc) - * @see com.polites.android.Animation#update(com.polites.android.GestureImageView, long) - */ - @Override - public boolean update(GestureImageView view, long time) { - totalTime += time; - - if(firstFrame) { - firstFrame = false; - startX = view.getImageX(); - startY = view.getImageY(); - } - - if(totalTime < animationTimeMS) { - - float ratio = (float) totalTime / animationTimeMS; - - float newX = ((targetX - startX) * ratio) + startX; - float newY = ((targetY - startY) * ratio) + startY; - - if(moveAnimationListener != null) { - moveAnimationListener.onMove(newX, newY); - } - - return true; - } - else { - if(moveAnimationListener != null) { - moveAnimationListener.onMove(targetX, targetY); - } - } - - return false; - } - - public void reset() { - firstFrame = true; - totalTime = 0; - } - - - public float getTargetX() { - return targetX; - } - - - public void setTargetX(float targetX) { - this.targetX = targetX; - } - - - public float getTargetY() { - return targetY; - } - - public void setTargetY(float targetY) { - this.targetY = targetY; - } - - public long getAnimationTimeMS() { - return animationTimeMS; - } - - public void setAnimationTimeMS(long animationTimeMS) { - this.animationTimeMS = animationTimeMS; - } - - public void setMoveAnimationListener(MoveAnimationListener moveAnimationListener) { - this.moveAnimationListener = moveAnimationListener; - } -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/MoveAnimationListener.java b/android/experimental/DocumentLoader/src/com/polites/android/MoveAnimationListener.java deleted file mode 100644 index 4574caa3a938..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/MoveAnimationListener.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -public interface MoveAnimationListener { - - public void onMove(float x, float y); - -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/VectorF.java b/android/experimental/DocumentLoader/src/com/polites/android/VectorF.java deleted file mode 100644 index 1ff4b19d7e4f..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/VectorF.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -import android.graphics.PointF; -import android.util.FloatMath; -import android.view.MotionEvent; - -public class VectorF { - - public float angle; - public float length; - - public final PointF start = new PointF(); - public final PointF end = new PointF(); - - public void calculateEndPoint() { - end.x = FloatMath.cos(angle) * length + start.x; - end.y = FloatMath.sin(angle) * length + start.y; - } - - public void setStart(PointF p) { - this.start.x = p.x; - this.start.y = p.y; - } - - public void setEnd(PointF p) { - this.end.x = p.x; - this.end.y = p.y; - } - - public void set(MotionEvent event) { - this.start.x = event.getX(0); - this.start.y = event.getY(0); - this.end.x = event.getX(1); - this.end.y = event.getY(1); - } - - public float calculateLength() { - length = MathUtils.distance(start, end); - return length; - } - - public float calculateAngle() { - angle = MathUtils.angle(start, end); - return angle; - } - - -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/ZoomAnimation.java b/android/experimental/DocumentLoader/src/com/polites/android/ZoomAnimation.java deleted file mode 100644 index c709a1b7b513..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/ZoomAnimation.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -import android.graphics.PointF; - -public class ZoomAnimation implements Animation { - - private boolean firstFrame = true; - - private float touchX; - private float touchY; - - private float zoom; - - private float startX; - private float startY; - private float startScale; - - private float xDiff; - private float yDiff; - private float scaleDiff; - - private long animationLengthMS = 200; - private long totalTime = 0; - - private ZoomAnimationListener zoomAnimationListener; - - /* (non-Javadoc) - * @see com.polites.android.Animation#update(com.polites.android.GestureImageView, long) - */ - @Override - public boolean update(GestureImageView view, long time) { - if(firstFrame) { - firstFrame = false; - - startX = view.getImageX(); - startY = view.getImageY(); - startScale = view.getScale(); - scaleDiff = (zoom * startScale) - startScale; - - if(scaleDiff > 0) { - // Calculate destination for midpoint - VectorF vector = new VectorF(); - - // Set the touch point as start because we want to move the end - vector.setStart(new PointF(touchX, touchY)); - vector.setEnd(new PointF(startX, startY)); - - vector.calculateAngle(); - - // Get the current length - float length = vector.calculateLength(); - - // Multiply length by zoom to get the new length - vector.length = length*zoom; - - // Now deduce the new endpoint - vector.calculateEndPoint(); - - xDiff = vector.end.x - startX; - yDiff = vector.end.y - startY; - } - else { - // Zoom out to center - xDiff = view.getCenterX() - startX; - yDiff = view.getCenterY() - startY; - } - } - - totalTime += time; - - float ratio = (float) totalTime / (float) animationLengthMS; - - if(ratio < 1) { - - if(ratio > 0) { - // we still have time left - float newScale = (ratio * scaleDiff) + startScale; - float newX = (ratio * xDiff) + startX; - float newY = (ratio * yDiff) + startY; - - if(zoomAnimationListener != null) { - zoomAnimationListener.onZoom(newScale, newX, newY); - } - } - - return true; - } - else { - - float newScale = scaleDiff + startScale; - float newX = xDiff + startX; - float newY = yDiff + startY; - - if(zoomAnimationListener != null) { - zoomAnimationListener.onZoom(newScale, newX, newY); - zoomAnimationListener.onComplete(); - } - - return false; - } - } - - public void reset() { - firstFrame = true; - totalTime = 0; - } - - public float getZoom() { - return zoom; - } - - public void setZoom(float zoom) { - this.zoom = zoom; - } - - public float getTouchX() { - return touchX; - } - - public void setTouchX(float touchX) { - this.touchX = touchX; - } - - public float getTouchY() { - return touchY; - } - - public void setTouchY(float touchY) { - this.touchY = touchY; - } - - public long getAnimationLengthMS() { - return animationLengthMS; - } - - public void setAnimationLengthMS(long animationLengthMS) { - this.animationLengthMS = animationLengthMS; - } - - public ZoomAnimationListener getZoomAnimationListener() { - return zoomAnimationListener; - } - - public void setZoomAnimationListener(ZoomAnimationListener zoomAnimationListener) { - this.zoomAnimationListener = zoomAnimationListener; - } -} diff --git a/android/experimental/DocumentLoader/src/com/polites/android/ZoomAnimationListener.java b/android/experimental/DocumentLoader/src/com/polites/android/ZoomAnimationListener.java deleted file mode 100644 index 21b6ec9a6fb0..000000000000 --- a/android/experimental/DocumentLoader/src/com/polites/android/ZoomAnimationListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2012 Jason Polites - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.polites.android; - -public interface ZoomAnimationListener { - public void onZoom(float scale, float x, float y); - public void onComplete(); -} diff --git a/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java b/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java deleted file mode 100644 index a7a2214e792f..000000000000 --- a/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java +++ /dev/null @@ -1,1140 +0,0 @@ -// -*- 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/. - -// This is just a testbed for ideas and implementations. (Still, it might turn -// out to be somewhat useful as such while waiting for "real" apps.) - -// Important points: - -// Everything that might take a long time should be done asynchronously: -// - loading the document (loadComponentFromURL()) -// - counting number of pages (getRendererCount()) -// - rendering a page (render()) - -// Unclear whether pages can be rendered in parallel. Probably best to -// serialize all the above in the same worker thread. We use -// AsyncTask.SERIAL_EXECUTOR below. - -// While a page is loading ideally should display some animated spinner (but -// for now just a static "please wait" text). - -// === - -// How should we handle re-rendering at higher resolution when zooming in, and -// then panning around? - -// Hopefully when LO is asked to render just a part of a page (i.e. the -// MapMode of the device rendered to causes significant parts of the page to -// be outside the device) the code is clever enough to quickly skip stuff that -// will be clipped. But I don't hold my breath. - -// How could we do it? - -// 1/ Re-render just the zoomed-in area. Probably not a good idea, as probably -// the user will almost immediately also pan a bit or zoom out a bit, which -// would cause a re-render. - -// 2/ Some kind of tiled approach. Initially just one tile for the whole -// page. When zooming in, at some point (2x?) split the currently visible -// tiles into four sub-tiles, each initially displaying the same resolution as -// the parent tile. Start asynchronous rendering of visible sub-tiles at -// double resolution. Keep the "parent" rendered bitmap but don't keep bitmaps -// that go out of view. (Except perhaps for some caching.) When zooming out, -// at some point (0.5x?) merge four sub-tiles back into one. Hmm. Is this the -// right approach? - -// In any case, also this rendering at higher resolution should be done -// asynchronously, of course. If the user zooms in and pans around, the -// existing bitmap will be shown scaled (and ugly) until required rendering -// has finished and then the affected tiles are replaced with -// higher-resolution ones. - -package org.libreoffice.android.examples; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.Matrix; -import android.graphics.PixelFormat; -import android.graphics.Paint; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.os.Bundle; -import android.util.Log; -import android.view.GestureDetector; -import android.view.Gravity; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.AnimationSet; -import android.view.animation.TranslateAnimation; -import android.widget.ImageView; -import android.widget.NumberPicker; -import android.widget.TextView; -import android.widget.ViewFlipper; -import android.widget.ViewSwitcher; - -import junit.framework.Assert; - -import com.polites.android.GestureImageView; - -import com.sun.star.awt.Size; -import com.sun.star.awt.XBitmap; -import com.sun.star.awt.XControl; -import com.sun.star.awt.XDevice; -import com.sun.star.awt.XToolkitExperimental; -import com.sun.star.beans.PropertyValue; -import com.sun.star.frame.XComponentLoader; -import com.sun.star.frame.XController; -import com.sun.star.frame.XFrame; -import com.sun.star.frame.XModel; -import com.sun.star.lang.XEventListener; -import com.sun.star.lang.XMultiComponentFactory; -import com.sun.star.lang.XTypeProvider; -import com.sun.star.uno.Type; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XComponentContext; -import com.sun.star.view.XRenderable; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; - -import org.libreoffice.android.Bootstrap; - -public class DocumentLoader - extends Activity -{ - private static final String TAG = "DocumentLoader"; - - // Size of a small virtual (bitmap) device used to find out page count and - // page sizes - private static final int SMALLSIZE = 128; - - // We pre-render this many pages preceding and succeeding the currently - // viewed one, i.e. the total number of rendered pages kept is - // PAGECACHE_PLUSMINUS*2+1. - private static final int PAGECACHE_PLUSMINUS = 2; - private static final int PAGECACHE_SIZE = PAGECACHE_PLUSMINUS*2 + 1; - - BootstrapContext bootstrapContext; - DocumentContext documentContext; - - GestureDetector.OnGestureListener gestureListener; - GestureDetector gestureDetector; - - ViewGroup.LayoutParams matchParent; - - ViewFlipper flipper; - - Bundle extras; - - PageViewer getPageViewerAt(int index) - { - return (PageViewer)flipper.getChildAt(index); - } - - PageViewer getCurrentPageViewer() - { - return (PageViewer)flipper.getCurrentView(); - } - - class GestureListener - extends GestureDetector.SimpleOnGestureListener - { - @Override - public boolean onFling(MotionEvent event1, - MotionEvent event2, - float velocityX, - float velocityY) - { - Log.i(TAG, "onFling: " + event1 + " " + event2); - if (event1.getX() - event2.getX() > 120) { - if (getCurrentPageViewer().currentPageNumber == documentContext.pageCount-1) - return false; - - Animation inFromRight = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 0, - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0); - int duration = Math.abs((int)((float)flipper.getWidth()/velocityX*1000f)); - inFromRight.setDuration(duration); - flipper.setInAnimation(inFromRight); - - Animation outToLeft = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -1, - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0); - outToLeft.setDuration(duration); - flipper.setOutAnimation(outToLeft); - - flipper.showNext(); - - // The entry after the next, both child index and next is 0..PAGECACHE_SIZE. - int next = (flipper.getDisplayedChild() + PAGECACHE_PLUSMINUS) % PAGECACHE_SIZE; - getPageViewerAt(next).display(getCurrentPageViewer().currentPageNumber + PAGECACHE_PLUSMINUS); - return true; - } else if (event2.getX() - event1.getX() > 120) { - if (getCurrentPageViewer().currentPageNumber == 0) - return false; - - Animation inFromLeft = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -1, Animation.RELATIVE_TO_SELF, 0, - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0); - int duration = Math.abs((int)((float)flipper.getWidth()/velocityX*1000f)); - inFromLeft.setDuration(duration); - flipper.setInAnimation(inFromLeft); - - Animation outToRight = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1, - Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0); - outToRight.setDuration(duration); - flipper.setOutAnimation(outToRight); - - flipper.showPrevious(); - - // The entry before the previous, both child index and previous is 0..PAGECACHE_SIZE. - int previous = (flipper.getDisplayedChild() + PAGECACHE_SIZE - PAGECACHE_PLUSMINUS) % PAGECACHE_SIZE; - getPageViewerAt(previous).display(getCurrentPageViewer().currentPageNumber - PAGECACHE_PLUSMINUS); - - return true; - } - return false; - } - } - - class MyXController - implements XController - { - - XFrame frame; - XModel model; - - public void attachFrame(XFrame frame) - { - Log.i(TAG, "attachFrame"); - this.frame = frame; - } - - public boolean attachModel(XModel model) - { - Log.i(TAG, "attachModel"); - this.model = model; - return true; - } - - public boolean suspend(boolean doSuspend) - { - Log.i(TAG, "suspend"); - return false; - } - - public Object getViewData() - { - Log.i(TAG, "getViewData"); - return null; - } - - public void restoreViewData(Object data) - { - Log.i(TAG, "restoreViewData"); - } - - public XModel getModel() - { - Log.i(TAG, "getModel"); - return model; - } - - public XFrame getFrame() - { - Log.i(TAG, "getFrame"); - return frame; - } - - public void dispose() - { - Log.i(TAG, "dispose"); - } - - public void addEventListener(XEventListener listener) - { - Log.i(TAG, "addEventListener"); - } - - public void removeEventListener(XEventListener listener) - { - Log.i(TAG, "removeEventListener"); - } - } - - static int zoomLevel(float scale) - { - if (scale <= 1) - return 0; - - int result = 1; - int power = 2; - - while (scale > power) { - result++; - power *= 2; - } - return result; - } - - static int scaleOfZoom(int zoom) - { - int result = 1; - - while (zoom > 0) { - result *= 2; - zoom--; - } - - return result; - } - - static int setColorAlpha(int color, - double alpha) - { - return Color.argb((int)(alpha*255), Color.red(color), Color.green(color), Color.blue(color)); - } - - // Each (Gesture)ImageView is showing an object of this subclass of - // BitmapDrawable, the root of a quadtree of higher-resolution partial - // page bitmaps. Obviously these should be rendered asynchronously on - // demand but that code is not here yet. And anyway, rendering partial - // pages won't work until I have figured out why offsetting VirtualDevice - // has no effect. - class QuadTree - extends BitmapDrawable - { - final int pageNumber; - final int level; - final int location; - final int w, h; - - static final int NW = 0; - static final int NE = 1; - static final int SE = 2; - static final int SW = 3; - - QuadTree sub[] = new QuadTree[4]; - - QuadTree(Bitmap bm, - int level, - int pageNumber, - int location) - { - super(bm); - - w = getIntrinsicWidth(); - h = getIntrinsicHeight(); - - this.pageNumber = pageNumber; - this.level = level; - this.location = location; - - // I spent several days wondering why nothing showed up for the - // sub-tiles, desperately tweaking stuff left and right, until I - // found out I need to call setBounds()... (For the level 0 - // drawable the GestureImageView handles calling setBounds(), but - // it doesn't hurt to do it here for all levels.) - setBounds(0, 0, w, h); - - // Just for testing until properly doing this asynchronously and - // with insert() - if (level == 0) { - // Don't do it anyway for now - - // 1) offsetting of VirtualDevice doesn't seem to work so this - // would work for the NW sub-tile only anyway. - - // 2) LO renders Windows-style "Y grows upwards" bitmaps, thus - // the imageView.setScaleY(-1) below in - // PageLoadTask.onPostExecute(), but that means that the - // scaling and translation stuff here in QuadTree needs to be - // twiddled for Y coordinates. (Just try: comment out the - // createSub(NW) call below. If you also comment out the - // setScaleY() call, the sub-tile will show up in the correct - // location, otherwise not. Or something like that. It's hard - // to try to write up sevral nights of desperate hacking back - // and forth... which in the end turned out to be just chasing - // the wrong ducks. If that is how the metaphor goes?) - - // So probably should write a native method to reflect the - // rendered byte buffer in the Y direction, and call that - // after rendering, instead? Or maybe the tweaks needed aren't - // that large anyway, and I just am mixing up my memory of the - // trouble caused by that with the trouble caused by not - // calling setBounds()... - - //createSub(NW); - //createSub(NE); - //createSub(SE); - //createSub(SW); - } - } - - QuadTree(QuadTree rhs, - Bitmap bm) - { - this(bm, rhs.level, rhs.pageNumber, rhs.location); - - sub = rhs.sub; - } - - QuadTree(Bitmap bm, - int pageNumber) - { - this(bm, 0, pageNumber, 0); - } - - QuadTree(int level, - int pageNumber, - int location) - { - this.level = level; - this.pageNumber = pageNumber; - this.location = location; - w = -1; - h = -1; - } - - void createSub(int q) - { - if (true) { - ByteBuffer bb = renderPage(pageNumber, level+1, (location<<2)+q); - Bitmap subbm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - subbm.copyPixelsFromBuffer(bb); - sub[q] = new QuadTree(subbm, level+1, pageNumber, (location<<2)+q); - } else { - // Test... just use transparent single colour subtiles - Bitmap subbm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - int color = 0; - switch (q) { - case NW: color = Color.RED; break; - case NE: color = Color.GREEN; break; - case SE: color = Color.BLUE; break; - case SW: color = Color.YELLOW; break; - } - subbm.eraseColor(setColorAlpha(color, 0.5)); - sub[q] = new QuadTree(subbm, 1, pageNumber, (location<<2)+q); - } - } - - int quadrantOf(int x, - int y) - { - if (x < 0 || y < 0 || x >= w || y >= h) - return -1; - - if (x < w/2 && y < h/2) - return NW; - if (x >= w/2 && y < h/2) - return NE; - if (x >= w/2 && y >= h/2) - return SE; - if (x < w/2 && y >= h/2) - return SW; - - return -1; - } - - int quadrantOf(Point p) - { - return quadrantOf(p.x, p.y); - } - - Point subCoord(Point p) - { - return subCoord(quadrantOf(p), p); - } - - Point subCoord(int q, - Point p) - { - switch (q) { - case NW: - return new Point(p.x*2, p.y*2); - case NE: - return new Point((p.x-w/2)*2, p.y*2); - case SE: - return new Point((p.x-w/2)*2, (p.y-h/2)*2); - case SW: - return new Point(p.x*2, (p.y-h/2)*2); - } - return null; - } - - // The insert() stuff has not been tested and is just a draft - void insert(Bitmap bm, - int level, - int x, - int y) - { - insert(bm, level, 1, new Point(x, y)); - } - - void insert(Bitmap bm, - int level, - int recursionDepth, - Point p) - { - int q = quadrantOf(p); - - if (q == -1) - return; - - if (recursionDepth == level) { - if (sub[q] == null) - sub[q] = new QuadTree(bm, level); - else - sub[q] = new QuadTree(sub[q], bm); - } else { - if (sub[q] == null) - sub[q] = new QuadTree(this.level+1, pageNumber, location); - sub[q].insert(bm, level, recursionDepth+1, subCoord(q, p)); - } - } - - // Ditto for find() - - QuadTree find(int levelCountdown, - int x, - int y) - { - return find(levelCountdown, new Point(x, y)); - } - - QuadTree find(int levelCountdown, - Point p) - { - final int x = p.x, y = p.y; - - Log.i(TAG, "find(" + levelCountdown + ", (" + p.x + ", " + p.y + "))"); - - if (x < 0 || y < 0 || x >= w || y >= h) - return null; - - if (levelCountdown == 0) { - Log.i(TAG, "Returning this at level " + this.level); - return this; - } - - int q = quadrantOf(p); - - if (sub[q] != null) - return sub[q].find(levelCountdown-1, subCoord(q, p)); - - return null; - } - - void subDraw(Canvas canvas, - int q) - { - if (q == -1 || sub[q] == null) - return; - - Log.i(TAG, "subDraw 1: q=" + q + ", matrix=" + canvas.getMatrix() + ", clip=" + canvas.getClipBounds()); - - canvas.save(); - canvas.scale(0.5f, 0.5f); - - float[] values = new float[9]; - canvas.getMatrix().getValues(values); - - Log.i(TAG, "subDraw 2: q=" + q + ", matrix=" + canvas.getMatrix() + ", clip=" + canvas.getClipBounds() + ", translate(" + - (((q == NW || q == SW) ? -w : w) /* * values[Matrix.MSCALE_X]*/) + "," + - (((q == NW || q == NE) ? -h : h) /* * values[Matrix.MSCALE_X]*/) + ")"); - - canvas.translate(((q == NW || q == SW) ? -w : 0) /* * values[Matrix.MSCALE_X]*/, - ((q == NW || q == NE) ? -h : 0) /* * values[Matrix.MSCALE_X]*/); - - Log.i(TAG, "subDraw 3: q=" + q + ", matrix=" + canvas.getMatrix() + ", clip=" + canvas.getClipBounds()); - - sub[q].draw(canvas); - - canvas.restore(); - } - - @Override - public void draw(Canvas canvas) - { - float[] values = new float[9]; - canvas.getMatrix().getValues(values); - - float scale = values[Matrix.MSCALE_X]; - int zoom = zoomLevel(scale); - - Log.i(TAG, "draw: level=" + level + ", scale=" + scale + ", zoom=" + zoom + ", matrix=" + canvas.getMatrix()); - Rect bounds = new Rect(); - if (canvas.getClipBounds(bounds)) - Log.i(TAG, " clip=" + bounds + ", bounds=" + getBounds()); - else - Log.i(TAG, " no clip"); - - int l = (int)(w/2 - values[Matrix.MTRANS_X]/scale); - int t = (int)(h/2 - values[Matrix.MTRANS_Y]/scale); - Log.i(TAG, "Unzoomed rect: " + l + ", " + t + ", " + (int)(l+w/scale) + ", " + (int)(t+h/scale)); - - Log.i(TAG, "Scales: " + values[Matrix.MSCALE_X] + ", " + values[Matrix.MSCALE_Y]); - - // Assert.assertTrue(values[Matrix.MSCALE_X] == values[Matrix.MSCALE_Y]); - - super.draw(canvas); - - if (/*zoom > 0 */ scale >= 1) { - subDraw(canvas, quadrantOf(l, t)); - subDraw(canvas, quadrantOf((int)(l+w/scale)-1, t)); - subDraw(canvas, quadrantOf((int)(l+w/scale)-1, (int)(t+h/scale)-1)); - subDraw(canvas, quadrantOf(l, (int)(t+h/scale)-1)); - } - } - } - - ByteBuffer renderPage(int number) - { - return renderPage(number, 0, 0); - } - - ByteBuffer renderPage(final int number, - final int level, - final int location) - { - Log.i(TAG, "renderPage(" + number + ", " + level + ", " + location + ")"); - try { - // Use dummySmallDevice with no scale or offset just to find out - // the paper size of this page. - - PropertyValue renderProps[] = new PropertyValue[3]; - renderProps[0] = new PropertyValue(); - renderProps[0].Name = "IsPrinter"; - renderProps[0].Value = Boolean.TRUE; - renderProps[1] = new PropertyValue(); - renderProps[1].Name = "RenderDevice"; - renderProps[1].Value = bootstrapContext.dummySmallDevice; - renderProps[2] = new PropertyValue(); - renderProps[2].Name = "View"; - renderProps[2].Value = new MyXController(); - - // getRenderer returns a set of properties that include the PageSize - long t0 = System.currentTimeMillis(); - PropertyValue rendererProps[] = documentContext.renderable.getRenderer(number, documentContext.doc, renderProps); - long t1 = System.currentTimeMillis(); - Log.i(TAG, "getRenderer took " + ((t1-t0)-bootstrapContext.timingOverhead) + " ms"); - - int pageWidth = 0, pageHeight = 0; - for (int i = 0; i < rendererProps.length; i++) { - if (rendererProps[i].Name.equals("PageSize")) { - pageWidth = ((Size) rendererProps[i].Value).Width; - pageHeight = ((Size) rendererProps[i].Value).Height; - Log.i(TAG, "PageSize: " + pageWidth + "x" + pageHeight); - } - } - - // Create a new device with the correct scale and offset - ByteBuffer bb = ByteBuffer.allocateDirect(flipper.getWidth()*flipper.getHeight()*4); - long wrapped_bb = Bootstrap.new_byte_buffer_wrapper(bb); - - XDevice device; - if (pageWidth == 0) { - // Huh? - device = bootstrapContext.toolkit.createScreenCompatibleDeviceUsingBuffer(flipper.getWidth(), flipper.getHeight(), 1, 1, 0, 0, wrapped_bb); - } else { - - // Scale so that it fits our device which has a resolution of - // 96/inch (see SvpSalGraphics::GetResolution()). The page - // size returned from getRenderer() is in 1/mm * 100. 2540 is - // one inch in mm/100. - - int scaleNumerator, scaleDenominator; - - // If the view has a wider aspect ratio than the page, fit - // height; otherwise, fit width - if ((double) flipper.getWidth() / flipper.getHeight() > (double) pageWidth / pageHeight) { - scaleNumerator = flipper.getHeight(); - scaleDenominator = pageHeight / 2540 * 96; - } else { - scaleNumerator = flipper.getWidth(); - scaleDenominator = pageWidth / 2540 * 96; - } - scaleNumerator *= scaleOfZoom(level); - - int xOffset = 0, yOffset = 0; - int hiX = pageWidth, hiY = pageHeight; - int lvl = level; - int loc = location; - while (lvl > 0) { - int q = (loc & 0x03); - - if (q == QuadTree.NE || q == QuadTree.SE) { - xOffset += (hiX - xOffset)/2; - } else { - hiX -= (hiX - xOffset)/2; - } - if (q == QuadTree.SW || q == QuadTree.SE) { - yOffset += (hiY - yOffset)/2; - } else { - hiY -= (hiY - yOffset)/2; - } - lvl--; - loc >>= 2; - } - - // Seems that the offsets passed in (which get passed to - // MapMode::SetOrigin() in - // VirtualDevice::SetOutputSizePixelScaleOffsetAndBuffer() - // are ignored... try a random value, no effect ;( - xOffset = 12345; xOffset = 789; - - Log.i(TAG, "Rendering page " + number + " level=" + level + " scale=" + scaleNumerator + "/" + scaleDenominator + ", offset=(" + xOffset + ", " + yOffset + ")"); - - device = bootstrapContext.toolkit.createScreenCompatibleDeviceUsingBuffer(flipper.getWidth(), flipper.getHeight(), - scaleNumerator, scaleDenominator, - -xOffset, -yOffset, - wrapped_bb); - } - - // Update the property that points to the device - renderProps[1].Value = device; - - t0 = System.currentTimeMillis(); - documentContext.renderable.render(number, documentContext.doc, renderProps); - t1 = System.currentTimeMillis(); - Log.i(TAG, "Rendering page " + number + " took " + ((t1-t0)-bootstrapContext.timingOverhead) + " ms"); - - Bootstrap.force_full_alpha_bb(bb, 0, flipper.getWidth() * flipper.getHeight() * 4); - - return bb; - } - catch (Exception e) { - e.printStackTrace(System.err); - finish(); - } - - return null; - } - - enum PageState { NONEXISTENT, LOADING, READY }; - - class PageViewer - extends ViewSwitcher - { - int currentPageNumber = -1; - TextView waitView; - PageState state = PageState.NONEXISTENT; - Bitmap bm; - - class PageLoadTask - extends AsyncTask<Integer, Void, Integer> - { - protected Integer doInBackground(Integer... params) - { - int number = params[0]; - - Log.i(TAG, "doInBackground(" + number + ")"); - - if (number >= documentContext.pageCount) - return -1; - - state = PageState.LOADING; - currentPageNumber = number; - ByteBuffer bb = renderPage(currentPageNumber); - bm = Bitmap.createBitmap(flipper.getWidth(), flipper.getHeight(), Bitmap.Config.ARGB_8888); - bm.copyPixelsFromBuffer(bb); - - return currentPageNumber; - } - - protected void onPostExecute(Integer result) - { - Log.i(TAG, "onPostExecute: " + result); - if (result == -1) - return; - - GestureImageView imageView = new GestureImageView(DocumentLoader.this, gestureListener); - imageView.setImageDrawable(new QuadTree(bm, result)); - - imageView.setScaleY(-1); - - if (getChildCount() == 2) - removeViewAt(1); - addView(imageView, 1, matchParent); - showNext(); - state = PageState.READY; - } - } - - void display(int number) - { - Log.i(TAG, "PageViewer display(" + number + ")"); - if (number >= 0) - waitView.setText("Page " + (number+1) + ", wait..."); - state = PageState.NONEXISTENT; - - if (getDisplayedChild() == 1) { - showPrevious(); - removeViewAt(1); - } - - if (number >= 0) { - new PageLoadTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, number); - } - } - - PageViewer(int number) - { - super(DocumentLoader.this); - - waitView = new TextView(DocumentLoader.this); - waitView.setTextSize(24); - waitView.setGravity(Gravity.CENTER); - waitView.setBackgroundColor(Color.WHITE); - waitView.setTextColor(Color.BLACK); - addView(waitView, 0, matchParent); - - display(number); - } - } - - class DocumentLoadTask - extends AsyncTask<String, Void, Void> - { - protected Void doInBackground(String... params) - { - try { - String url = params[0]; - Log.i(TAG, "Attempting to load " + url); - - PropertyValue loadProps[] = new PropertyValue[3]; - loadProps[0] = new PropertyValue(); - loadProps[0].Name = "Hidden"; - loadProps[0].Value = Boolean.TRUE; - loadProps[1] = new PropertyValue(); - loadProps[1].Name = "ReadOnly"; - loadProps[1].Value = Boolean.TRUE; - loadProps[2] = new PropertyValue(); - loadProps[2].Name = "Preview"; - loadProps[2].Value = Boolean.TRUE; - - long t0 = System.currentTimeMillis(); - documentContext.doc = bootstrapContext.componentLoader.loadComponentFromURL(url, "_blank", 0, loadProps); - long t1 = System.currentTimeMillis(); - Log.i(TAG, "Loading took " + ((t1-t0)-bootstrapContext.timingOverhead) + " ms"); - - documentContext.renderable = (XRenderable) UnoRuntime.queryInterface(XRenderable.class, documentContext.doc); - - PropertyValue renderProps[] = new PropertyValue[3]; - renderProps[0] = new PropertyValue(); - renderProps[0].Name = "IsPrinter"; - renderProps[0].Value = Boolean.TRUE; - renderProps[1] = new PropertyValue(); - renderProps[1].Name = "RenderDevice"; - renderProps[1].Value = bootstrapContext.dummySmallDevice; - renderProps[2] = new PropertyValue(); - renderProps[2].Name = "View"; - renderProps[2].Value = new MyXController(); - - t0 = System.currentTimeMillis(); - documentContext.pageCount = documentContext.renderable.getRendererCount(documentContext.doc, renderProps); - t1 = System.currentTimeMillis(); - Log.i(TAG, "getRendererCount: " + documentContext.pageCount + ", took " + ((t1-t0)-bootstrapContext.timingOverhead) + " ms"); - } - catch (Exception e) { - e.printStackTrace(System.err); - finish(); - } - return null; - } - } - - /** - * This class contains the state that is initialized once and never changes - * (not specific to a document or a view). - */ - class BootstrapContext - { - public long timingOverhead; - public XComponentContext componentContext; - public XMultiComponentFactory mcf; - public XComponentLoader componentLoader; - public XToolkitExperimental toolkit; - public XDevice dummySmallDevice; - } - - /** - * This class contains the state that is specific to a document, but - * independent from a view. - */ - class DocumentContext - { - public Object doc; - public int pageCount; - public XRenderable renderable; - public String input; - // This is not updated constantly, just in onRetainNonConfigurationInstance() - public int currentPageNumber; - } - - static void dumpUNOObject(String objectName, Object object) - { - Log.i(TAG, objectName + " is " + (object != null ? object.toString() : "null")); - - if (object == null) - return; - - XTypeProvider typeProvider = (XTypeProvider) - UnoRuntime.queryInterface(XTypeProvider.class, object); - if (typeProvider == null) - return; - - Type[] types = typeProvider.getTypes(); - if (types == null) - return; - - for (Type t : types) - Log.i(TAG, " " + t.getTypeName()); - } - - static void dumpBytes(String name, byte[] bytes, int offset) - { - if (bytes == null) { - Log.i(TAG, name + " is null"); - return; - } - Log.i(TAG, name + ":"); - - if (offset != 0) - Log.i(TAG, " (offset " + offset + ")"); - - for (int i = offset; i < Math.min(bytes.length, offset+160); i += 16) { - String s = ""; - for (int j = i; j < Math.min(bytes.length, i+16); j++) - s = s + String.format(" %02x", bytes[j]); - - Log.i(TAG, s); - } - } - - static void dumpBytes(String name, ByteBuffer bytes, int offset) - { - if (bytes == null) { - Log.i(TAG, name + " is null"); - return; - } - Log.i(TAG, name + ":"); - - if (offset != 0) - Log.i(TAG, " (offset " + offset + ")"); - - for (int i = offset; i < Math.min(bytes.limit(), offset+160); i += 16) { - String s = ""; - for (int j = i; j < Math.min(bytes.limit(), i+16); j++) - s = s + String.format(" %02x", bytes.get(j)); - - Log.i(TAG, s); - } - } - - @Override - public Object onRetainNonConfigurationInstance() { - ArrayList ret = new ArrayList(2); - ret.add(bootstrapContext); - documentContext.currentPageNumber = getCurrentPageViewer().currentPageNumber; - ret.add(documentContext); - return ret; - } - - private void initBootstrapContext() - { - try - { - bootstrapContext = new BootstrapContext(); - - long t0 = System.currentTimeMillis(); - long t1 = System.currentTimeMillis(); - bootstrapContext.timingOverhead = t1 - t0; - - Bootstrap.setup(this); - - // Avoid all the old style OSL_TRACE calls especially in vcl - Bootstrap.putenv("SAL_LOG=+WARN+INFO"); - - // Log.i(TAG, "Sleeping NOW"); - // Thread.sleep(20000); - - bootstrapContext.componentContext = com.sun.star.comp.helper.Bootstrap.defaultBootstrap_InitialComponentContext(); - - Log.i(TAG, "context is" + (bootstrapContext.componentContext!=null ? " not" : "") + " null"); - - bootstrapContext.mcf = bootstrapContext.componentContext.getServiceManager(); - - Log.i(TAG, "mcf is" + (bootstrapContext.mcf!=null ? " not" : "") + " null"); - - Bootstrap.initVCL(); - - Object desktop = bootstrapContext.mcf.createInstanceWithContext - ("com.sun.star.frame.Desktop", bootstrapContext.componentContext); - - Log.i(TAG, "desktop is" + (desktop!=null ? " not" : "") + " null"); - - bootstrapContext.componentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktop); - - Log.i(TAG, "componentLoader is" + (bootstrapContext.componentLoader!=null ? " not" : "") + " null"); - - Object toolkitService = bootstrapContext.mcf.createInstanceWithContext - ("com.sun.star.awt.Toolkit", bootstrapContext.componentContext); - bootstrapContext.toolkit = (XToolkitExperimental) UnoRuntime.queryInterface(XToolkitExperimental.class, toolkitService); - - // Set up dummySmallDevice and use it to find out the number - // of pages ("renderers"). - ByteBuffer smallbb = ByteBuffer.allocateDirect(SMALLSIZE*SMALLSIZE*4); - long wrapped_smallbb = Bootstrap.new_byte_buffer_wrapper(smallbb); - bootstrapContext.dummySmallDevice = bootstrapContext.toolkit.createScreenCompatibleDeviceUsingBuffer(SMALLSIZE, SMALLSIZE, 1, 1, 0, 0, wrapped_smallbb); - - } - catch (Exception e) - { - e.printStackTrace(System.err); - finish(); - } - } - - private void initDocumentContext(String input) - { - documentContext = new DocumentContext(); - documentContext.input = input; - // Load the wanted document - new DocumentLoadTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, "file://" + input); - } - - private void goToPage(int number) - { - // Remove old views. - flipper.removeAllViews(); - - // Add new ones. - flipper.addView(new PageViewer(number), 0, matchParent); - for (int i = 0; i < PAGECACHE_PLUSMINUS; i++) - flipper.addView(new PageViewer(number + i + 1), i + 1, matchParent); - for (int i = 0; i < PAGECACHE_PLUSMINUS; i++) - flipper.addView(new PageViewer(number + (i * -1) - 1), PAGECACHE_PLUSMINUS + i + 1, matchParent); - } - - private void askPageNumber() - { - AlertDialog.Builder alert = new AlertDialog.Builder(this); - alert.setTitle(R.string.go_to_page); - final NumberPicker input = new NumberPicker(this); - input.setMinValue(1); - input.setMaxValue(documentContext.pageCount); - alert.setView(input); - alert.setPositiveButton("OK", new DialogInterface.OnClickListener() - { - public void onClick(DialogInterface dialog, int whichButton) - { - goToPage(input.getValue() - 1); - } - }); - - alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() - { - public void onClick(DialogInterface dialog, int whichButton) - { - } - }); - alert.show(); - } - - @Override - public void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - ArrayList contexts = (ArrayList)getLastNonConfigurationInstance(); - if (contexts != null) - { - bootstrapContext = (BootstrapContext)contexts.get(0); - documentContext = (DocumentContext)contexts.get(1); - } - - extras = getIntent().getExtras(); - - gestureListener = new GestureListener(); - gestureDetector = new GestureDetector(this, gestureListener); - - try { - String input = getIntent().getStringExtra("input"); - if (input == null) - input = "/assets/test1.odt"; - - // We need to fake up an argv, and the argv[0] even needs to - // point to some file name that we can pretend is the "program". - // setCommandArgs() will prefix argv[0] with the app's data - // directory. - - String[] argv = { "lo-document-loader", input }; - - Bootstrap.setCommandArgs(argv); - - if (bootstrapContext == null) - initBootstrapContext(); - - if (documentContext == null || !documentContext.input.equals(input)) - initDocumentContext(input); - - flipper = new ViewFlipper(this); - - matchParent = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - - goToPage(documentContext.currentPageNumber); - - setContentView(flipper); - } - catch (Exception e) { - e.printStackTrace(System.err); - finish(); - } - } - - @Override - public boolean onTouchEvent(MotionEvent event) - { - return gestureDetector.onTouchEvent(event); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) - { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.option, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) - { - // Handle item selection - switch (item.getItemId()) { - case R.id.go_to_page: - askPageNumber(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } -} - -// vim:set shiftwidth=4 softtabstop=4 expandtab: |