0031619: Samples - update JNI sample to use Android Studio
authorkgv <kgv@opencascade.com>
Fri, 19 Jun 2020 23:14:51 +0000 (02:14 +0300)
committerkgv <kgv@opencascade.com>
Mon, 22 Jun 2020 06:19:06 +0000 (09:19 +0300)
Project structure and project files have been updated to use Android Studio 4.0, gradle and CMake.
Redundant OcctJni_Window has been replaced by Aspect_NeutralWindow.
SD Card permissions are not dynamically requested for compatibility with Android API level 26+.

83 files changed:
samples/java/jniviewer/.classpath [deleted file]
samples/java/jniviewer/.externalToolBuilders/C++ Builder.launch [deleted file]
samples/java/jniviewer/.gitattributes [new file with mode: 0644]
samples/java/jniviewer/.gitignore
samples/java/jniviewer/.project [deleted file]
samples/java/jniviewer/.settings/org.eclipse.jdt.core.prefs [deleted file]
samples/java/jniviewer/AndroidManifest.xml [deleted file]
samples/java/jniviewer/ReadMe.md
samples/java/jniviewer/app/build.gradle [new file with mode: 0644]
samples/java/jniviewer/app/src/main/AndroidManifest.xml [new file with mode: 0644]
samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniActivity.java [new file with mode: 0644]
samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniFileDialog.java [new file with mode: 0644]
samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniLogger.java [new file with mode: 0644]
samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniRenderer.java [new file with mode: 0644]
samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniView.java [new file with mode: 0644]
samples/java/jniviewer/app/src/main/jni/CMakeLists.txt [new file with mode: 0644]
samples/java/jniviewer/app/src/main/jni/OcctJni_MsgPrinter.cxx [new file with mode: 0644]
samples/java/jniviewer/app/src/main/jni/OcctJni_MsgPrinter.hxx [new file with mode: 0644]
samples/java/jniviewer/app/src/main/jni/OcctJni_Viewer.cxx [new file with mode: 0644]
samples/java/jniviewer/app/src/main/jni/OcctJni_Viewer.hxx [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/close_l.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/close_p.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/fit.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/ic_launcher.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/info.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/info_image.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/message.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/open.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/open_l.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/open_p.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_back.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_bottom.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_front.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_left.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_right.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_top.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-hdpi/view.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-mdpi/ic_launcher.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-xhdpi/ic_launcher.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/drawable-xxhdpi/ic_launcher.png [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/layout/activity_main.xml [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/values/id.xml [new file with mode: 0644]
samples/java/jniviewer/app/src/main/res/values/strings.xml [new file with mode: 0644]
samples/java/jniviewer/build.gradle [new file with mode: 0644]
samples/java/jniviewer/gradle.properties.template [new file with mode: 0644]
samples/java/jniviewer/jni/Android.mk [deleted file]
samples/java/jniviewer/jni/Application.mk [deleted file]
samples/java/jniviewer/jni/OcctJni_MsgPrinter.cxx [deleted file]
samples/java/jniviewer/jni/OcctJni_MsgPrinter.hxx [deleted file]
samples/java/jniviewer/jni/OcctJni_Viewer.cxx [deleted file]
samples/java/jniviewer/jni/OcctJni_Viewer.hxx [deleted file]
samples/java/jniviewer/jni/OcctJni_Window.cxx [deleted file]
samples/java/jniviewer/jni/OcctJni_Window.hxx [deleted file]
samples/java/jniviewer/project.properties [deleted file]
samples/java/jniviewer/res/drawable-hdpi/close_l.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/close_p.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/fit.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/ic_launcher.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/info.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/info_image.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/message.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/open.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/open_l.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/open_p.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/proj_back.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/proj_bottom.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/proj_front.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/proj_left.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/proj_right.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/proj_top.png [deleted file]
samples/java/jniviewer/res/drawable-hdpi/view.png [deleted file]
samples/java/jniviewer/res/drawable-mdpi/ic_launcher.png [deleted file]
samples/java/jniviewer/res/drawable-xhdpi/ic_launcher.png [deleted file]
samples/java/jniviewer/res/drawable-xxhdpi/ic_launcher.png [deleted file]
samples/java/jniviewer/res/layout/activity_main.xml [deleted file]
samples/java/jniviewer/res/values/id.xml [deleted file]
samples/java/jniviewer/res/values/strings.xml [deleted file]
samples/java/jniviewer/settings.gradle [new file with mode: 0644]
samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniActivity.java [deleted file]
samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniFileDialog.java [deleted file]
samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniLogger.java [deleted file]
samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniRenderer.java [deleted file]
samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniView.java [deleted file]

diff --git a/samples/java/jniviewer/.classpath b/samples/java/jniviewer/.classpath
deleted file mode 100644 (file)
index 5176974..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="gen"/>
-       <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/samples/java/jniviewer/.externalToolBuilders/C++ Builder.launch b/samples/java/jniviewer/.externalToolBuilders/C++ Builder.launch
deleted file mode 100644 (file)
index cbe7a12..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
-<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/occtJniActivity/libs&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
-<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
-<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/occtJniActivity/jni&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="~/develop/android-ndk-r10/ndk-build"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="V=1 jniall"/>
-<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/occtJniActivity/jni}"/>
-</launchConfiguration>
diff --git a/samples/java/jniviewer/.gitattributes b/samples/java/jniviewer/.gitattributes
new file mode 100644 (file)
index 0000000..c275dc2
--- /dev/null
@@ -0,0 +1 @@
+*.gradle eol=lf
index 890072f..3328b0f 100644 (file)
@@ -1,4 +1,10 @@
-/assets
-/bin
-/gen
-/libs
+/.gradle
+/.idea
+/build
+/gradle
+gradlew
+gradlew.bat
+/app/.cxx
+/app/build
+gradle.properties
+local.properties
diff --git a/samples/java/jniviewer/.project b/samples/java/jniviewer/.project
deleted file mode 100644 (file)
index c258add..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-       <name>occtJniActivity</name>
-       <comment></comment>
-       <projects>
-       </projects>
-       <buildSpec>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
-                       <triggers>auto,full,incremental,</triggers>
-                       <arguments>
-                               <dictionary>
-                                       <key>LaunchConfigHandle</key>
-                                       <value>&lt;project&gt;/.externalToolBuilders/C++ Builder.launch</value>
-                               </dictionary>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.jdt.core.javabuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-       </buildSpec>
-       <natures>
-               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
-               <nature>org.eclipse.jdt.core.javanature</nature>
-       </natures>
-</projectDescription>
diff --git a/samples/java/jniviewer/.settings/org.eclipse.jdt.core.prefs b/samples/java/jniviewer/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644 (file)
index b080d2d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.source=1.6
diff --git a/samples/java/jniviewer/AndroidManifest.xml b/samples/java/jniviewer/AndroidManifest.xml
deleted file mode 100644 (file)
index c0cbbbb..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.opencascade.jnisample">
-    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
-        <activity android:name="OcctJniActivity"
-                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
-                  android:launchMode="singleTask"
-                  android:configChanges="orientation|keyboardHidden|screenSize">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-
-                <data android:scheme="" />
-                <data android:scheme="file" />
-                <data android:scheme="content" />
-                <data android:host="*" />
-
-                <data android:pathPattern=".*\\.brep" />
-                <data android:pathPattern=".*\\.rle" />
-                <data android:pathPattern=".*\\.step" />
-                <data android:pathPattern=".*\\.stp" />
-                <data android:pathPattern=".*\\.iges" />
-                <data android:pathPattern=".*\\.igs" />
-            </intent-filter>
-        </activity>
-    </application>
-    <uses-feature android:glEsVersion="0x00020000"/>
-    <uses-sdk android:minSdkVersion="15"/>
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-</manifest>
index c1dd21d..4019016 100644 (file)
@@ -11,36 +11,22 @@ This sample demonstrates indirect method of wrapping C++ to Java using manually
 Alternative method is available, wrapping individual OCCT classes to Java equivalents so that their full API is available to Java user
 and the code can be programmed on Java level similarly to C++ one.
 See description of OCCT Java Wrapper in Advanced Samples and Tools on OCCT web site at 
-http://www.opencascade.org/support/products/advsamples
+https://www.opencascade.com/content/advanced-samples-and-tools
 
-Run Eclipse from ADT (Android Developer Tools) for building the sample. To import sample project perform
-~~~~
-  File -> Import... -> Android -> Existing Android code into Workspace
-~~~~
-and specify this directory. The project re-build will be started immediately right after importation if "Build automatically" option is turned on (default in Eclipse).  
-Proxy library compilation and packaging is performed by NDK build script, called by "C++ Builder" configured within Eclipse project.
-The path to "ndk-build" tool from Android NDK (Native Development Kit) should be specified in Eclipse project properties:
-~~~~
-  Project -> Properties -> Builders -> C++ Builder -> Edit -> Location
-~~~~
+Install Android Studio 4.0+ and install building tools (check Tools -> SDK Manager):
+- Android SDK (API level 21 or higher).
+- Android SDK build tools.
+- Android NDK r16 or higher (coming with CMake toolchain).
+  Using NDK r18 or newer will require changing ANDROID_STL in project settings.
+- CMake 3.10+.
 
-Now paths to OCCT C++ libraries and additional components should be specified in "jni/Android.mk" file:
-~~~~
-OCCT_ROOT := $(LOCAL_PATH)/../../../..
-
-FREETYPE_INC  := $(OCCT_ROOT)/../freetype/include/freetype2
-FREETYPE_LIBS := $(OCCT_ROOT)/../freetype/libs
+Specify this folder location in Android Studio for opening project.
+You might need re-entering Android SDK explicitly in File -> Project Structure -> SDK Location settings (SDK, NDK, JDK locations).
 
-FREEIMAGE_INC  := $(OCCT_ROOT)/../FreeImage/include
-FREEIMAGE_LIBS := $(OCCT_ROOT)/../FreeImage/libs
-
-OCCT_INC  := $(OCCT_ROOT)/inc
-OCCT_LIBS := $(OCCT_ROOT)/and/libs
-~~~~
-The list of extra components (Freetype, FreeImage) depends on OCCT configuration.
-Variable $(TARGET_ARCH_ABI) is used within this script to refer to active architecture.
-E.g. for 32-bit ARM build (see variable *APP_ABI* in "jni/Application.mk")
-the folder *OCCT_LIBS* should contain sub-folder "armeabi-v7a" with OCCT libraries.
+This sample expects OCCT to be already build - please refer to appropriate CMake building instructions in OCCT documentation.
+The following variables should be added into file gradle.properties (see gradle.properties.template as template):
+- `OCCT_ROOT` - path to OCCT installation folder.
+- `FREETYPE_ROOT` - path to FreeType installation folder.
 
 FreeImage is optional and does not required for this sample, however you should include all extra libraries used for OCCT building
 and load the explicitly from Java code within OcctJniActivity::loadNatives() method, including toolkits from OCCT itself in proper order:
@@ -49,10 +35,8 @@ and load the explicitly from Java code within OcctJniActivity::loadNatives() met
      || !loadLibVerbose ("TKMath",  aLoaded, aFailed)
      || !loadLibVerbose ("TKG2d",   aLoaded, aFailed)
 ~~~~
-Note that C++ STL library is not part of Android system.
-Thus application must package this library as well as extra component.
-"gnustl_shared" STL implementation is expected within this sample.
+Note that C++ STL library is not part of Android system, and application must package this library as well as extra component ("gnustl_shared" by default - see also `ANDROID_STL`).
 
-After successful build, the application can be packaged to Android:
-- Deploy and run application on connected device or emulator directly from Eclipse using adb interface by menu items "Run" and "Debug". This would sign package with debug certificate.
-- Prepare signed end-user package using wizard File -> Export -> Android -> Export Android Application.
+After successful build via Build -> Rebuild Project, the application can be packaged to Android:
+- Deploy and run application on connected device or emulator directly from Android Studio using adb interface by menu items "Run" and "Debug". This would sign package with debug certificate.
+- Prepare signed end-user package using wizard Build -> Generate signed APK.
diff --git a/samples/java/jniviewer/app/build.gradle b/samples/java/jniviewer/app/build.gradle
new file mode 100644 (file)
index 0000000..10014ce
--- /dev/null
@@ -0,0 +1,48 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 21
+    buildToolsVersion "30.0.0"
+
+    defaultConfig {
+        applicationId "com.opencascade.jnisample"
+        minSdkVersion 21
+        targetSdkVersion 26
+
+        ndk {
+            abiFilters "arm64-v8a"
+        }
+
+        externalNativeBuild {
+            cmake {
+                arguments "-DOCCT_ROOT=" + OCCT_ROOT,
+                        "-DFREETYPE_ROOT=" + FREETYPE_ROOT,
+                        "-DANDROID_STL=gnustl_shared"
+            }
+        }
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
+        }
+    }
+
+    sourceSets {
+        main {
+            manifest.srcFile 'src/main/AndroidManifest.xml'
+            assets.srcDirs = [OCCT_ROOT + "/src"]
+        }
+    }
+
+    externalNativeBuild {
+        cmake {
+            path "src/main/jni/CMakeLists.txt"
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'java/com/opencascade/jnisample', include: ['*.jar'])
+}
diff --git a/samples/java/jniviewer/app/src/main/AndroidManifest.xml b/samples/java/jniviewer/app/src/main/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..4813d0a
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.opencascade.jnisample">
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name="OcctJniActivity"
+                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+                  android:launchMode="singleTask"
+                  android:configChanges="orientation|keyboardHidden|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+
+                <data android:scheme="" />
+                <data android:scheme="file" />
+                <data android:scheme="content" />
+                <data android:host="*" />
+
+                <data android:pathPattern=".*\\.brep" />
+                <data android:pathPattern=".*\\.rle" />
+                <data android:pathPattern=".*\\.step" />
+                <data android:pathPattern=".*\\.stp" />
+                <data android:pathPattern=".*\\.iges" />
+                <data android:pathPattern=".*\\.igs" />
+            </intent-filter>
+        </activity>
+    </application>
+    <uses-feature android:glEsVersion="0x00020000"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+</manifest>
diff --git a/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniActivity.java b/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniActivity.java
new file mode 100644 (file)
index 0000000..83a3e2b
--- /dev/null
@@ -0,0 +1,864 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+package com.opencascade.jnisample;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.List;
+
+import android.app.Activity;
+import android.content.Context;
+
+import android.content.Intent;
+import android.content.res.AssetManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+
+import android.text.Html;
+import android.text.Html.ImageGetter;
+import android.text.Spanned;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.TextView;
+import android.widget.Toast;
+
+//! Main activity
+public class OcctJniActivity extends Activity implements OnClickListener
+{
+
+  //! Auxiliary method to print temporary info messages
+  public static void printShortInfo (Activity     theActivity,
+                                     CharSequence theInfo)
+  {
+    Context aCtx   = theActivity.getApplicationContext();
+    Toast   aToast = Toast.makeText (aCtx, theInfo, Toast.LENGTH_LONG);
+    aToast.show();
+  }
+
+  //! Load single native library
+  private static boolean loadLibVerbose (String        theLibName,
+                                         StringBuilder theLoadedInfo,
+                                         StringBuilder theFailedInfo)
+  {
+    try
+    {
+      System.loadLibrary (theLibName);
+      theLoadedInfo.append ("Info:  native library \"");
+      theLoadedInfo.append (theLibName);
+      theLoadedInfo.append ("\" has been loaded\n");
+      return true;
+    }
+    catch (java.lang.UnsatisfiedLinkError theError)
+    {
+      theFailedInfo.append ("Error: native library \"");
+      theFailedInfo.append (theLibName);
+      theFailedInfo.append ("\" is unavailable:\n  " + theError.getMessage());
+      return false;
+    }
+    catch (SecurityException theError)
+    {
+      theFailedInfo.append ("Error: native library \"");
+      theFailedInfo.append (theLibName);
+      theFailedInfo.append ("\" can not be loaded for security reasons:\n  " + theError.getMessage());
+      return false;
+    }
+  }
+
+  public static boolean wasNativesLoadCalled = false;
+  public static boolean areNativeLoaded      = false;
+  public static String  nativeLoaded         = "";
+  public static String  nativeFailed         = "";
+
+  //! Auxiliary method to load native libraries
+  public boolean loadNatives()
+  {
+    if (wasNativesLoadCalled)
+    {
+      return areNativeLoaded;
+    }
+    wasNativesLoadCalled = true;
+    StringBuilder aLoaded = new StringBuilder();
+    StringBuilder aFailed = new StringBuilder();
+
+    // copy OCCT resources
+    String aResFolder = getFilesDir().getAbsolutePath();
+    copyAssetFolder (getAssets(), "src/SHMessage", aResFolder + "/SHMessage");
+    copyAssetFolder (getAssets(), "src/XSMessage", aResFolder + "/XSMessage");
+
+    // C++ runtime
+    loadLibVerbose ("gnustl_shared", aLoaded, aFailed);
+
+    // 3rd-parties
+    loadLibVerbose ("freetype",  aLoaded, aFailed);
+    loadLibVerbose ("freeimage", aLoaded, aFailed);
+
+    if (// OCCT modeling
+        !loadLibVerbose ("TKernel",      aLoaded, aFailed)
+     || !loadLibVerbose ("TKMath",       aLoaded, aFailed)
+     || !loadLibVerbose ("TKG2d",        aLoaded, aFailed)
+     || !loadLibVerbose ("TKG3d",        aLoaded, aFailed)
+     || !loadLibVerbose ("TKGeomBase",   aLoaded, aFailed)
+     || !loadLibVerbose ("TKBRep",       aLoaded, aFailed)
+     || !loadLibVerbose ("TKGeomAlgo",   aLoaded, aFailed)
+     || !loadLibVerbose ("TKTopAlgo",    aLoaded, aFailed)
+     || !loadLibVerbose ("TKShHealing",  aLoaded, aFailed)
+     || !loadLibVerbose ("TKMesh",       aLoaded, aFailed)
+        // exchange
+     || !loadLibVerbose ("TKPrim",       aLoaded, aFailed)
+     || !loadLibVerbose ("TKBO",         aLoaded, aFailed)
+     || !loadLibVerbose ("TKBool",       aLoaded, aFailed)
+     || !loadLibVerbose ("TKFillet",     aLoaded, aFailed)
+     || !loadLibVerbose ("TKOffset",     aLoaded, aFailed)
+     || !loadLibVerbose ("TKXSBase",     aLoaded, aFailed)
+     || !loadLibVerbose ("TKIGES",       aLoaded, aFailed)
+     || !loadLibVerbose ("TKSTEPBase",   aLoaded, aFailed)
+     || !loadLibVerbose ("TKSTEPAttr",   aLoaded, aFailed)
+     || !loadLibVerbose ("TKSTEP209",    aLoaded, aFailed)
+     || !loadLibVerbose ("TKSTEP",       aLoaded, aFailed)
+        // OCCT Visualization
+     || !loadLibVerbose ("TKService",    aLoaded, aFailed)
+     || !loadLibVerbose ("TKHLR",        aLoaded, aFailed)
+     || !loadLibVerbose ("TKV3d",        aLoaded, aFailed)
+     || !loadLibVerbose ("TKOpenGl",     aLoaded, aFailed)
+        // application code
+     || !loadLibVerbose ("TKJniSample",  aLoaded, aFailed))
+    {
+      nativeLoaded = aLoaded.toString();
+      nativeFailed = aFailed.toString();
+      areNativeLoaded = false;
+      //exitWithError (theActivity, "Broken apk?\n" + theFailedInfo);
+      return false;
+    }
+    nativeLoaded = aLoaded.toString();
+    areNativeLoaded = true;
+    return true;
+  }
+
+  //! Create activity
+  @Override protected void onCreate (Bundle theBundle)
+  {
+    super.onCreate (theBundle);
+
+    boolean isLoaded = loadNatives();
+    if (!isLoaded)
+    {
+      printShortInfo (this, nativeFailed);
+      OcctJniLogger.postMessage (nativeLoaded + "\n" + nativeFailed);
+    }
+
+    setContentView (R.layout.activity_main);
+    
+    myOcctView        = (OcctJniView )findViewById (R.id.custom_view);
+    myMessageTextView = (TextView    )findViewById (R.id.message_view);
+    OcctJniLogger.setTextView (myMessageTextView);
+
+    createViewAndButtons (Configuration.ORIENTATION_LANDSCAPE);
+
+    myButtonPreferSize = defineButtonSize ((LinearLayout )findViewById (R.id.panel_menu));
+    ImageButton aScrollBtn = (ImageButton )findViewById (R.id.scroll_btn);
+    aScrollBtn.setY (myButtonPreferSize);
+    aScrollBtn.setOnTouchListener (new View.OnTouchListener()
+    {
+      @Override
+      public boolean onTouch (View theView, MotionEvent theEvent)
+      {
+        return onScrollBtnTouch (theView, theEvent);
+      }
+    });
+
+    onConfigurationChanged (getResources().getConfiguration());
+
+    Intent anIntent = getIntent();
+    Uri    aDataUrl  = anIntent != null ? anIntent.getData() : null;
+    String aDataPath = aDataUrl != null ? aDataUrl.getPath() : "";
+    myOcctView.open (aDataPath);
+    myLastPath = aDataPath;
+
+    myContext = new android.content.ContextWrapper (this);
+    myContext.getExternalFilesDir (null);
+  }
+
+  //! Handle scroll events
+  private boolean onScrollBtnTouch (View        theView,
+                                    MotionEvent theEvent)
+  {
+    switch (theEvent.getAction())
+    {
+      case MotionEvent.ACTION_DOWN:
+      {
+        LinearLayout aPanelMenu = (LinearLayout )findViewById (R.id.panel_menu);
+        boolean isLandscape = (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
+        if (aPanelMenu.getVisibility() == View.VISIBLE)
+        {
+          aPanelMenu.setVisibility (View.GONE);
+          if (!isLandscape)
+          {
+            ((ImageButton )theView).setImageResource (R.drawable.open_p);
+            theView.setY (0);
+          }
+          else
+          {
+            ((ImageButton )theView).setImageResource (R.drawable.open_l);
+            theView.setX (0);
+          }
+        }
+        else
+        {
+          aPanelMenu.setVisibility (View.VISIBLE);
+          if (!isLandscape)
+          {
+            ((ImageButton )theView).setImageResource (R.drawable.close_p);
+            theView.setY (myButtonPreferSize);
+          }
+          else
+          {
+            ((ImageButton )theView).setImageResource (R.drawable.close_l);
+            theView.setX (myButtonPreferSize);
+          }
+        }
+        break;
+      }
+    }
+    return false;
+  }
+
+  //! Initialize views and buttons
+  private void createViewAndButtons (int theOrientation)
+  {
+    // open button
+    ImageButton anOpenButton = (ImageButton )findViewById (R.id.open);
+    anOpenButton.setOnClickListener (this);
+
+    // fit all
+    ImageButton aFitAllButton = (ImageButton )findViewById (R.id.fit);
+    aFitAllButton.setOnClickListener (this);
+    aFitAllButton.setOnTouchListener (new View.OnTouchListener()
+    {
+      @Override
+      public boolean onTouch (View theView, MotionEvent theEvent)
+      {
+        return onTouchButton (theView, theEvent);
+      }
+    });
+    
+    // message
+    ImageButton aMessageButton = (ImageButton )findViewById (R.id.message);
+    aMessageButton.setOnClickListener (this);
+
+    // info
+    ImageButton anInfoButton = (ImageButton )findViewById (R.id.info);
+    anInfoButton.setOnClickListener (this);
+    
+    // font for text view
+    TextView anInfoView = (TextView )findViewById (R.id.info_view);
+    anInfoView.setTextSize (TypedValue.COMPLEX_UNIT_SP, 18);
+
+    // add submenu buttons
+    createSubmenuBtn (R.id.view, R.id.view_group,
+                      Arrays.asList (R.id.proj_front, R.id.proj_top,    R.id.proj_left,
+                                     R.id.proj_back,  R.id.proj_bottom, R.id.proj_right),
+                      Arrays.asList (R.drawable.proj_front, R.drawable.proj_top,    R.drawable.proj_left,
+                                     R.drawable.proj_back,  R.drawable.proj_bottom, R.drawable.proj_right),
+                      4);
+  }
+
+  @Override protected void onNewIntent (Intent theIntent)
+  {
+    super.onNewIntent (theIntent);
+    setIntent (theIntent);
+  }
+
+  @Override protected void onDestroy()
+  {
+    super.onDestroy();
+    OcctJniLogger.setTextView (null);
+  }
+
+  @Override protected void onPause()
+  {
+    super.onPause();
+    myOcctView.onPause();
+  }
+
+  @Override protected void onResume()
+  {
+    super.onResume();
+    myOcctView.onResume();
+
+    Intent anIntent = getIntent();
+    Uri    aDataUrl  = anIntent != null ? anIntent.getData() : null;
+    String aDataPath = aDataUrl != null ? aDataUrl.getPath() : "";
+    if (!aDataPath.equals (myLastPath))
+    {
+      myOcctView.open (aDataPath);
+      myLastPath = aDataPath;
+    }
+  }
+
+  //! Copy folder from assets
+  private boolean copyAssetFolder (AssetManager theAssetMgr,
+                                   String       theAssetFolder,
+                                   String       theFolderPathTo)
+  {
+    try
+    {
+      String[] aFiles  = theAssetMgr.list (theAssetFolder);
+      File     aFolder = new File (theFolderPathTo);
+      aFolder.mkdirs();
+      boolean isOk = true;
+      for (String aFileIter : aFiles)
+      {
+        if (aFileIter.contains ("."))
+        {
+          isOk &= copyAsset (theAssetMgr,
+                             theAssetFolder  + "/" + aFileIter,
+                             theFolderPathTo + "/" + aFileIter);
+        }
+        else
+        {
+          isOk &= copyAssetFolder (theAssetMgr,
+                                   theAssetFolder  + "/" + aFileIter,
+                                   theFolderPathTo + "/" + aFileIter);
+        }
+      }
+      return isOk;
+    }
+    catch (Exception theError)
+    {
+      theError.printStackTrace();
+      return false;
+    }
+  }
+
+  //! Copy single file from assets
+  private boolean copyAsset (AssetManager theAssetMgr,
+                             String       thePathFrom,
+                             String       thePathTo)
+  {
+    try
+    {
+      InputStream aStreamIn = theAssetMgr.open (thePathFrom);
+      File aFileTo = new File (thePathTo);
+      aFileTo.createNewFile();
+      OutputStream aStreamOut = new FileOutputStream (thePathTo);
+      copyStreamContent (aStreamIn, aStreamOut);
+      aStreamIn.close();
+      aStreamIn = null;
+      aStreamOut.flush();
+      aStreamOut.close();
+      aStreamOut = null;
+      return true;
+    }
+    catch (Exception theError)
+    {
+      theError.printStackTrace();
+      return false;
+    }
+  }
+
+  //! Copy single file
+  private static void copyStreamContent (InputStream  theIn,
+                                         OutputStream theOut) throws IOException
+  {
+    byte[] aBuffer = new byte[1024];
+    int aNbReadBytes = 0;
+    while ((aNbReadBytes = theIn.read (aBuffer)) != -1)
+    {
+      theOut.write (aBuffer, 0, aNbReadBytes);
+    }
+  }
+  
+  //! Show/hide text view
+  private void switchTextView (TextView    theTextView,
+                               ImageButton theClickedBtn,
+                               boolean     theToSwitchOn)
+  {
+    if (theTextView != null
+     && theTextView.getVisibility() == View.GONE
+     && theToSwitchOn)
+    {
+      theTextView.setVisibility (View.VISIBLE);
+      theClickedBtn.setBackgroundColor (getResources().getColor(R.color.pressedBtnColor));
+      setTextViewPosition (theTextView);
+    }
+    else
+    {
+      theTextView.setVisibility (View.GONE);
+      theClickedBtn.setBackgroundColor (getResources().getColor (R.color.btnColor));
+    }
+  }
+
+  //! Setup text view position
+  private void setTextViewPosition (TextView theTextView)
+  {
+    if (theTextView.getVisibility() != View.VISIBLE)
+    {
+      return;
+    }
+
+    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
+    {
+      theTextView.setX (myButtonPreferSize);
+      theTextView.setY (0);
+    }
+    else
+    {
+      theTextView.setX (0);
+      theTextView.setY (myButtonPreferSize);
+    }
+  }
+
+  @Override
+  public void onClick (View theButton)
+  {
+    ImageButton aClickedBtn = (ImageButton )theButton;
+    switch (aClickedBtn.getId())
+    {
+      case R.id.message:
+      {
+        switchTextView ((TextView    )findViewById (R.id.info_view),
+                        (ImageButton )findViewById (R.id.info), false);
+        switchTextView (myMessageTextView, aClickedBtn, true);
+        return;
+      }
+      case R.id.info:
+      {
+        String aText = getString (R.string.info_html);
+        aText = String.format (aText, cppOcctMajorVersion(), cppOcctMinorVersion(), cppOcctMicroVersion());
+        Spanned aSpanned = Html.fromHtml (aText, new ImageGetter()
+        {
+          @Override
+          public Drawable getDrawable (String theSource)
+          {
+            Resources aResources = getResources();
+            int anId = aResources.getIdentifier (theSource, "drawable", getPackageName());
+            Drawable aRes = aResources.getDrawable (anId);
+            aRes.setBounds (0, 0, aRes.getIntrinsicWidth(), aRes.getIntrinsicHeight());
+            return aRes;
+          }
+        }, null);
+
+        TextView anInfoView = (TextView )findViewById (R.id.info_view);
+        anInfoView.setText (aSpanned);
+        switchTextView (myMessageTextView, (ImageButton ) findViewById (R.id.message), false);
+        switchTextView (anInfoView,        aClickedBtn,                                true);
+        return;
+      }
+      case R.id.fit:
+      {
+        myOcctView.fitAll();
+        return;
+      }
+      case R.id.proj_front:
+      {
+        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Xpos);
+        return;
+      }
+      case R.id.proj_left:
+      {
+        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Yneg);
+        return;
+      }
+      case R.id.proj_top:
+      {
+        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Zpos);
+        return;
+      }
+      case R.id.proj_back:
+      {
+        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Xneg);
+        return;
+      }
+      case R.id.proj_right:
+      {
+        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Ypos);
+        return;
+      }
+      case R.id.proj_bottom:
+      {
+        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Zneg);
+        return;
+      }
+      case R.id.open:
+      {
+        File aPath = Environment.getExternalStorageDirectory();
+        aClickedBtn.setBackgroundColor (getResources().getColor(R.color.pressedBtnColor));
+        if (myFileOpenDialog == null)
+        {
+          // should be requested on runtime since API level 26 (Android 8)
+          askUserPermission (android.Manifest.permission.WRITE_EXTERNAL_STORAGE, null); // for accessing SD card
+
+          myFileOpenDialog = new OcctJniFileDialog (this, aPath);
+          myFileOpenDialog.setFileEndsWith (".brep");
+          myFileOpenDialog.setFileEndsWith (".rle");
+          myFileOpenDialog.setFileEndsWith (".iges");
+          myFileOpenDialog.setFileEndsWith (".igs");
+          myFileOpenDialog.setFileEndsWith (".step");
+          myFileOpenDialog.setFileEndsWith (".stp");
+          myFileOpenDialog.addFileListener (new OcctJniFileDialog.FileSelectedListener()
+          {
+            public void fileSelected (File theFile)
+            {
+              if (theFile != null && myOcctView != null)
+              {
+                myOcctView.open (theFile.getPath());
+              }
+            }
+          });
+          myFileOpenDialog.addDialogDismissedListener (new OcctJniFileDialog.DialogDismissedListener()
+          {
+            @Override
+            public void dialogDismissed()
+            {
+              ImageButton openButton = (ImageButton )findViewById (R.id.open);
+              openButton.setBackgroundColor (getResources().getColor(R.color.btnColor));
+            }
+          });
+        }
+        myFileOpenDialog.showDialog();
+        return;
+      }
+    }
+  }
+
+  private void createSubmenuBtn (int     theParentBtnId,
+                                 int     theParentLayoutId,
+                                 final List<Integer> theNewButtonIds,
+                                 final List<Integer> theNewButtonImageIds,
+                                 int     thePosition)
+  {
+    int aPosInList = 0;
+    final ImageButton aParentBtn = (ImageButton )findViewById (theParentBtnId);
+
+    ViewGroup.LayoutParams aParams = null;
+    LinearLayout parentLayout = (LinearLayout ) findViewById (theParentLayoutId);
+    for (Integer newButtonId : theNewButtonIds)
+    {
+      ImageButton aNewButton = (ImageButton )findViewById (newButtonId);
+      if (aNewButton == null)
+      {
+        aNewButton = (ImageButton )new ImageButton (this);
+        aNewButton.setId (newButtonId);
+        aNewButton.setImageResource (theNewButtonImageIds.get (aPosInList));
+        aNewButton.setLayoutParams (aParams);
+        parentLayout.addView (aNewButton);
+      }
+
+      aNewButton.setOnClickListener (this);
+      aNewButton.setVisibility (View.GONE);
+
+      aNewButton.setOnTouchListener (new View.OnTouchListener()
+      {
+        @Override
+        public boolean onTouch (View theView, MotionEvent theEvent)
+        {
+          return onTouchButton (theView, theEvent);
+        }
+      });
+      ++aPosInList;
+    }
+
+    if (aParentBtn != null)
+    {
+      aParentBtn.setOnTouchListener (null);
+      aParentBtn.setOnTouchListener (new View.OnTouchListener()
+      {
+        @Override
+        public boolean onTouch (View theView, MotionEvent theEvent)
+        {
+          if (theEvent.getAction () == MotionEvent.ACTION_DOWN)
+          {
+            Boolean isVisible = false;
+            for (Integer aNewButtonId : theNewButtonIds)
+            {
+              ImageButton anBtn = (ImageButton )findViewById (aNewButtonId);
+              if (anBtn != null)
+              {
+                if (anBtn.getVisibility() == View.GONE)
+                {
+                  anBtn.setVisibility (View.VISIBLE);
+                  isVisible = true;
+                }
+                else
+                {
+                  anBtn.setVisibility (View.GONE);
+                }
+              }
+            }
+            aParentBtn.setBackgroundColor (!isVisible ? getResources().getColor(R.color.btnColor) : getResources().getColor(R.color.pressedBtnColor));
+          }
+          return false;
+        }
+      });
+    }
+  }
+
+  //! Implements onTouch functionality
+  private boolean onTouchButton (View        theView,
+                                 MotionEvent theEvent)
+  {
+    switch (theEvent.getAction())
+    {
+      case MotionEvent.ACTION_DOWN:
+        ((ImageButton )theView).setBackgroundColor (getResources().getColor (R.color.pressedBtnColor));
+        break;
+      case MotionEvent.ACTION_UP:
+        ((ImageButton )theView).setBackgroundColor (getResources().getColor (R.color.btnColor));
+        break;
+    }
+    return false;
+  }
+
+  //! Handle configuration change event
+  @Override
+  public void onConfigurationChanged (Configuration theNewConfig)
+  {
+    super.onConfigurationChanged (theNewConfig);
+    LinearLayout aLayoutPanelMenu       = (LinearLayout )findViewById (R.id.panel_menu);
+    LayoutParams aPanelMenuLayoutParams = aLayoutPanelMenu.getLayoutParams();
+
+    LinearLayout aLayoutViewGroup       = (LinearLayout )findViewById (R.id.view_group);
+    LayoutParams aViewGroupLayoutParams = aLayoutViewGroup.getLayoutParams();
+    ImageButton  aScrollBtn             = (ImageButton )findViewById (R.id.scroll_btn);
+    LayoutParams aScrollBtnLayoutParams = aScrollBtn.getLayoutParams();
+
+    myButtonPreferSize = defineButtonSize ((LinearLayout )findViewById (R.id.panel_menu));
+    defineButtonSize ((LinearLayout )findViewById (R.id.view_group));
+
+    switch (theNewConfig.orientation)
+    {
+      case Configuration.ORIENTATION_PORTRAIT:
+      {
+        setHorizontal (aLayoutPanelMenu, aPanelMenuLayoutParams);
+        setHorizontal (aLayoutViewGroup, aViewGroupLayoutParams);
+        aLayoutViewGroup.setGravity (Gravity.BOTTOM);
+
+        aScrollBtnLayoutParams.height = LayoutParams.WRAP_CONTENT;
+        aScrollBtnLayoutParams.width  = LayoutParams.MATCH_PARENT;
+        aScrollBtn.setLayoutParams (aScrollBtnLayoutParams);
+        if (aLayoutPanelMenu.getVisibility() == View.VISIBLE)
+        {
+          aScrollBtn.setImageResource (R.drawable.close_p);
+          aScrollBtn.setY (myButtonPreferSize);
+          aScrollBtn.setX (0);
+        }
+        else
+        {
+          aScrollBtn.setImageResource (R.drawable.open_p);
+          aScrollBtn.setY (0);
+          aScrollBtn.setX (0);
+        }
+        break;
+      }
+      case Configuration.ORIENTATION_LANDSCAPE:
+      {
+        setVertical (aLayoutPanelMenu, aPanelMenuLayoutParams);
+        setVertical (aLayoutViewGroup, aViewGroupLayoutParams);
+        aLayoutViewGroup.setGravity (Gravity.RIGHT);
+
+        aScrollBtnLayoutParams.height = LayoutParams.MATCH_PARENT;
+        aScrollBtnLayoutParams.width  = LayoutParams.WRAP_CONTENT;
+        aScrollBtn.setLayoutParams (aScrollBtnLayoutParams);
+        if (aLayoutPanelMenu.getVisibility() == View.VISIBLE)
+        {
+          aScrollBtn.setImageResource (R.drawable.close_l);
+          aScrollBtn.setX (myButtonPreferSize);
+          aScrollBtn.setY (0);
+        }
+        else
+        {
+          aScrollBtn.setImageResource (R.drawable.open_l);
+          aScrollBtn.setY (0);
+          aScrollBtn.setX (0);
+        }
+        break;
+      }
+    }
+    setTextViewPosition (myMessageTextView);
+    setTextViewPosition ((TextView )findViewById (R.id.info_view));
+  }
+
+  private void setHorizontal (LinearLayout theLayout,
+                              LayoutParams theLayoutParams)
+  {
+    theLayout.setOrientation (LinearLayout.HORIZONTAL);
+    theLayoutParams.height = LayoutParams.WRAP_CONTENT;
+    theLayoutParams.width  = LayoutParams.MATCH_PARENT;
+    theLayout.setLayoutParams (theLayoutParams);
+  }
+
+  private void setVertical (LinearLayout theLayout,
+                            LayoutParams theLayoutParams)
+  {
+    theLayout.setOrientation (LinearLayout.VERTICAL);
+    theLayoutParams.height = LayoutParams.MATCH_PARENT;
+    theLayoutParams.width  = LayoutParams.WRAP_CONTENT;
+    theLayout.setLayoutParams (theLayoutParams);
+  }
+
+  //! Define button size
+  private int defineButtonSize (LinearLayout theLayout)
+  {
+    boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
+    Display aDisplay    = getWindowManager().getDefaultDisplay();
+    Point   aDispPnt    = new Point();
+    aDisplay.getSize (aDispPnt);
+
+    int aNbChildren = theLayout.getChildCount();
+    int aHeight     = aDispPnt.y / aNbChildren;
+    int aWidth      = aDispPnt.x / aNbChildren;
+    int aResultSize = 0;
+    for (int aChildIter = 0; aChildIter < aNbChildren; ++aChildIter)
+    {
+      View aView = theLayout.getChildAt (aChildIter);
+      if (aView instanceof ImageButton)
+      {
+        ImageButton aButton = (ImageButton )aView;
+        if (isLandscape)
+        {
+          aButton.setMinimumWidth (aHeight);
+        }
+        else
+        {
+          aButton.setMinimumHeight (aWidth);
+        }
+      }
+    }
+    if (isLandscape)
+    {
+      aResultSize = aHeight;
+    }
+    else
+    {
+      aResultSize = aWidth;
+    }
+    return aResultSize;
+  }
+
+  //! Request user permission.
+  private void askUserPermission (String thePermission, String theRationale)
+  {
+    // Dynamically load methods introduced by API level 23.
+    // On older system this permission is granted by user during application installation.
+    java.lang.reflect.Method aMetPtrCheckSelfPermission, aMetPtrRequestPermissions, aMetPtrShouldShowRequestPermissionRationale;
+    try
+    {
+      aMetPtrCheckSelfPermission = myContext.getClass().getMethod ("checkSelfPermission", String.class);
+      aMetPtrRequestPermissions = getClass().getMethod ("requestPermissions", String[].class, int.class);
+      aMetPtrShouldShowRequestPermissionRationale = getClass().getMethod ("shouldShowRequestPermissionRationale", String.class);
+    }
+    catch (SecurityException theError)
+    {
+      postMessage ("Unable to find permission methods:\n" + theError.getMessage(), Message_Trace);
+      return;
+    }
+    catch (NoSuchMethodException theError)
+    {
+      postMessage ("Unable to find permission methods:\n" + theError.getMessage(), Message_Trace);
+      return;
+    }
+
+    try
+    {
+      int isAlreadyGranted = (Integer )aMetPtrCheckSelfPermission.invoke (myContext, thePermission);
+      if (isAlreadyGranted == android.content.pm.PackageManager.PERMISSION_GRANTED)
+      {
+        return;
+      }
+
+      boolean toShowInfo = theRationale != null && (Boolean )aMetPtrShouldShowRequestPermissionRationale.invoke (this, thePermission);
+      if (toShowInfo)
+      {
+        postMessage (theRationale, Message_Info);
+      }
+
+      // show dialog to user
+      aMetPtrRequestPermissions.invoke (this, new String[]{thePermission}, 0);
+    }
+    catch (IllegalArgumentException theError)
+    {
+      postMessage ("Internal error: Unable to call permission method:\n" + theError.getMessage(), Message_Fail);
+      return;
+    }
+    catch (IllegalAccessException theError)
+    {
+      postMessage ("Internal error: Unable to call permission method:\n" + theError.getMessage(), Message_Fail);
+      return;
+    }
+    catch (java.lang.reflect.InvocationTargetException theError)
+    {
+      postMessage ("Internal error: Unable to call permission method:\n" + theError.getMessage(), Message_Fail);
+      return;
+    }
+  }
+
+  //! Message gravity.
+  private static final int Message_Trace   = 0;
+  private static final int Message_Info    = 1;
+  private static final int Message_Warning = 2;
+  private static final int Message_Alarm   = 3;
+  private static final int Message_Fail    = 4;
+
+  //! Auxiliary method to show info message.
+  public void postMessage (String theMessage, int theGravity)
+  {
+    if (theGravity == Message_Trace)
+    {
+      return;
+    }
+
+    final String  aText = theMessage;
+    final Context aCtx  = this;
+    this.runOnUiThread (new Runnable() { public void run() {
+      android.app.AlertDialog.Builder aBuilder = new android.app.AlertDialog.Builder (aCtx);
+      aBuilder.setMessage (aText).setNegativeButton ("OK", null);
+      android.app.AlertDialog aDialog = aBuilder.create();
+      aDialog.show();
+    }});
+  }
+
+  //! OCCT major version
+  private native long cppOcctMajorVersion();
+
+  //! OCCT minor version
+  private native long cppOcctMinorVersion();
+
+  //! OCCT micro version
+  private native long cppOcctMicroVersion();
+
+  private OcctJniView       myOcctView;
+  private TextView          myMessageTextView;
+  private String            myLastPath;
+  private android.content.ContextWrapper myContext = null;
+  private OcctJniFileDialog myFileOpenDialog;
+  private int               myButtonPreferSize = 65;
+
+}
diff --git a/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniFileDialog.java b/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniFileDialog.java
new file mode 100644 (file)
index 0000000..e12cc1a
--- /dev/null
@@ -0,0 +1,376 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+package com.opencascade.jnisample;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import com.opencascade.jnisample.ListenerList.FireHandler;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.graphics.Color;
+import android.os.Environment;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.Spinner;
+
+//! Simple open file dialog
+public class OcctJniFileDialog
+{
+
+  public enum DialogMode
+  {
+    FileOpen, FileExport, FileSave
+  }
+
+  private static final String PARENT_DIR = "..";
+  private String[]   myFileList;
+  private File       myCurrentPath;
+  private DialogMode myDialogMode = DialogMode.FileOpen;
+
+  private ListenerList<FileSelectedListener>    myFileListenerList    = new ListenerList<OcctJniFileDialog.FileSelectedListener>();
+  private ListenerList<DialogDismissedListener> myDialogDismissedList = new ListenerList<DialogDismissedListener>();
+  private final Activity myActivity;
+  private List<String>   myFileEndsWith;
+  private EditText myFileNameInput;
+  private Spinner  myFileExtSpinner;
+  int myCurrentExtPositionInList = 0;
+
+  public interface FileSelectedListener
+  {
+    void fileSelected (File theFile);
+  }
+
+  public interface DialogDismissedListener
+  {
+    void dialogDismissed();
+  }
+
+  //! Main constructor.
+  public OcctJniFileDialog (Activity theActivity,
+                            File     thePath)
+  {
+    myActivity = theActivity;
+    if (!thePath.exists())
+    {
+      thePath = Environment.getExternalStorageDirectory();
+    }
+    loadFileList (thePath);
+  }
+
+  //! Create new dialog
+  public Dialog createFileDialog()
+  {
+    final Object[] anObjWrapper = new Object[1];
+    Dialog aDialog = null;
+    AlertDialog.Builder aBuilder = new AlertDialog.Builder (myActivity);
+
+    aBuilder.setTitle (myCurrentPath.getPath());
+    LinearLayout aTitleLayout = new LinearLayout (myActivity);
+    aTitleLayout.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+    aTitleLayout.setOrientation (LinearLayout.VERTICAL);
+
+    ListView list = new ListView (myActivity);
+    list.setScrollingCacheEnabled(false);
+    list.setBackgroundColor (Color.parseColor ("#33B5E5"));
+
+    list.setAdapter (new ArrayAdapter<String> (myActivity, android.R.layout.select_dialog_item, myFileList));
+    list.setOnItemClickListener (new AdapterView.OnItemClickListener ()
+    {
+
+      public void onItemClick (AdapterView<?> arg0, View view, int pos, long id)
+      {
+        String fileChosen = myFileList[pos];
+        File aChosenFile = getChosenFile (fileChosen);
+        if (aChosenFile.isDirectory())
+        {
+          loadFileList (aChosenFile);
+          ((Dialog )anObjWrapper[0]).cancel();
+          ((Dialog )anObjWrapper[0]).dismiss();
+          showDialog();
+        }
+        else
+        {
+          if (myDialogMode == DialogMode.FileOpen)
+          {
+            ((Dialog )anObjWrapper[0]).cancel();
+            ((Dialog )anObjWrapper[0]).dismiss();
+            fireFileSelectedEvent (aChosenFile);
+          }
+          else
+          {
+            myFileNameInput.setText (aChosenFile.getName());
+          }
+        }
+      }
+    });
+    list.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 0.6f));
+    aTitleLayout.addView (list);
+
+    if (myDialogMode == DialogMode.FileSave
+     || myDialogMode == DialogMode.FileExport)
+    {
+      myFileNameInput  = new EditText (myActivity);
+      myFileExtSpinner = new Spinner  (myActivity);
+      ArrayAdapter<CharSequence> adapter = null;
+      if (myDialogMode == DialogMode.FileExport)
+      {
+        adapter = ArrayAdapter.createFromResource (myActivity, R.array.ext_to_exp,
+            android.R.layout.simple_spinner_item);
+      }
+      else
+      {
+        adapter = ArrayAdapter.createFromResource (myActivity, R.array.ext_to_save,
+            android.R.layout.simple_spinner_item);
+      }
+      // Specify the layout to use when the list of choices appears
+      adapter.setDropDownViewResource (android.R.layout.simple_spinner_dropdown_item);
+      // Apply the adapter to the spinner
+      myFileExtSpinner.setAdapter (adapter);
+      myFileExtSpinner.setSelection (myCurrentExtPositionInList);
+
+      myFileExtSpinner.setOnItemSelectedListener (new AdapterView.OnItemSelectedListener()
+      {
+
+        @Override
+        public void onNothingSelected (AdapterView<?> theParentView)
+        {
+          // your code here
+        }
+
+        @Override
+        public void onItemSelected (AdapterView<?> theParent, View theView, int thePosition, long theId)
+        {
+          if (myCurrentExtPositionInList != thePosition)
+          {
+            myCurrentExtPositionInList = thePosition;
+            setFileEndsWith (Arrays.asList (myFileExtSpinner.getSelectedItem().toString()));
+            loadFileList (myCurrentPath);
+            ((Dialog )anObjWrapper[0]).cancel();
+            ((Dialog )anObjWrapper[0]).dismiss();
+            showDialog();
+          }
+        }
+      });
+
+      myFileExtSpinner.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT,
+          LayoutParams.WRAP_CONTENT, 0.2f));
+      // titleLayout.addView(fileExtSpinner);
+      myFileNameInput.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT,
+          LayoutParams.WRAP_CONTENT, 0.2f));
+      LinearLayout aControlsView = new LinearLayout (myActivity);
+
+      aControlsView.addView (myFileNameInput);
+      aControlsView.addView (myFileExtSpinner);
+
+      aTitleLayout.addView (aControlsView);
+      aBuilder.setView (aTitleLayout);
+      aBuilder.setPositiveButton ("OK", new DialogInterface.OnClickListener()
+      {
+        @Override
+        public void onClick (DialogInterface theDialog, int theWhich)
+        {
+          if (theWhich >= 0)
+          {
+            String aFileChosen = myFileList[theWhich];
+            File aChosenFile = getChosenFile (aFileChosen);
+            fireFileSelectedEvent (aChosenFile);
+          }
+        }
+      }).setNegativeButton ("Cancel", null);
+    }
+    else
+    {
+      aBuilder.setNegativeButton ("Cancel", null);
+    }
+
+    aBuilder.setView (aTitleLayout);
+
+    aDialog = aBuilder.show();
+    aDialog.setOnDismissListener (new DialogInterface.OnDismissListener()
+    {
+      @Override
+      public void onDismiss (DialogInterface theDialog)
+      {
+        fireDialogDismissedEvent();
+      }
+    });
+    anObjWrapper[0] = aDialog;
+    return aDialog;
+  }
+
+  public void addFileListener (FileSelectedListener theListener)
+  {
+    myFileListenerList.add (theListener);
+  }
+
+  public void addDialogDismissedListener (DialogDismissedListener theListener)
+  {
+    myDialogDismissedList.add (theListener);
+  }
+
+  //! Show file dialog
+  public void showDialog()
+  {
+    createFileDialog().show();
+  }
+
+  private void fireFileSelectedEvent (final File theFile)
+  {
+    myFileListenerList.fireEvent (new FireHandler<OcctJniFileDialog.FileSelectedListener>()
+    {
+      public void fireEvent (FileSelectedListener theListener)
+      {
+        theListener.fileSelected (theFile);
+      }
+    });
+  }
+
+  private void fireDialogDismissedEvent()
+  {
+    myDialogDismissedList.fireEvent (new FireHandler<OcctJniFileDialog.DialogDismissedListener>()
+    {
+      public void fireEvent (DialogDismissedListener theListener)
+      {
+        theListener.dialogDismissed();
+      }
+    });
+  }
+
+  private void loadFileList (File thePath)
+  {
+    myCurrentPath = thePath;
+    List<String> aList = new ArrayList<String>();
+    if (thePath.exists())
+    {
+      if (thePath.getParentFile() != null)
+      {
+        aList.add (PARENT_DIR);
+      }
+      FilenameFilter aFilter = new FilenameFilter()
+      {
+        public boolean accept (File theDir, String theFilename)
+        {
+          File aSel = new File (theDir, theFilename);
+          if (!aSel.canRead())
+          {
+            return false;
+          }
+          boolean isEndWith = false;
+          if (myFileEndsWith != null)
+          {
+            for (String aFileExtIter : myFileEndsWith)
+            {
+              if (theFilename.toLowerCase().endsWith (aFileExtIter))
+              {
+                isEndWith = true;
+                break;
+              }
+            }
+          }
+          return isEndWith || aSel.isDirectory();
+        }
+      };
+      String[] aFileList1 = thePath.list (aFilter);
+      if (aFileList1 != null)
+      {
+        for (String aFileIter : aFileList1)
+        {
+          aList.add (aFileIter);
+        }
+      }
+    }
+    myFileList = (String[] )aList.toArray (new String[] {});
+  }
+
+  private File getChosenFile (String theFileChosen)
+  {
+    if (theFileChosen.equals (PARENT_DIR))
+      return myCurrentPath.getParentFile();
+    else
+      return new File (myCurrentPath, theFileChosen);
+  }
+
+  public void setFileEndsWith (String fileEndsWith)
+  {
+    if (myFileEndsWith == null)
+    {
+      myFileEndsWith = new ArrayList<String>();
+    }
+    if (myFileEndsWith.indexOf (fileEndsWith) == -1)
+    {
+      myFileEndsWith.add (fileEndsWith);
+    }
+  }
+
+  public void setFileEndsWith (List<String> theFileEndsWith)
+  {
+    myFileEndsWith = theFileEndsWith;
+  }
+
+  public DialogMode DialogMode()
+  {
+    return myDialogMode;
+  }
+
+  public void DialogMode (DialogMode theMode)
+  {
+    myDialogMode = theMode;
+  }
+}
+
+class ListenerList<L>
+{
+  private List<L> myListenerList = new ArrayList<L>();
+
+  public interface FireHandler<L>
+  {
+    void fireEvent (L theListener);
+  }
+
+  public void add (L theListener)
+  {
+    myListenerList.add (theListener);
+  }
+
+  public void fireEvent (FireHandler<L> theFireHandler)
+  {
+    List<L> aCopy = new ArrayList<L> (myListenerList);
+    for (L anIter : aCopy)
+    {
+      theFireHandler.fireEvent (anIter);
+    }
+  }
+
+  public void remove (L theListener)
+  {
+    myListenerList.remove (theListener);
+  }
+
+  public List<L> getListenerList()
+  {
+    return myListenerList;
+  }
+}
diff --git a/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniLogger.java b/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniLogger.java
new file mode 100644 (file)
index 0000000..cc8b1e4
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+package com.opencascade.jnisample;
+
+import java.util.concurrent.locks.ReentrantLock;
+
+import android.util.Log;
+import android.widget.TextView;
+
+//! Auxiliary class for logging messages
+public class OcctJniLogger
+{
+
+  //! Setup text view
+  public static void setTextView (TextView theTextView)
+  {
+    if (myTextView != null)
+    {
+      myLog = myTextView.getText().toString();
+    }
+
+    myTextView = theTextView;
+    if (myTextView != null)
+    {
+      myTextView.setText (myLog);
+      myLog = "";
+    }
+  }
+
+  //! Interface implementation
+  public static void postMessage (String theText)
+  {
+    final String aCopy = new String (theText);
+    Log.e (myTag, theText);
+
+    myMutex.lock();
+    final TextView aView = myTextView;
+    if (aView == null)
+    {
+      myLog += aCopy;
+      myMutex.unlock();
+      return;
+    }
+
+    aView.post (new Runnable()
+    {
+      public void run()
+      {
+        aView.setText (aView.getText() + aCopy + "\n");
+      }
+    });
+    myMutex.unlock();
+  }
+
+  private static final String        myTag      = "occtJniViewer";
+  private static final ReentrantLock myMutex    = new ReentrantLock (true);
+  private static TextView            myTextView = null;
+  private static String              myLog      = "";
+
+}
diff --git a/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniRenderer.java b/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniRenderer.java
new file mode 100644 (file)
index 0000000..731037a
--- /dev/null
@@ -0,0 +1,218 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+package com.opencascade.jnisample;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLSurfaceView;
+
+//! Wrapper for C++ OCCT viewer.
+public class OcctJniRenderer implements GLSurfaceView.Renderer
+{
+
+  //! Wrapper for V3d_TypeOfOrientation
+  enum TypeOfOrientation
+  {
+    Xpos, // front
+    Ypos, // left
+    Zpos, // top
+    Xneg, // back
+    Yneg, // right
+    Zneg  // bottom
+  };
+
+  //! Empty constructor.
+  OcctJniRenderer()
+  {
+    if (OcctJniActivity.areNativeLoaded)
+    {
+      myCppViewer = cppCreate();
+    }
+  }
+
+  //! Open file.
+  public void open (String thePath)
+  {
+    if (myCppViewer != 0)
+    {
+      cppOpen (myCppViewer, thePath);
+    }
+  }
+
+  //! Update viewer.
+  public void onDrawFrame (GL10 theGl)
+  {
+    if (myCppViewer != 0)
+    {
+      cppRedraw (myCppViewer);
+    }
+  }
+
+  //! (re)initialize viewer.
+  public void onSurfaceChanged (GL10 theGl, int theWidth, int theHeight)
+  {
+    if (myCppViewer != 0)
+    {
+      cppResize (myCppViewer, theWidth, theHeight);
+    }
+  }
+
+  public void onSurfaceCreated (GL10 theGl, EGLConfig theEglConfig)
+  {
+    if (myCppViewer != 0)
+    {
+      cppInit (myCppViewer);
+    }
+  }
+
+  //! Initialize rotation (remember first point position)
+  public void onStartRotation (int theStartX, int theStartY)
+  {
+    if (myCppViewer != 0)
+    {
+      cppStartRotation (myCppViewer, theStartX, theStartY);
+    }
+  }
+
+  //! Perform rotation (relative to first point)
+  public void onRotation (int theX, int theY)
+  {
+    if (myCppViewer != 0)
+    {
+      cppOnRotation (myCppViewer, theX, theY);
+    }
+  }
+
+  //! Perform panning
+  public void onPanning (int theDX, int theDY)
+  {
+    if (myCppViewer != 0)
+    {
+      cppOnPanning (myCppViewer, theDX, theDY);
+    }
+  }
+
+  //! Perform selection
+  public void onClick (int theX, int theY)
+  {
+    if (myCppViewer != 0)
+    {
+      cppOnClick (myCppViewer, theX, theY);
+    }
+  }
+
+  //! Stop previously active action (e.g. discard first rotation point)
+  public void onStopAction()
+  {
+    if (myCppViewer != 0)
+    {
+      cppStopAction (myCppViewer);
+    }
+  }
+
+  //! Fit All
+  public void fitAll()
+  {
+    if (myCppViewer != 0)
+    {
+      cppFitAll (myCppViewer);
+    }
+  }
+
+  //! Move camera
+  public void setProj (TypeOfOrientation theProj)
+  {
+    if (myCppViewer == 0)
+    {
+      return;
+    }
+
+    switch (theProj)
+    {
+      case Xpos: cppSetXposProj (myCppViewer); break;
+      case Ypos: cppSetYposProj (myCppViewer); break;
+      case Zpos: cppSetZposProj (myCppViewer); break;
+      case Xneg: cppSetXnegProj (myCppViewer); break;
+      case Yneg: cppSetYnegProj (myCppViewer); break;
+      case Zneg: cppSetZnegProj (myCppViewer); break;
+    }
+  }
+
+  //! Post message to the text view.
+  public void postMessage (String theText)
+  {
+    OcctJniLogger.postMessage (theText);
+  }
+
+  //! Create instance of C++ class
+  private native long cppCreate();
+
+  //! Destroy instance of C++ class
+  private native void cppDestroy (long theCppPtr);
+
+  //! Initialize OCCT viewer (steal OpenGL ES context bound to this thread)
+  private native void cppInit    (long theCppPtr);
+
+  //! Resize OCCT viewer
+  private native void cppResize  (long theCppPtr, int theWidth, int theHeight);
+
+  //! Open CAD file
+  private native void cppOpen    (long theCppPtr, String thePath);
+
+  //! Handle detection in the viewer
+  private native void cppMoveTo  (long theCppPtr, int theX, int theY);
+
+  //! Redraw OCCT viewer
+  private native void cppRedraw  (long theCppPtr);
+
+  //! Fit All
+  private native void cppFitAll  (long theCppPtr);
+
+  //! Move camera
+  private native void cppSetXposProj (long theCppPtr);
+
+  //! Move camera
+  private native void cppSetYposProj (long theCppPtr);
+
+  //! Move camera
+  private native void cppSetZposProj (long theCppPtr);
+
+  //! Move camera
+  private native void cppSetXnegProj (long theCppPtr);
+
+  //! Move camera
+  private native void cppSetYnegProj (long theCppPtr);
+
+  //! Move camera
+  private native void cppSetZnegProj (long theCppPtr);
+
+  //! Initialize rotation
+  private native void cppStartRotation (long theCppPtr, int theStartX, int theStartY);
+
+  //! Perform rotation
+  private native void cppOnRotation    (long theCppPtr, int theX,  int theY);
+
+  //! Perform panning
+  private native void cppOnPanning     (long theCppPtr, int theDX, int theDY);
+
+  //! Perform selection
+  private native void cppOnClick       (long theCppPtr, int theX,  int theY);
+
+  //! Stop action (rotation / panning / scaling)
+  private native void cppStopAction    (long theCppPtr);
+
+  private long myCppViewer = 0;   //!< pointer to c++ class instance
+
+}
diff --git a/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniView.java b/samples/java/jniviewer/app/src/main/java/com/opencascade/jnisample/OcctJniView.java
new file mode 100644 (file)
index 0000000..7909d9c
--- /dev/null
@@ -0,0 +1,332 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+package com.opencascade.jnisample;
+
+import android.app.ActionBar.LayoutParams;
+import android.content.Context;
+import android.graphics.PointF;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.MotionEvent;
+import android.widget.RelativeLayout;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+
+//! OpenGL ES 2.0+ view.
+//! Performs rendering in parallel thread.
+class OcctJniView extends GLSurfaceView
+{
+
+  // ! Default constructor.
+  public OcctJniView (Context      theContext,
+                      AttributeSet theAttrs)
+  {
+    super (theContext, theAttrs);
+
+    setPreserveEGLContextOnPause (true);
+    setEGLContextFactory (new ContextFactory());
+    setEGLConfigChooser  (new ConfigChooser());
+
+    RelativeLayout.LayoutParams aLParams = new RelativeLayout.LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+    aLParams.addRule (RelativeLayout.ALIGN_TOP);
+
+    myRenderer = new OcctJniRenderer();
+    setRenderer (myRenderer);
+  }
+
+  //! Open file.
+  public void open (String thePath)
+  {
+    final String aPath = thePath;
+    queueEvent (new Runnable() { public void run() { myRenderer.open (aPath); }});
+  }
+
+  //! Create OpenGL ES 2.0+ context
+  private static class ContextFactory implements GLSurfaceView.EGLContextFactory
+  {
+    private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+    public EGLContext createContext (EGL10      theEgl,
+                                     EGLDisplay theEglDisplay,
+                                     EGLConfig  theEglConfig)
+    {
+      if (theEglConfig == null)
+      {
+        return null;
+      }
+
+      // reset EGL errors stack
+      int anError = EGL10.EGL_SUCCESS;
+      while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS) {}
+
+      int[]      anAttribs   = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+      EGLContext aEglContext = theEgl.eglCreateContext (theEglDisplay, theEglConfig, EGL10.EGL_NO_CONTEXT, anAttribs);
+
+      while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS)
+      {
+        OcctJniLogger.postMessage ("Error: eglCreateContext() " + String.format ("0x%x", anError));
+      }
+      return aEglContext;
+    }
+
+    public void destroyContext (EGL10      theEgl,
+                                EGLDisplay theEglDisplay,
+                                EGLContext theEglContext)
+    {
+      theEgl.eglDestroyContext (theEglDisplay, theEglContext);
+    }
+  }
+
+  //! Search for RGB24 config with depth and stencil buffers
+  private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser
+  {
+    //! Reset EGL errors stack
+    private void popEglErrors (EGL10 theEgl)
+    {
+      int anError = EGL10.EGL_SUCCESS;
+      while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS)
+      {
+        OcctJniLogger.postMessage ("EGL Error: " + String.format ("0x%x", anError));
+      }
+    }
+
+    //! Auxiliary method to dump EGL configuration - for debugging purposes
+    @SuppressWarnings("unused")
+    private void printConfig (EGL10      theEgl,
+                              EGLDisplay theEglDisplay,
+                              EGLConfig  theEglConfig)
+    {
+      int[] THE_ATTRIBS =
+      {
+        EGL10.EGL_BUFFER_SIZE, EGL10.EGL_ALPHA_SIZE, EGL10.EGL_BLUE_SIZE, EGL10.EGL_GREEN_SIZE, EGL10.EGL_RED_SIZE, EGL10.EGL_DEPTH_SIZE, EGL10.EGL_STENCIL_SIZE,
+        EGL10.EGL_CONFIG_CAVEAT,
+        EGL10.EGL_CONFIG_ID,
+        EGL10.EGL_LEVEL,
+        EGL10.EGL_MAX_PBUFFER_HEIGHT, EGL10.EGL_MAX_PBUFFER_PIXELS, EGL10.EGL_MAX_PBUFFER_WIDTH,
+        EGL10.EGL_NATIVE_RENDERABLE,  EGL10.EGL_NATIVE_VISUAL_ID,   EGL10.EGL_NATIVE_VISUAL_TYPE,
+        0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
+        EGL10.EGL_SAMPLES, EGL10.EGL_SAMPLE_BUFFERS,
+        EGL10.EGL_SURFACE_TYPE,
+        EGL10.EGL_TRANSPARENT_TYPE, EGL10.EGL_TRANSPARENT_RED_VALUE, EGL10.EGL_TRANSPARENT_GREEN_VALUE, EGL10.EGL_TRANSPARENT_BLUE_VALUE,
+        0x3039, 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGB, EGL10.EGL_BIND_TO_TEXTURE_RGBA,
+        0x303B, 0x303C, // EGL10.EGL_MIN_SWAP_INTERVAL, EGL10.EGL_MAX_SWAP_INTERVAL
+        EGL10.EGL_LUMINANCE_SIZE, EGL10.EGL_ALPHA_MASK_SIZE,
+        EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RENDERABLE_TYPE,
+        0x3042 // EGL10.EGL_CONFORMANT
+      };
+      String[] THE_NAMES =
+      {
+        "EGL_BUFFER_SIZE", "EGL_ALPHA_SIZE", "EGL_BLUE_SIZE", "EGL_GREEN_SIZE", "EGL_RED_SIZE", "EGL_DEPTH_SIZE", "EGL_STENCIL_SIZE",
+        "EGL_CONFIG_CAVEAT",
+        "EGL_CONFIG_ID",
+        "EGL_LEVEL",
+        "EGL_MAX_PBUFFER_HEIGHT", "EGL_MAX_PBUFFER_PIXELS", "EGL_MAX_PBUFFER_WIDTH",
+        "EGL_NATIVE_RENDERABLE",  "EGL_NATIVE_VISUAL_ID",   "EGL_NATIVE_VISUAL_TYPE",
+        "EGL_PRESERVED_RESOURCES",
+        "EGL_SAMPLES", "EGL_SAMPLE_BUFFERS",
+        "EGL_SURFACE_TYPE",
+        "EGL_TRANSPARENT_TYPE", "EGL_TRANSPARENT_RED_VALUE", "EGL_TRANSPARENT_GREEN_VALUE", "EGL_TRANSPARENT_BLUE_VALUE",
+        "EGL_BIND_TO_TEXTURE_RGB", "EGL_BIND_TO_TEXTURE_RGBA",
+        "EGL_MIN_SWAP_INTERVAL", "EGL_MAX_SWAP_INTERVAL",
+        "EGL_LUMINANCE_SIZE", "EGL_ALPHA_MASK_SIZE",
+        "EGL_COLOR_BUFFER_TYPE", "EGL_RENDERABLE_TYPE",
+        "EGL_CONFORMANT"
+      };
+      int[] aValue = new int[1];
+      for (int anAttrIter = 0; anAttrIter < THE_ATTRIBS.length; ++anAttrIter)
+      {
+        int    anAttr = THE_ATTRIBS[anAttrIter];
+        String aName  = THE_NAMES  [anAttrIter];
+        if (theEgl.eglGetConfigAttrib (theEglDisplay, theEglConfig, anAttr, aValue))
+        {
+          OcctJniLogger.postMessage (String.format ("  %s: %d\n", aName, aValue[0]));
+        }
+        else
+        {
+          popEglErrors (theEgl);
+        }
+      }
+    }
+
+    //! Interface implementation
+    public EGLConfig chooseConfig (EGL10      theEgl,
+                                   EGLDisplay theEglDisplay)
+    {
+      int EGL_OPENGL_ES2_BIT = 4;
+      int[] aCfgAttribs =
+      {
+        EGL10.EGL_RED_SIZE,     8,
+        EGL10.EGL_GREEN_SIZE,   8,
+        EGL10.EGL_BLUE_SIZE,    8,
+        EGL10.EGL_ALPHA_SIZE,   0,
+        EGL10.EGL_DEPTH_SIZE,  24,
+        EGL10.EGL_STENCIL_SIZE, 8,
+        EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+        EGL10.EGL_NONE
+      };
+
+      EGLConfig aConfigs[] = new EGLConfig[1];
+      int[]     aNbConfigs = new int[1];
+      if (!theEgl.eglChooseConfig (theEglDisplay, aCfgAttribs, aConfigs, 1, aNbConfigs)
+       || aConfigs[0] == null)
+      {
+        aCfgAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
+        popEglErrors (theEgl);
+        if (!theEgl.eglChooseConfig (theEglDisplay, aCfgAttribs, aConfigs, 1, aNbConfigs)
+         || aConfigs[0] == null)
+        {
+          OcctJniLogger.postMessage ("Error: eglChooseConfig() has failed!");
+          return null;
+        }
+      }
+
+      //printConfig (theEgl, theEglDisplay, aConfigs[0]);
+      return aConfigs[0];
+    }
+  }
+
+  //! Callback to handle touch events
+  @Override public boolean onTouchEvent (MotionEvent theEvent)
+  {
+    int aPointerIndex = theEvent.getActionIndex();
+    int aPointerId    = theEvent.getPointerId (aPointerIndex);
+    int aMaskedAction = theEvent.getActionMasked();
+    switch (aMaskedAction)
+    {
+      case MotionEvent.ACTION_DOWN:
+      case MotionEvent.ACTION_POINTER_DOWN:
+      {
+        PointF aPntLast = null;
+        if (myActivePointers.size() >= 1)
+        {
+          aPntLast = myActivePointers.get (myActivePointers.keyAt (0));
+        }
+
+        final PointF aPnt = new PointF();
+        aPnt.x = theEvent.getX (aPointerIndex);
+        aPnt.y = theEvent.getY (aPointerIndex);
+        myActivePointers.put (aPointerId, aPnt);
+
+        switch (myActivePointers.size())
+        {
+          case 1:
+          {
+            final int aStartX = (int )aPnt.x;
+            final int aStartY = (int )aPnt.y;
+            queueEvent (new Runnable() { public void run() { myRenderer.onStartRotation (aStartX, aStartY); }});
+            break;
+          }
+          case 2:
+          {
+            myPanFrom.x = (aPntLast.x + aPnt.x) * 0.5f;
+            myPanFrom.y = (aPntLast.y + aPnt.y) * 0.5f;
+            break;
+          }
+        }
+
+        break;
+      }
+      case MotionEvent.ACTION_MOVE:
+      {
+        for (int aNbPointers = theEvent.getPointerCount(), aPntIter = 0; aPntIter < aNbPointers; ++aPntIter)
+        {
+          PointF aPnt = myActivePointers.get (theEvent.getPointerId (aPntIter));
+          if (aPnt != null)
+          {
+            aPnt.x = theEvent.getX (aPntIter);
+            aPnt.y = theEvent.getY (aPntIter);
+          }
+        }
+
+        switch (myActivePointers.size())
+        {
+          case 1:
+          {
+            PointF aPnt = myActivePointers.get (theEvent.getPointerId (0));
+            final int anX = (int )aPnt.x;
+            final int anY = (int )aPnt.y;
+            queueEvent (new Runnable() { public void run() { myRenderer.onRotation (anX, anY); }});
+            break;
+          }
+          case 2:
+          {
+            PointF aPnt1 = myActivePointers.get (myActivePointers.keyAt (0));
+            PointF aPnt2 = myActivePointers.get (myActivePointers.keyAt (1));
+            PointF aPntAver = new PointF ((aPnt1.x + aPnt2.x) * 0.5f,
+                                          (aPnt1.y + aPnt2.y) * 0.5f);
+            final int aDX = (int )(aPntAver.x - myPanFrom.x);
+            final int aDY = (int )(myPanFrom.y -aPntAver.y);
+            myPanFrom.x = aPntAver.x;
+            myPanFrom.y = aPntAver.y;
+            queueEvent (new Runnable() { public void run() { myRenderer.onPanning (aDX, aDY); }});
+          }
+        }
+        break;
+      }
+      case MotionEvent.ACTION_UP:
+      case MotionEvent.ACTION_POINTER_UP:
+      case MotionEvent.ACTION_CANCEL:
+      {
+        myActivePointers.remove (aPointerId);
+        if (myActivePointers.size() == 0)
+        {
+          final int aPressX      = (int )theEvent.getX (aPointerIndex);
+          final int aPressY      = (int )theEvent.getY (aPointerIndex);
+          double    aPressTimeMs = theEvent.getEventTime() - theEvent.getDownTime();
+          if (aPressTimeMs < 100.0)
+          {
+            queueEvent (new Runnable() { public void run() { myRenderer.onClick (aPressX, aPressY); }});
+            break;
+          }
+        }
+        else if (myActivePointers.size() == 1)
+        {
+          PointF    aPnt    = myActivePointers.get (myActivePointers.keyAt (0));
+          final int aStartX = (int )aPnt.x;
+          final int aStartY = (int )aPnt.y;
+          queueEvent (new Runnable() { public void run() { myRenderer.onStartRotation (aStartX, aStartY); }});
+        }
+        //queueEvent (new Runnable() { public void run() { myRenderer.onStopAction(); }});
+        break;
+      }
+    }
+    ///invalidate();
+    return true;
+  }
+
+  //! Fit All
+  public void fitAll()
+  {
+    queueEvent (new Runnable() { public void run() { myRenderer.fitAll(); }});
+  }
+
+  //! Move camera
+  public void setProj (final OcctJniRenderer.TypeOfOrientation theProj)
+  {
+    queueEvent (new Runnable() { public void run() { myRenderer.setProj (theProj); }});
+  }
+
+  //! OCCT viewer
+  private OcctJniRenderer     myRenderer = null;
+
+  //! Touch events cache
+  private SparseArray<PointF> myActivePointers = new SparseArray<PointF>();
+
+  //! Starting point for panning event
+  private PointF              myPanFrom  = new PointF (0.0f, 0.0f);
+
+}
diff --git a/samples/java/jniviewer/app/src/main/jni/CMakeLists.txt b/samples/java/jniviewer/app/src/main/jni/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4862495
--- /dev/null
@@ -0,0 +1,43 @@
+cmake_minimum_required(VERSION 3.4.1)
+
+set(HEADER_FILES OcctJni_MsgPrinter.hxx OcctJni_Viewer.hxx)
+set(SOURCE_FILES OcctJni_MsgPrinter.cxx OcctJni_Viewer.cxx)
+
+set (anOcctLibs
+  TKernel TKMath TKG2d TKG3d TKGeomBase TKBRep TKGeomAlgo TKTopAlgo TKShHealing TKMesh
+  # exchange
+  TKPrim TKBO TKBool TKFillet TKOffset
+  TKXSBase
+  TKIGES
+  TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP
+  # OCCT Visualization
+  TKService TKHLR TKV3d TKOpenGl
+)
+
+set(aLibDeps "")
+
+# OCCT libraries
+include_directories(${OCCT_ROOT}/inc)
+foreach(anOcctLib ${anOcctLibs})
+  add_library(lib_${anOcctLib} SHARED IMPORTED)
+  set_target_properties(lib_${anOcctLib} PROPERTIES IMPORTED_LOCATION ${OCCT_ROOT}/libs/${ANDROID_ABI}/lib${anOcctLib}.so)
+  list(APPEND aLibDeps lib_${anOcctLib})
+endforeach()
+
+# FreeType
+add_library(lib_FreeType SHARED IMPORTED)
+set_target_properties(lib_FreeType PROPERTIES IMPORTED_LOCATION ${FREETYPE_ROOT}/libs/${ANDROID_ABI}/libfreetype.so)
+list(APPEND aLibDeps lib_FreeType)
+
+# FreeImage - uncomment, if OCCT was built with FreeImage
+#add_library(lib_FreeImage SHARED IMPORTED)
+#set_target_properties(lib_FreeImage PROPERTIES IMPORTED_LOCATION ${FREETYPE_ROOT}/libs/${ANDROID_ABI}/libfreeimage.so)
+#list(APPEND aLibDeps lib_FreeImage)
+
+# system libraries
+list(APPEND aLibDeps EGL GLESv2 log android)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -frtti -fexceptions -fpermissive")
+
+add_library(TKJniSample SHARED ${SOURCE_FILES})
+target_link_libraries(TKJniSample ${aLibDeps})
diff --git a/samples/java/jniviewer/app/src/main/jni/OcctJni_MsgPrinter.cxx b/samples/java/jniviewer/app/src/main/jni/OcctJni_MsgPrinter.cxx
new file mode 100644 (file)
index 0000000..3c12ca6
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include "OcctJni_MsgPrinter.hxx"
+
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_ExtendedString.hxx>
+
+#include <android/log.h>
+
+IMPLEMENT_STANDARD_RTTIEXT(OcctJni_MsgPrinter, Message_Printer)
+
+// =======================================================================
+// function : OcctJni_MsgPrinter
+// purpose  :
+// =======================================================================
+OcctJni_MsgPrinter::OcctJni_MsgPrinter (JNIEnv* theJEnv,
+                                        jobject theJObj)
+: myJEnv (theJEnv),
+  myJObj (theJEnv->NewGlobalRef (theJObj)),
+  myJMet (NULL)
+{
+  jclass aJClass = theJEnv->GetObjectClass (theJObj);
+  myJMet = theJEnv->GetMethodID (aJClass, "postMessage", "(Ljava/lang/String;)V");
+  if (myJMet == NULL)
+  {
+    __android_log_write (ANDROID_LOG_FATAL, "jniSample", "Broken initialization of OcctJni_MsgPrinter!");
+  }
+}
+
+// =======================================================================
+// function : ~OcctJni_MsgPrinter
+// purpose  :
+// =======================================================================
+OcctJni_MsgPrinter::~OcctJni_MsgPrinter()
+{
+  //myJEnv->DeleteGlobalRef (myJObj);
+}
+
+// =======================================================================
+// function : send
+// purpose  :
+// =======================================================================
+void OcctJni_MsgPrinter::send (const TCollection_AsciiString& theString,
+                               const Message_Gravity theGravity) const
+{
+  if (theGravity < myTraceLevel)
+  {
+    return;
+  }
+
+  ///__android_log_write (ANDROID_LOG_DEBUG, "OcctJni_MsgPrinter", (TCollection_AsciiString(" @@ ") + theString).ToCString());
+  if (myJMet == NULL)
+  {
+    return;
+  }
+
+  jstring aJStr = myJEnv->NewStringUTF ((theString + "\n").ToCString());
+  myJEnv->CallObjectMethod (myJObj, myJMet, aJStr);
+  myJEnv->DeleteLocalRef (aJStr);
+}
diff --git a/samples/java/jniviewer/app/src/main/jni/OcctJni_MsgPrinter.hxx b/samples/java/jniviewer/app/src/main/jni/OcctJni_MsgPrinter.hxx
new file mode 100644 (file)
index 0000000..6557255
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef OcctJni_MsgPrinter_H
+#define OcctJni_MsgPrinter_H
+
+#include <Message_Printer.hxx>
+
+#include <jni.h>
+
+// Class providing connection between messenger interfaces in C++ and Java layers.
+class OcctJni_MsgPrinter : public Message_Printer
+{
+public:
+
+  //! Default constructor
+  OcctJni_MsgPrinter (JNIEnv* theJEnv,
+                      jobject theJObj);
+
+  //! Destructor.
+  ~OcctJni_MsgPrinter();
+
+protected:
+
+  //! Main printing method
+  virtual void send (const TCollection_AsciiString& theString,
+                     const Message_Gravity theGravity) const override;
+
+private:
+
+  JNIEnv*   myJEnv;
+  jobject   myJObj;
+  jmethodID myJMet;
+
+public:
+
+  DEFINE_STANDARD_RTTIEXT(OcctJni_MsgPrinter,Message_Printer)
+
+};
+
+DEFINE_STANDARD_HANDLE(OcctJni_MsgPrinter, Message_Printer)
+
+#endif // OcctJni_MsgPrinter_H
diff --git a/samples/java/jniviewer/app/src/main/jni/OcctJni_Viewer.cxx b/samples/java/jniviewer/app/src/main/jni/OcctJni_Viewer.cxx
new file mode 100644 (file)
index 0000000..eac9b52
--- /dev/null
@@ -0,0 +1,815 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include "OcctJni_Viewer.hxx"
+#include "OcctJni_MsgPrinter.hxx"
+
+#include <AIS_Shape.hxx>
+#include <Aspect_NeutralWindow.hxx>
+#include <Image_AlienPixMap.hxx>
+#include <BRepTools.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_MsgFile.hxx>
+#include <Message_PrinterSystemLog.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <OSD_Environment.hxx>
+#include <OSD_Timer.hxx>
+#include <Standard_Version.hxx>
+
+#include <BRepPrimAPI_MakeBox.hxx>
+
+#include <STEPControl_Reader.hxx>
+#include <IGESControl_Reader.hxx>
+#include <XSControl_WorkSession.hxx>
+
+#include <EGL/egl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <jni.h>
+
+//! @return true if file exists
+static bool isFileExist (const TCollection_AsciiString& thePath)
+{
+  struct stat64 aStatBuffer;
+  return stat64 (thePath.ToCString(), &aStatBuffer) == 0;
+}
+
+//! Cut-off the last split character from the path and everything after it.
+static TCollection_AsciiString getParentDir (const TCollection_AsciiString& thePath)
+{
+  TCollection_AsciiString aPath = thePath;
+  char* aSplitter = (char* )aPath.ToCString();
+  for (char* anIter = aSplitter; *anIter != '\0'; ++anIter)
+  {
+    if (*anIter == '\\'
+     || *anIter == '/')
+    {
+      aSplitter = anIter;
+    }
+  }
+  *aSplitter = '\0'; // cut off file name or trailing folder
+  return TCollection_AsciiString (aPath.ToCString());
+}
+
+//! Set environment variable theVarName indicating location of resource
+//! file theFile so as to correspond to actual location of this file.
+//!
+//! The resource file is searched in directory where Test.Draw.dll is located,
+//! and if not found - also in subdirectory ../res from there.
+//! If file is found, environment variable is set for C subsystem.
+//! Otherwise, environment is not changed.
+//!
+//! If theToAddFileName is true, complete file name is set as value of the variable,
+//! if theToAddFileName is false, only path is set.
+Standard_Boolean setResourceEnv (const TCollection_AsciiString& theVarName,
+                                 const TCollection_AsciiString& theRoot,
+                                 const TCollection_AsciiString& theFile,
+                                 const Standard_Boolean         theToAddFileName)
+{
+  // use location of current assembly to figure out possible location of resource
+  TCollection_AsciiString aBaseDir = theRoot;
+
+  // check the same directory where binary is located
+  if (!isFileExist (aBaseDir + "/" + theFile))
+  {
+    // check subdirectory ../res
+    aBaseDir = getParentDir (aBaseDir) + "/res";
+    if (!isFileExist (aBaseDir + "/" + theFile))
+    {
+      return Standard_False;
+    }
+  }
+
+  // set C library environment
+  if (theToAddFileName)
+  {
+    aBaseDir = aBaseDir + "/" + theFile;
+  }
+
+  OSD_Environment anEnv (theVarName, aBaseDir);
+  anEnv.Build();
+  return Standard_True;
+}
+
+// =======================================================================
+// function : OcctJni_Viewer
+// purpose  :
+// =======================================================================
+OcctJni_Viewer::OcctJni_Viewer()
+{
+#ifndef NDEBUG
+  // Register printer for logging messages into global Android log.
+  // Should never be used in production (or specify higher gravity for logging only failures).
+  Handle(Message_Messenger) aMsgMgr = Message::DefaultMessenger();
+  aMsgMgr->RemovePrinters (STANDARD_TYPE (Message_PrinterSystemLog));
+  aMsgMgr->AddPrinter (new Message_PrinterSystemLog ("OcctJni_Viewer"));
+#endif
+
+  // prepare necessary environment
+  TCollection_AsciiString aResRoot = "/data/data/com.opencascade.jnisample/files";
+
+  setResourceEnv ("CSF_XSMessage", aResRoot + "/XSMessage", "XSTEP.us", Standard_False);
+  setResourceEnv ("CSF_SHMessage", aResRoot + "/XSMessage", "SHAPE.us", Standard_False);
+}
+
+// =======================================================================
+// function : init
+// purpose  :
+// =======================================================================
+bool OcctJni_Viewer::init()
+{
+  EGLint aCfgId = 0;
+  int aWidth = 0, aHeight = 0;
+  EGLDisplay anEglDisplay = eglGetCurrentDisplay();
+  EGLContext anEglContext = eglGetCurrentContext();
+  EGLSurface anEglSurf    = eglGetCurrentSurface (EGL_DRAW);
+  if (anEglDisplay == EGL_NO_DISPLAY
+   || anEglContext == EGL_NO_CONTEXT
+   || anEglSurf    == EGL_NO_SURFACE)
+  {
+    Message::DefaultMessenger()->Send ("Error: No active EGL context!", Message_Fail);
+    release();
+    return false;
+  }
+
+  eglQuerySurface (anEglDisplay, anEglSurf, EGL_WIDTH,     &aWidth);
+  eglQuerySurface (anEglDisplay, anEglSurf, EGL_HEIGHT,    &aHeight);
+  eglQuerySurface (anEglDisplay, anEglSurf, EGL_CONFIG_ID, &aCfgId);
+  const EGLint aConfigAttribs[] = { EGL_CONFIG_ID, aCfgId, EGL_NONE };
+  EGLint       aNbConfigs = 0;
+  void*        anEglConfig = NULL;
+  if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE)
+  {
+    Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
+    release();
+    return false;
+  }
+
+  TCollection_AsciiString anEglInfo = TCollection_AsciiString()
+      + "\n  EGLVersion:     " + eglQueryString (anEglDisplay, EGL_VERSION)
+      + "\n  EGLVendor:      " + eglQueryString (anEglDisplay, EGL_VENDOR)
+      + "\n  EGLClient APIs: " + eglQueryString (anEglDisplay, EGL_CLIENT_APIS)
+      + "\n  GLvendor:       " + (const char* )glGetString (GL_VENDOR)
+      + "\n  GLdevice:       " + (const char* )glGetString (GL_RENDERER)
+      + "\n  GLversion:      " + (const char* )glGetString (GL_VERSION) + " [GLSL: " + (const char* )glGetString (GL_SHADING_LANGUAGE_VERSION) + "]";
+    ::Message::DefaultMessenger()->Send (anEglInfo, Message_Info);
+
+  if (!myViewer.IsNull())
+  {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
+    Handle(Aspect_NeutralWindow) aWindow = Handle(Aspect_NeutralWindow)::DownCast (myView->Window());
+    if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
+    {
+      Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized!", Message_Fail);
+      release();
+      return false;
+    }
+
+    aWindow->SetSize (aWidth, aHeight);
+    myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
+    return true;
+  }
+
+  Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False);
+  aDriver->ChangeOptions().buffersNoSwap = Standard_True;
+//aDriver->ChangeOptions().glslWarnings  = Standard_True; /// for debug only!
+  if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
+  {
+    Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized!", Message_Fail);
+    release();
+    return false;
+  }
+
+  // create viewer
+  myViewer = new V3d_Viewer (aDriver);
+  myViewer->SetDefaultBackgroundColor (Quantity_NOC_BLACK);
+  myViewer->SetDefaultLights();
+  myViewer->SetLightOn();
+
+  // create AIS context
+  myContext = new AIS_InteractiveContext (myViewer);
+  //myContext->SetDisplayMode (AIS_WireFrame, false);
+  myContext->SetDisplayMode (AIS_Shaded, false);
+
+  Handle(Aspect_NeutralWindow) aWindow = new Aspect_NeutralWindow();
+  aWindow->SetSize (aWidth, aHeight);
+  myView = myViewer->CreateView();
+
+  myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
+  myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER);
+
+  initContent();
+  return true;
+}
+
+// =======================================================================
+// function : release
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::release()
+{
+  myContext.Nullify();
+  myView.Nullify();
+  myViewer.Nullify();
+}
+
+// =======================================================================
+// function : resize
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::resize (int theWidth,
+                             int theHeight)
+{
+  if (myContext.IsNull())
+  {
+    Message::DefaultMessenger()->Send ("Resize failed - view is unavailable", Message_Fail);
+    return;
+  }
+
+  Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
+  Handle(Aspect_NeutralWindow) aWindow = Handle(Aspect_NeutralWindow)::DownCast (myView->Window());
+  aWindow->SetSize (theWidth, theHeight);
+  //myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed
+
+  EGLContext anEglContext = eglGetCurrentContext();
+  myView->SetImmediateUpdate (Standard_False);
+  myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
+  //saveSnapshot ("/sdcard/Download/tt.png", theWidth, theHeight);
+}
+
+// =======================================================================
+// function : initContent
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::initContent()
+{
+  myContext->RemoveAll (Standard_False);
+
+  OSD_Timer aTimer;
+  aTimer.Start();
+  if (!myShape.IsNull())
+  {
+    Handle(AIS_Shape) aShapePrs = new AIS_Shape (myShape);
+    myContext->Display (aShapePrs, Standard_False);
+  }
+  else
+  {
+    BRepPrimAPI_MakeBox aBuilder (1.0, 2.0, 3.0);
+    Handle(AIS_Shape) aShapePrs = new AIS_Shape (aBuilder.Shape());
+    myContext->Display (aShapePrs, Standard_False);
+  }
+  myView->FitAll();
+
+  aTimer.Stop();
+  Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Presentation computed in " + aTimer.ElapsedTime() + " seconds", Message_Info);
+}
+
+//! Load shape from IGES file
+static TopoDS_Shape loadIGES (const TCollection_AsciiString& thePath)
+{
+  TopoDS_Shape          aShape;
+  IGESControl_Reader    aReader;
+  IFSelect_ReturnStatus aReadStatus = IFSelect_RetFail;
+  try
+  {
+    aReadStatus = aReader.ReadFile (thePath.ToCString());
+  }
+  catch (Standard_Failure)
+  {
+    Message::DefaultMessenger()->Send ("Error: IGES reader, computation error", Message_Fail);
+    return aShape;
+  }
+
+  if (aReadStatus != IFSelect_RetDone)
+  {
+    Message::DefaultMessenger()->Send ("Error: IGES reader, bad file format", Message_Fail);
+    return aShape;
+  }
+
+  // now perform the translation
+  aReader.TransferRoots();
+  if (aReader.NbShapes() <= 0)
+  {
+    Handle(XSControl_WorkSession) aWorkSession = new XSControl_WorkSession();
+    aWorkSession->SelectNorm ("IGES");
+    aReader.SetWS (aWorkSession, Standard_True);
+    aReader.SetReadVisible (Standard_False);
+    aReader.TransferRoots();
+  }
+  if (aReader.NbShapes() <= 0)
+  {
+    Message::DefaultMessenger()->Send ("Error: IGES reader, no shapes has been found", Message_Fail);
+    return aShape;
+  }
+  return aReader.OneShape();
+  /*TopoDS_Shape anImportedShape = aReader.OneShape();
+
+  // apply sewing on the imported shape
+  BRepBuilderAPI_Sewing aTool (0.0);
+  aTool.SetNonManifoldMode  (Standard_False);
+  aTool.SetFloatingEdgesMode(Standard_True);
+  aTool.Load (anImportedShape);
+  aTool.Perform();
+  TopoDS_Shape aSewedShape = aTool.SewedShape();
+
+  if (aSewedShape.IsNull())
+  {
+    Message::DefaultMessenger()->Send ("Error: Sewing result is empty", Message_Fail);
+    return aShape;
+  }
+  if (aSewedShape.IsSame(anImportedShape))
+  {
+    aShape = anImportedShape;
+  }
+  else
+  {
+    // apply shape healing
+    ShapeFix_Shape aShapeFixer(aSewedShape);
+    aShapeFixer.FixSolidMode() = 1;
+    aShapeFixer.FixFreeShellMode() = 1;
+    aShapeFixer.FixFreeFaceMode() = 1;
+    aShapeFixer.FixFreeWireMode() = 0;
+    aShapeFixer.FixSameParameterMode() = 0;
+    aShapeFixer.FixVertexPositionMode() = 0;
+    aShape = aShapeFixer.Perform() ? aShapeFixer.Shape() : aSewedShape;
+  }
+  return aShape;*/
+}
+
+//! Load shape from STEP file
+static TopoDS_Shape loadSTEP (const TCollection_AsciiString& thePath)
+{
+  STEPControl_Reader    aReader;
+  IFSelect_ReturnStatus aReadStatus = IFSelect_RetFail;
+  try
+  {
+    aReadStatus = aReader.ReadFile (thePath.ToCString());
+  }
+  catch (Standard_Failure)
+  {
+    Message::DefaultMessenger()->Send ("Error: STEP reader, computation error", Message_Fail);
+    return TopoDS_Shape();
+  }
+
+  if (aReadStatus != IFSelect_RetDone)
+  {
+    Message::DefaultMessenger()->Send ("Error: STEP reader, bad file format", Message_Fail);
+    return TopoDS_Shape();
+  }
+  else if (aReader.NbRootsForTransfer() <= 0)
+  {
+    Message::DefaultMessenger()->Send ("Error: STEP reader, shape is empty", Message_Fail);
+    return TopoDS_Shape();
+  }
+
+  // now perform the translation
+  aReader.TransferRoots();
+  return aReader.OneShape();
+}
+
+// =======================================================================
+// function : open
+// purpose  :
+// =======================================================================
+bool OcctJni_Viewer::open (const TCollection_AsciiString& thePath)
+{
+  myShape.Nullify();
+  if (!myContext.IsNull())
+  {
+    myContext->RemoveAll (Standard_False);
+  }
+  if (thePath.IsEmpty())
+  {
+    return false;
+  }
+
+  OSD_Timer aTimer;
+  aTimer.Start();
+  TCollection_AsciiString aFormatStr;
+  const Standard_Integer  aLen = thePath.Length();
+  if (aLen >= 5
+  && thePath.Value (aLen - 4) == '.')
+  {
+    aFormatStr = thePath.SubString (aLen - 3, aLen);
+  }
+  else if (aLen >= 4
+   && thePath.Value (aLen - 3) == '.')
+  {
+    aFormatStr = thePath.SubString (aLen - 2, aLen);
+  }
+  else if (aLen >= 3
+        && thePath.Value (aLen - 2) == '.')
+  {
+    aFormatStr = thePath.SubString (aLen - 1, aLen);
+  }
+  aFormatStr.LowerCase();
+
+  TopoDS_Shape aShape;
+  if (aFormatStr == "stp"
+   || aFormatStr == "step")
+  {
+    aShape = loadSTEP (thePath);
+  }
+  else if (aFormatStr == "igs"
+        || aFormatStr == "iges")
+  {
+    aShape = loadIGES (thePath);
+  }
+  else
+      // if (aFormatStr == "brep"
+      //  || aFormatStr == "rle")
+  {
+    BRep_Builder aBuilder;
+    if (!BRepTools::Read (aShape, thePath.ToCString(), aBuilder))
+    {
+      Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Error: file '" + thePath + "' can not be opened!", Message_Info);
+      return false;
+    }
+  }
+  if (aShape.IsNull())
+  {
+    return false;
+  }
+  aTimer.Stop();
+  Message::DefaultMessenger()->Send (TCollection_AsciiString() + "File '" + thePath + "' loaded in " + aTimer.ElapsedTime() + " seconds", Message_Info);
+
+  myShape = aShape;
+  if (myContext.IsNull())
+  {
+    return true;
+  }
+
+  aTimer.Reset();
+  aTimer.Start();
+
+  Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape);
+  myContext->Display (aShapePrs, Standard_False);
+  myView->FitAll();
+
+  aTimer.Stop();
+  Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Presentation computed in " + aTimer.ElapsedTime() + " seconds", Message_Info);
+  return true;
+}
+
+// =======================================================================
+// function : saveSnapshot
+// purpose  :
+// =======================================================================
+bool OcctJni_Viewer::saveSnapshot (const TCollection_AsciiString& thePath,
+                                   int theWidth,
+                                   int theHeight)
+{
+  if (myContext.IsNull()
+   || thePath.IsEmpty())
+  {
+    Message::DefaultMessenger()->Send ("Image dump failed - view is unavailable", Message_Fail);
+    return false;
+  }
+
+  if (theWidth  < 1
+   || theHeight < 1)
+  {
+    myView->Window()->Size (theWidth, theHeight);
+  }
+  if (theWidth  < 1
+   || theHeight < 1)
+  {
+    Message::DefaultMessenger()->Send ("Image dump failed - view is unavailable", Message_Fail);
+    return false;
+  }
+
+  Image_AlienPixMap anAlienImage;
+  if (!anAlienImage.InitTrash (Image_PixMap::ImgBGRA, theWidth, theHeight))
+  {
+    Message::DefaultMessenger()->Send (TCollection_AsciiString() + "RGBA image " + theWidth + "x" + theHeight + " allocation failed", Message_Fail);
+    return false;
+  }
+
+  // OpenGL ES does not support fetching data in BGRA format
+  // while FreeImage does not support RGBA format.
+  Image_PixMap anImage;
+  anImage.InitWrapper (Image_PixMap::ImgRGBA,
+                       anAlienImage.ChangeData(),
+                       anAlienImage.SizeX(),
+                       anAlienImage.SizeY(),
+                       anAlienImage.SizeRowBytes());
+  if (!myView->ToPixMap (anImage, theWidth, theHeight, Graphic3d_BT_RGBA))
+  {
+    Message::DefaultMessenger()->Send (TCollection_AsciiString() + "View dump to the image " + theWidth + "x" + theHeight + " failed", Message_Fail);
+  }
+
+  for (Standard_Size aRow = 0; aRow < anAlienImage.SizeY(); ++aRow)
+  {
+    for (Standard_Size aCol = 0; aCol < anAlienImage.SizeX(); ++aCol)
+    {
+      Image_ColorRGBA& aPixel = anAlienImage.ChangeValue<Image_ColorRGBA> (aRow, aCol);
+      std::swap (aPixel.r(), aPixel.b());
+      //aPixel.a() = 1.0;
+    }
+  }
+
+  if (!anAlienImage.Save (thePath))
+  {
+    Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Image saving to path '" + thePath + "' failed", Message_Fail);
+    return false;
+  }
+  Message::DefaultMessenger()->Send (TCollection_AsciiString() + "View " + theWidth + "x" + theHeight + " dumped to image '" + thePath + "'", Message_Info);
+  return true;
+}
+
+// =======================================================================
+// function : redraw
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::redraw()
+{
+  if (myView.IsNull())
+  {
+    return;
+  }
+
+  myView->Redraw();
+}
+
+// =======================================================================
+// function : fitAll
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::fitAll()
+{
+  if (myView.IsNull())
+  {
+    return;
+  }
+
+  myView->FitAll (0.01, Standard_False);
+  myView->Invalidate();
+}
+
+// =======================================================================
+// function : startRotation
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::startRotation (int theStartX,
+                                    int theStartY)
+{
+  if (myView.IsNull())
+  {
+    return;
+  }
+
+  myView->StartRotation (theStartX, theStartY, 0.45);
+  myView->Invalidate();
+}
+
+// =======================================================================
+// function : onRotation
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::onRotation (int theX,
+                                 int theY)
+{
+  if (myView.IsNull())
+  {
+    return;
+  }
+
+  myView->Rotation (theX, theY);
+  myView->Invalidate();
+}
+
+// =======================================================================
+// function : onPanning
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::onPanning (int theDX,
+                                int theDY)
+{
+  if (myView.IsNull())
+  {
+    return;
+  }
+
+  myView->Pan (theDX, theDY);
+  myView->Invalidate();
+}
+
+// =======================================================================
+// function : onClick
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::onClick (int theX,
+                              int theY)
+{
+  if (myView.IsNull())
+  {
+    return;
+  }
+
+  myContext->MoveTo (theX, theY, myView, Standard_False);
+  myContext->Select (Standard_False);
+  myView->Invalidate();
+}
+
+// =======================================================================
+// function : stopAction
+// purpose  :
+// =======================================================================
+void OcctJni_Viewer::stopAction()
+{
+  if (myView.IsNull())
+  {
+    return;
+  }
+}
+
+#define jexp extern "C" JNIEXPORT
+
+jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppCreate (JNIEnv* theEnv,
+                                                                             jobject theObj)
+{
+  return jlong(new OcctJni_Viewer());
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppDestroy (JNIEnv* theEnv,
+                                                                             jobject theObj,
+                                                                             jlong   theCppPtr)
+{
+  delete (OcctJni_Viewer* )theCppPtr;
+
+  Handle(Message_Messenger) aMsgMgr = Message::DefaultMessenger();
+  aMsgMgr->RemovePrinters (STANDARD_TYPE (OcctJni_MsgPrinter));
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppRelease (JNIEnv* theEnv,
+                                                                             jobject theObj,
+                                                                             jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->release();
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppInit (JNIEnv* theEnv,
+                                                                          jobject theObj,
+                                                                          jlong   theCppPtr)
+{
+  Handle(Message_Messenger) aMsgMgr = Message::DefaultMessenger();
+  aMsgMgr->RemovePrinters (STANDARD_TYPE (OcctJni_MsgPrinter));
+  aMsgMgr->AddPrinter (new OcctJni_MsgPrinter (theEnv, theObj));
+  ((OcctJni_Viewer* )theCppPtr)->init();
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppResize (JNIEnv* theEnv,
+                                                                            jobject theObj,
+                                                                            jlong   theCppPtr,
+                                                                            jint    theWidth,
+                                                                            jint    theHeight)
+{
+  ((OcctJni_Viewer* )theCppPtr)->resize (theWidth, theHeight);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOpen (JNIEnv* theEnv,
+                                                                          jobject theObj,
+                                                                          jlong   theCppPtr,
+                                                                          jstring thePath)
+{
+  const char* aPathPtr = theEnv->GetStringUTFChars (thePath, 0);
+  const TCollection_AsciiString aPath (aPathPtr);
+  theEnv->ReleaseStringUTFChars (thePath, aPathPtr);
+  ((OcctJni_Viewer* )theCppPtr)->open (aPath);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppRedraw (JNIEnv* theEnv,
+                                                                            jobject theObj,
+                                                                            jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->redraw();
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetAxoProj (JNIEnv* theEnv,
+                                                                                jobject theObj,
+                                                                                jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_XposYnegZpos);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetXposProj (JNIEnv* theEnv,
+                                                                                 jobject theObj,
+                                                                                 jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Xpos);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetYposProj (JNIEnv* theEnv,
+                                                                                 jobject theObj,
+                                                                                 jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Ypos);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetZposProj (JNIEnv* theEnv,
+                                                                                 jobject theObj,
+                                                                                 jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Zpos);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetXnegProj (JNIEnv* theEnv,
+                                                                                 jobject theObj,
+                                                                                 jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Xneg);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetYnegProj (JNIEnv* theEnv,
+                                                                                 jobject theObj,
+                                                                                 jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Yneg);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetZnegProj (JNIEnv* theEnv,
+                                                                                 jobject theObj,
+                                                                                 jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Zneg);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppFitAll (JNIEnv* theEnv,
+                                                                            jobject theObj,
+                                                                            jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->fitAll();
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppStartRotation (JNIEnv* theEnv,
+                                                                                   jobject theObj,
+                                                                                   jlong   theCppPtr,
+                                                                                   jint    theStartX,
+                                                                                   jint    theStartY)
+{
+  ((OcctJni_Viewer* )theCppPtr)->startRotation (theStartX, theStartY);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnRotation (JNIEnv* theEnv,
+                                                                                jobject theObj,
+                                                                                jlong   theCppPtr,
+                                                                                jint    theX,
+                                                                                jint    theY)
+{
+  ((OcctJni_Viewer* )theCppPtr)->onRotation (theX, theY);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnPanning (JNIEnv* theEnv,
+                                                                               jobject theObj,
+                                                                               jlong   theCppPtr,
+                                                                               jint    theDX,
+                                                                               jint    theDY)
+{
+  ((OcctJni_Viewer* )theCppPtr)->onPanning (theDX, theDY);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnClick (JNIEnv* theEnv,
+                                                                             jobject theObj,
+                                                                             jlong   theCppPtr,
+                                                                             jint    theX,
+                                                                             jint    theY)
+{
+  ((OcctJni_Viewer* )theCppPtr)->onClick (theX, theY);
+}
+
+jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppStopAction (JNIEnv* theEnv,
+                                                                                jobject theObj,
+                                                                                jlong   theCppPtr)
+{
+  ((OcctJni_Viewer* )theCppPtr)->stopAction();
+}
+
+jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMajorVersion (JNIEnv* theEnv,
+                                                                                       jobject theObj)
+{
+  return OCC_VERSION_MAJOR;
+}
+
+jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMinorVersion (JNIEnv* theEnv,
+                                                                                       jobject theObj)
+{
+  return OCC_VERSION_MINOR;
+}
+
+jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMicroVersion (JNIEnv* theEnv,
+                                                                                       jobject theObj)
+{
+  return OCC_VERSION_MAINTENANCE;
+}
diff --git a/samples/java/jniviewer/app/src/main/jni/OcctJni_Viewer.hxx b/samples/java/jniviewer/app/src/main/jni/OcctJni_Viewer.hxx
new file mode 100644 (file)
index 0000000..f8b8369
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AIS_InteractiveContext.hxx>
+#include <TopoDS_Shape.hxx>
+#include <V3d_Viewer.hxx>
+#include <V3d_View.hxx>
+
+//! Main C++ back-end for activity.
+class OcctJni_Viewer
+{
+
+public:
+
+  //! Empty constructor
+  OcctJni_Viewer();
+
+  //! Initialize the viewer
+  bool init();
+
+  //! Release the viewer
+  void release();
+
+  //! Resize the viewer
+  void resize (int theWidth,
+               int theHeight);
+
+  //! Open CAD file
+  bool open (const TCollection_AsciiString& thePath);
+
+  //! Take snapshot
+  bool saveSnapshot (const TCollection_AsciiString& thePath,
+                     int theWidth  = 0,
+                     int theHeight = 0);
+
+  //! Viewer update.
+  void redraw();
+
+  //! Move camera
+  void setProj (V3d_TypeOfOrientation theProj) { if (!myView.IsNull()) myView->SetProj (theProj); }
+
+  //! Fit All.
+  void fitAll();
+
+  //! Start rotation (remember first point position)
+  void startRotation (int theStartX,
+                      int theStartY);
+
+  //! Perform rotation (relative to first point)
+  void onRotation (int theX,
+                   int theY);
+
+  //! Perform panning
+  void onPanning (int theDX,
+                  int theDY);
+
+  //! Perform selection
+  void onClick (int theX,
+                int theY);
+
+  //! Stop previously started action
+  void stopAction();
+
+protected:
+
+  //! Reset viewer content.
+  void initContent();
+
+protected:
+
+  Handle(V3d_Viewer)             myViewer;
+  Handle(V3d_View)               myView;
+  Handle(AIS_InteractiveContext) myContext;
+  TopoDS_Shape                   myShape;
+
+};
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/close_l.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/close_l.png
new file mode 100644 (file)
index 0000000..0125c4a
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/close_l.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/close_p.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/close_p.png
new file mode 100644 (file)
index 0000000..b5ce8bd
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/close_p.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/fit.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/fit.png
new file mode 100644 (file)
index 0000000..70daee1
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/fit.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/ic_launcher.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..d27ba82
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/info.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/info.png
new file mode 100644 (file)
index 0000000..88d27c8
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/info.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/info_image.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/info_image.png
new file mode 100644 (file)
index 0000000..bac9bea
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/info_image.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/message.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/message.png
new file mode 100644 (file)
index 0000000..a3dc8cc
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/message.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open.png
new file mode 100644 (file)
index 0000000..68e5265
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open_l.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open_l.png
new file mode 100644 (file)
index 0000000..6069ce3
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open_l.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open_p.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open_p.png
new file mode 100644 (file)
index 0000000..c0898e6
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/open_p.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_back.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_back.png
new file mode 100644 (file)
index 0000000..77ab199
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_back.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_bottom.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_bottom.png
new file mode 100644 (file)
index 0000000..b0bb012
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_bottom.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_front.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_front.png
new file mode 100644 (file)
index 0000000..b93d4d3
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_front.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_left.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_left.png
new file mode 100644 (file)
index 0000000..bce95df
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_left.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_right.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_right.png
new file mode 100644 (file)
index 0000000..8cdb338
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_right.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_top.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_top.png
new file mode 100644 (file)
index 0000000..4ad098f
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/proj_top.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-hdpi/view.png b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/view.png
new file mode 100644 (file)
index 0000000..76ce879
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-hdpi/view.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-mdpi/ic_launcher.png b/samples/java/jniviewer/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..4b86dbf
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-xhdpi/ic_launcher.png b/samples/java/jniviewer/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..cd79bea
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/samples/java/jniviewer/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..a34301f
Binary files /dev/null and b/samples/java/jniviewer/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/samples/java/jniviewer/app/src/main/res/layout/activity_main.xml b/samples/java/jniviewer/app/src/main/res/layout/activity_main.xml
new file mode 100644 (file)
index 0000000..e7f3ebf
--- /dev/null
@@ -0,0 +1,166 @@
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+android:id="@+id/panel_main"\r
+android:layout_width="fill_parent"\r
+android:layout_height="fill_parent"\r
+android:stretchColumns="1">\r
+\r
+    <LinearLayout android:layout_height="fill_parent"\r
+    android:layout_width="fill_parent"\r
+    android:id="@+id/linearLayout2">\r
+\r
+        <FrameLayout\r
+        android:id="@+id/submenu_group"\r
+        android:layout_width="fill_parent"\r
+        android:layout_height="fill_parent" >\r
+\r
+            <com.opencascade.jnisample.OcctJniView\r
+            android:id="@+id/custom_view"\r
+            android:layout_width="fill_parent"\r
+            android:layout_height="fill_parent"\r
+            android:layout_gravity="bottom|end" >\r
+            </com.opencascade.jnisample.OcctJniView>\r
+\r
+            <ImageButton\r
+            android:id="@+id/scroll_btn"\r
+            style="?android:borderlessButtonStyle"\r
+            android:layout_width="match_parent"\r
+            android:layout_height="wrap_content"\r
+            android:background="@null"\r
+            android:src="@drawable/close_p" />\r
+\r
+            <LinearLayout\r
+            android:id="@+id/panel_menu"\r
+            android:layout_width="fill_parent"\r
+            android:layout_height="wrap_content"\r
+            android:orientation="horizontal" >\r
+                <ImageButton\r
+                android:id="@+id/open"\r
+                style="?android:borderlessButtonStyle"\r
+                android:layout_width="wrap_content"\r
+                android:layout_height="wrap_content"\r
+                android:layout_weight=".2"\r
+                android:background="@color/btnColor"\r
+                android:src="@drawable/open" />\r
+\r
+                <ImageButton\r
+                android:id="@+id/fit"\r
+                style="?android:borderlessButtonStyle"\r
+                android:layout_width="wrap_content"\r
+                android:layout_height="wrap_content"\r
+                android:layout_weight=".2"\r
+                android:background="@color/btnColor"\r
+                android:src="@drawable/fit" />\r
+\r
+                <ImageButton\r
+                android:id="@+id/view"\r
+                style="?android:borderlessButtonStyle"\r
+                android:layout_width="wrap_content"\r
+                android:layout_height="wrap_content"\r
+                android:layout_weight=".2"\r
+                android:background="@color/btnColor"\r
+                android:src="@drawable/view" />\r
+\r
+                <ImageButton\r
+                android:id="@+id/info"\r
+                style="?android:borderlessButtonStyle"\r
+                android:layout_width="wrap_content"\r
+                android:layout_height="wrap_content"\r
+                android:layout_weight=".2"\r
+                android:background="@color/btnColor"\r
+                android:src="@drawable/info" />\r
+\r
+                <ImageButton\r
+                android:id="@+id/message"\r
+                style="?android:borderlessButtonStyle"\r
+                android:layout_width="wrap_content"\r
+                android:layout_height="wrap_content"\r
+                android:layout_weight=".2"\r
+                android:background="@color/btnColor"\r
+                android:src="@drawable/message" />\r
+            </LinearLayout>\r
+\r
+                <TextView\r
+                android:id="@+id/message_view"\r
+                android:background="@color/viewColor"\r
+                android:text="Message Log"\r
+                android:textSize="16px"\r
+                android:textStyle="bold"\r
+                android:visibility="gone"\r
+                android:layout_width="wrap_content"\r
+                android:layout_height="wrap_content"/>\r
+\r
+            <TextView\r
+            android:id="@+id/info_view"\r
+            android:background="@color/viewColor"\r
+            android:gravity="center"\r
+            android:text="info Log"\r
+            android:textSize="16px"\r
+            android:textStyle="bold"\r
+            android:visibility="gone"\r
+            android:layout_width="fill_parent"\r
+            android:layout_height="wrap_content"/>\r
+\r
+            <LinearLayout\r
+            android:id="@+id/view_group"\r
+            android:layout_width="fill_parent"\r
+            android:layout_height="wrap_content"\r
+            android:layout_gravity="bottom|end"\r
+            android:orientation="horizontal" >\r
+\r
+                <ImageButton \r
+                style="?android:borderlessButtonStyle"\r
+                android:background="@color/btnColor" \r
+                android:id="@+id/proj_front"\r
+                android:layout_height="wrap_content" \r
+                android:layout_width="fill_parent"\r
+                android:src="@drawable/proj_front"\r
+                android:layout_weight=".16"/>\r
+\r
+                <ImageButton \r
+                style="?android:borderlessButtonStyle"\r
+                android:background="@color/btnColor" \r
+                android:id="@+id/proj_top"\r
+                android:layout_height="wrap_content" \r
+                android:layout_width="fill_parent"\r
+                android:src="@drawable/proj_top"\r
+                android:layout_weight=".16"/>\r
+\r
+                <ImageButton \r
+                style="?android:borderlessButtonStyle"\r
+                android:background="@color/btnColor" \r
+                android:id="@+id/proj_left"\r
+                android:layout_height="wrap_content" \r
+                android:layout_width="fill_parent"\r
+                android:src="@drawable/proj_left"\r
+                android:layout_weight=".16"/>\r
+\r
+                <ImageButton \r
+                style="?android:borderlessButtonStyle"\r
+                android:background="@color/btnColor" \r
+                android:id="@+id/proj_back"\r
+                android:layout_height="wrap_content" \r
+                android:layout_width="fill_parent"\r
+                android:src="@drawable/proj_back"\r
+                android:layout_weight=".16"/>\r
+\r
+                <ImageButton \r
+                style="?android:borderlessButtonStyle"\r
+                android:background="@color/btnColor" \r
+                android:id="@+id/proj_bottom"\r
+                android:layout_height="wrap_content" \r
+                android:layout_width="fill_parent"\r
+                android:src="@drawable/proj_bottom"\r
+                android:layout_weight=".16"/>\r
+\r
+                <ImageButton \r
+                style="?android:borderlessButtonStyle"\r
+                android:background="@color/btnColor" \r
+                android:id="@+id/proj_right"\r
+                android:layout_height="wrap_content" \r
+                android:layout_width="fill_parent"\r
+                android:src="@drawable/proj_right"\r
+                android:layout_weight=".16"/>\r
+            </LinearLayout>\r
+        </FrameLayout>\r
+    </LinearLayout>\r
+</TableLayout>\r
diff --git a/samples/java/jniviewer/app/src/main/res/values/id.xml b/samples/java/jniviewer/app/src/main/res/values/id.xml
new file mode 100644 (file)
index 0000000..56bde94
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+   <item name="open" type="id"/>
+   <item name="save" type="id"/>
+   <item name="screenshot" type="id"/>
+   <item name="mesh_none" type="id"/>
+   <item name="mesh_low_q" type="id"/>
+   <item name="mesh_norm_q" type="id"/>
+   <item name="mesh_high_q" type="id"/>
+   <item name="view1" type="id"/>
+   <item name="view2" type="id"/>
+   <item name="view3" type="id"/>
+   <item name="settings" type="id"/>
+   <item name="message" type="id"/>
+   <item name="lock" type="id"/>
+   <item name="info" type="id"/>
+</resources>
diff --git a/samples/java/jniviewer/app/src/main/res/values/strings.xml b/samples/java/jniviewer/app/src/main/res/values/strings.xml
new file mode 100644 (file)
index 0000000..6f2a431
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">OpenCASCADE JNI Java Sample</string>
+    <color name="btnColor">#484848</color>
+    <color name="pressedBtnColor">#0099CC</color>
+    <color name="viewColor">#66252525</color>
+        <string-array name="ext_to_save">
+        <item>.png</item>
+        <item>.jpg</item>
+    </string-array>
+    <string-array name="ext_to_exp">
+        <item>.brep</item>
+        <item>.rle</item>
+        <item>.iges</item>
+        <item>.igs</item>
+        <item>.step</item>
+        <item>.stp</item>
+    </string-array>
+    <string name="wireframe_shading_title">wireframe/shading</string>
+    <string name="color_title">color</string>
+    <string name="material_title">material</string>
+    <string name="transparency_title">transparency</string>
+    <string name="hidden_lines_title">show/hide hidden lines</string>
+    <string name="info_html" formatted="false">
+        <![CDATA[
+        <p>OpenCASCADE JNI Java Sample</p>
+        <p>Simple viewer for BREP, STEP and IGES files.</p>
+        <p>Driven by Open CASCADE Technology %d.%d.%d.</p>
+        <p>Copyright 2014 OPEN CASCADE SAS.</p>
+        <p><img src="info_image"></p>
+        <p>http://www.opencascade.com</p>
+        <p>http://www.opencascade.org</p>
+        ]]>
+    </string>
+</resources>
diff --git a/samples/java/jniviewer/build.gradle b/samples/java/jniviewer/build.gradle
new file mode 100644 (file)
index 0000000..da2f7cd
--- /dev/null
@@ -0,0 +1,17 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+    repositories {
+        jcenter()
+        google()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:4.0.0'
+    }
+}
+
+allprojects {
+    repositories {
+        jcenter()
+        google()
+    }
+}
diff --git a/samples/java/jniviewer/gradle.properties.template b/samples/java/jniviewer/gradle.properties.template
new file mode 100644 (file)
index 0000000..2cf7323
--- /dev/null
@@ -0,0 +1,5 @@
+# customized paths
+OCCT_ROOT=c\:/android/occt-dev-android
+FREETYPE_ROOT=c\:/android/freetype-2.7.1-android
+# in case if OCCT was built with FreeImage
+#FREEIMAGE_ROOT=c\:/android/freeimage-3.17-android
diff --git a/samples/java/jniviewer/jni/Android.mk b/samples/java/jniviewer/jni/Android.mk
deleted file mode 100644 (file)
index 83547a2..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-STL_INC := $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/include $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/$(TARGET_ARCH_ABI)/include
-#STL_LIB := $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/$(TARGET_ARCH_ABI)/libgnustl_static.a
-STL_LIB := $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/$(TARGET_ARCH_ABI)/libgnustl_shared.so
-
-OCCT_ROOT := $(LOCAL_PATH)/../../../..
-
-FREETYPE_INC  := $(OCCT_ROOT)/../freetype/include/freetype2
-FREETYPE_LIBS := $(OCCT_ROOT)/../freetype/libs
-
-FREEIMAGE_INC  := $(OCCT_ROOT)/../FreeImage/include
-FREEIMAGE_LIBS := $(OCCT_ROOT)/../FreeImage/libs
-
-OCCT_INC  := $(OCCT_ROOT)/inc
-OCCT_LIBS := $(OCCT_ROOT)/and/libs
-
-ASSETDIR := $(LOCAL_PATH)/../assets
-
-$(ASSETDIR)/Shaders: $(ASSETDIR)
-       -mkdir -p $(ASSETDIR)
-       -mkdir -p $(ASSETDIR)/Shaders
-       cp -f -r $(OCCT_ROOT)/src/Shaders/*.* $(ASSETDIR)/Shaders
-
-$(ASSETDIR)/SHMessage: $(ASSETDIR)
-       -mkdir -p $(ASSETDIR)
-       -mkdir -p $(ASSETDIR)/SHMessage
-       cp -f -r $(OCCT_ROOT)/src/SHMessage/*.* $(ASSETDIR)/SHMessage
-
-$(ASSETDIR)/XSMessage: $(ASSETDIR)
-       -mkdir -p $(ASSETDIR)
-       -mkdir -p $(ASSETDIR)/XSMessage
-       cp -f -r $(OCCT_ROOT)/src/XSMessage/*.* $(ASSETDIR)/XSMessage
-
-pre_all: $(ASSETDIR)/Shaders $(ASSETDIR)/SHMessage $(ASSETDIR)/XSMessage
-
-jniall: pre_all all
-
-# STL libs
-include $(CLEAR_VARS)
-LOCAL_MODULE := SharedStl
-LOCAL_EXPORT_C_INCLUDES := $(STL_INC)
-LOCAL_SRC_FILES := $(STL_LIB)
-include $(PREBUILT_SHARED_LIBRARY)
-
-# 3rd-parties used in OCCT
-include $(CLEAR_VARS)
-LOCAL_MODULE := FreeType
-LOCAL_EXPORT_C_INCLUDES := $(FREETYPE_INC)
-LOCAL_SRC_FILES := $(FREETYPE_LIBS)/$(TARGET_ARCH_ABI)/libfreetype.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-#include $(CLEAR_VARS)
-#LOCAL_MODULE := FreeImage
-#LOCAL_EXPORT_C_INCLUDES := $(FREEIMAGE_INC)
-#LOCAL_SRC_FILES := $(FREEIMAGE_LIBS)/$(TARGET_ARCH_ABI)/libfreeimage.so
-#include $(PREBUILT_SHARED_LIBRARY)
-
-# OCCT core
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKernel
-LOCAL_EXPORT_C_INCLUDES := $(OCCT_INC)
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKernel.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKMath
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKMath.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKG2d
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKG2d.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKG3d
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKG3d.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKGeomBase
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKGeomBase.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKBRep
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKBRep.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKGeomAlgo
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKGeomAlgo.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKTopAlgo
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKTopAlgo.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKShHealing
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKShHealing.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKMesh
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKMesh.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-# OCCT Exchange
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKPrim
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKPrim.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKBO
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKBO.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKBool
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKBool.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKFillet
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKFillet.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKOffset
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKOffset.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKXSBase
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKXSBase.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKIGES
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKIGES.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKSTEPBase
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKSTEPBase.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKSTEPAttr
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKSTEPAttr.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKSTEP209
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKSTEP209.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKSTEP
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKSTEP.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-# OCCT visualization
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKService
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKService.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKHLR
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKHLR.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKV3d
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKV3d.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := OcctTKOpenGl
-LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKOpenGl.so
-include $(PREBUILT_SHARED_LIBRARY)
-
-# our sample
-include $(CLEAR_VARS)
-LOCAL_MODULE           := libTKJniSample
-LOCAL_C_INCLUDES       := $(STL_INC)
-#LOCAL_STATIC_LIBRARIES := $(STL_LIB) does not work
-LOCAL_CFLAGS           := -Wall -std=c++11
-LOCAL_CPP_EXTENSION    := .cxx .cpp
-LOCAL_CPP_FEATURES     := rtti exceptions
-LOCAL_SRC_FILES        := OcctJni_Viewer.cxx OcctJni_Window.cxx OcctJni_MsgPrinter.cxx
-LOCAL_SHARED_LIBRARIES := OcctTKernel OcctTKMath OcctTKG2d OcctTKG3d OcctTKGeomBase OcctTKBRep OcctTKGeomAlgo OcctTKTopAlgo OcctTKShHealing OcctTKMesh OcctTKPrim
-LOCAL_SHARED_LIBRARIES += OcctTKIGES OcctTKSTEP OcctTKXSBase
-LOCAL_SHARED_LIBRARIES += OcctTKService OcctTKHLR OcctTKV3d OcctTKOpenGl
-LOCAL_SHARED_LIBRARIES += SharedStl
-LOCAL_LDLIBS           := -llog -lGLESv2 -lEGL
-
-#LOCAL_LDLIBS += $(STL_LIB)
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/samples/java/jniviewer/jni/Application.mk b/samples/java/jniviewer/jni/Application.mk
deleted file mode 100644 (file)
index 1d6b633..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-NDK_TOOLCHAIN_VERSION := 4.8
-APP_PLATFORM := android-15
-
-APP_ABI := armeabi-v7a
-#APP_ABI := all
-
-#APP_STL := gnustl_static
-#APP_STL := stlport_static
diff --git a/samples/java/jniviewer/jni/OcctJni_MsgPrinter.cxx b/samples/java/jniviewer/jni/OcctJni_MsgPrinter.cxx
deleted file mode 100644 (file)
index 62ea7f9..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <OcctJni_MsgPrinter.hxx>
-
-#include <TCollection_AsciiString.hxx>
-#include <TCollection_ExtendedString.hxx>
-
-#include <android/log.h>
-
-IMPLEMENT_STANDARD_RTTIEXT(OcctJni_MsgPrinter, Message_Printer)
-
-// =======================================================================
-// function : OcctJni_MsgPrinter
-// purpose  :
-// =======================================================================
-OcctJni_MsgPrinter::OcctJni_MsgPrinter (JNIEnv* theJEnv,
-                                        jobject theJObj)
-: myJEnv (theJEnv),
-  myJObj (theJEnv->NewGlobalRef (theJObj)),
-  myJMet (NULL)
-{
-  jclass aJClass = theJEnv->GetObjectClass (theJObj);
-  myJMet = theJEnv->GetMethodID (aJClass, "postMessage", "(Ljava/lang/String;)V");
-  if (myJMet == NULL)
-  {
-    __android_log_write (ANDROID_LOG_FATAL, "jniSample", "Broken initialization of OcctJni_MsgPrinter!");
-  }
-}
-
-// =======================================================================
-// function : ~OcctJni_MsgPrinter
-// purpose  :
-// =======================================================================
-OcctJni_MsgPrinter::~OcctJni_MsgPrinter()
-{
-  //myJEnv->DeleteGlobalRef (myJObj);
-}
-
-// =======================================================================
-// function : send
-// purpose  :
-// =======================================================================
-void OcctJni_MsgPrinter::send (const TCollection_AsciiString& theString,
-                               const Message_Gravity theGravity) const
-{
-  if (theGravity < myTraceLevel)
-  {
-    return;
-  }
-
-  ///__android_log_write (ANDROID_LOG_DEBUG, "OcctJni_MsgPrinter", (TCollection_AsciiString(" @@ ") + theString).ToCString());
-  if (myJMet == NULL)
-  {
-    return;
-  }
-
-  jstring aJStr = myJEnv->NewStringUTF ((theString + "\n").ToCString());
-  myJEnv->CallObjectMethod (myJObj, myJMet, aJStr);
-  myJEnv->DeleteLocalRef (aJStr);
-}
diff --git a/samples/java/jniviewer/jni/OcctJni_MsgPrinter.hxx b/samples/java/jniviewer/jni/OcctJni_MsgPrinter.hxx
deleted file mode 100644 (file)
index 3f825de..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef OcctJni_MsgPrinter_H
-#define OcctJni_MsgPrinter_H
-
-#include <Message_Printer.hxx>
-
-#include <jni.h>
-
-// Class providing connection between messenger interfaces in C++ and Java layers.
-class OcctJni_MsgPrinter : public Message_Printer
-{
-public:
-
-  //! Default constructor
-  OcctJni_MsgPrinter (JNIEnv* theJEnv,
-                      jobject theJObj);
-
-  //! Destructor.
-  ~OcctJni_MsgPrinter();
-
-protected:
-
-  //! Main printing method
-  virtual void send (const TCollection_AsciiString& theString,
-                     const Message_Gravity theGravity) const;
-
-private:
-
-  JNIEnv*   myJEnv;
-  jobject   myJObj;
-  jmethodID myJMet;
-
-public:
-
-  DEFINE_STANDARD_RTTIEXT(OcctJni_MsgPrinter,Message_Printer)
-
-};
-
-DEFINE_STANDARD_HANDLE(OcctJni_MsgPrinter, Message_Printer)
-
-#endif // OcctJni_MsgPrinter_H
diff --git a/samples/java/jniviewer/jni/OcctJni_Viewer.cxx b/samples/java/jniviewer/jni/OcctJni_Viewer.cxx
deleted file mode 100644 (file)
index 23a02af..0000000
+++ /dev/null
@@ -1,809 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <OcctJni_Viewer.hxx>
-#include <OcctJni_MsgPrinter.hxx>
-
-#include <AIS_Shape.hxx>
-#include <Image_AlienPixMap.hxx>
-#include <BRepTools.hxx>
-#include <Message_Messenger.hxx>
-#include <Message_MsgFile.hxx>
-#include <OpenGl_GraphicDriver.hxx>
-#include <OSD_Environment.hxx>
-#include <OSD_Timer.hxx>
-#include <Standard_Version.hxx>
-
-#include <BRepPrimAPI_MakeBox.hxx>
-
-#include <STEPControl_Reader.hxx>
-#include <IGESControl_Reader.hxx>
-#include <XSControl_WorkSession.hxx>
-
-#include <EGL/egl.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <jni.h>
-
-//! @return true if file exists
-static bool isFileExist (const TCollection_AsciiString& thePath)
-{
-  struct stat64 aStatBuffer;
-  return stat64 (thePath.ToCString(), &aStatBuffer) == 0;
-}
-
-//! Cut-off the last split character from the path and everything after it.
-static TCollection_AsciiString getParentDir (const TCollection_AsciiString& thePath)
-{
-  TCollection_AsciiString aPath = thePath;
-  char* aSplitter = (char* )aPath.ToCString();
-  for (char* anIter = aSplitter; *anIter != '\0'; ++anIter)
-  {
-    if (*anIter == '\\'
-     || *anIter == '/')
-    {
-      aSplitter = anIter;
-    }
-  }
-  *aSplitter = '\0'; // cut off file name or trailing folder
-  return TCollection_AsciiString (aPath.ToCString());
-}
-
-//! Set environment variable theVarName indicating location of resource
-//! file theFile so as to correspond to actual location of this file.
-//!
-//! The resource file is searched in directory where Test.Draw.dll is located,
-//! and if not found - also in subdirectory ../res from there.
-//! If file is found, environment variable is set for C subsystem.
-//! Otherwise, environment is not changed.
-//!
-//! If theToAddFileName is true, complete file name is set as value of the variable,
-//! if theToAddFileName is false, only path is set.
-Standard_Boolean setResourceEnv (const TCollection_AsciiString& theVarName,
-                                 const TCollection_AsciiString& theRoot,
-                                 const TCollection_AsciiString& theFile,
-                                 const Standard_Boolean         theToAddFileName)
-{
-  // use location of current assembly to figure out possible location of resource
-  TCollection_AsciiString aBaseDir = theRoot;
-
-  // check the same directory where binary is located
-  if (!isFileExist (aBaseDir + "/" + theFile))
-  {
-    // check subdirectory ../res
-    aBaseDir = getParentDir (aBaseDir) + "/res";
-    if (!isFileExist (aBaseDir + "/" + theFile))
-    {
-      return Standard_False;
-    }
-  }
-
-  // set C library environment
-  if (theToAddFileName)
-  {
-    aBaseDir = aBaseDir + "/" + theFile;
-  }
-
-  OSD_Environment anEnv (theVarName, aBaseDir);
-  anEnv.Build();
-  return Standard_True;
-}
-
-// =======================================================================
-// function : OcctJni_Viewer
-// purpose  :
-// =======================================================================
-OcctJni_Viewer::OcctJni_Viewer()
-{
-  // prepare necessary environment
-  TCollection_AsciiString aResRoot = "/data/data/com.opencascade.jnisample/files";
-
-  setResourceEnv ("CSF_ShadersDirectory", aResRoot + "/Shaders",   "Declarations.glsl", Standard_False);
-  setResourceEnv ("CSF_XSMessage",        aResRoot + "/XSMessage", "XSTEP.us",          Standard_False);
-  setResourceEnv ("CSF_SHMessage",        aResRoot + "/XSMessage", "SHAPE.us",          Standard_False);
-  //setResourceEnv ("CSF_PluginDefaults",   "Plugin",            Standard_False);
-
-  // make sure OCCT loads the dictionary
-  //UnitsAPI::SetLocalSystem (UnitsAPI_SI);
-}
-
-// =======================================================================
-// function : init
-// purpose  :
-// =======================================================================
-bool OcctJni_Viewer::init()
-{
-  EGLint aCfgId = 0;
-  int aWidth = 0, aHeight = 0;
-  EGLDisplay anEglDisplay = eglGetCurrentDisplay();
-  EGLContext anEglContext = eglGetCurrentContext();
-  EGLSurface anEglSurf    = eglGetCurrentSurface (EGL_DRAW);
-  if (anEglDisplay == EGL_NO_DISPLAY
-   || anEglContext == EGL_NO_CONTEXT
-   || anEglSurf    == EGL_NO_SURFACE)
-  {
-    Message::DefaultMessenger()->Send ("Error: No active EGL context!", Message_Fail);
-    release();
-    return false;
-  }
-
-  eglQuerySurface (anEglDisplay, anEglSurf, EGL_WIDTH,     &aWidth);
-  eglQuerySurface (anEglDisplay, anEglSurf, EGL_HEIGHT,    &aHeight);
-  eglQuerySurface (anEglDisplay, anEglSurf, EGL_CONFIG_ID, &aCfgId);
-  const EGLint aConfigAttribs[] = { EGL_CONFIG_ID, aCfgId, EGL_NONE };
-  EGLint       aNbConfigs = 0;
-  void*        anEglConfig = NULL;
-  if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE)
-  {
-    Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
-    release();
-    return false;
-  }
-
-  TCollection_AsciiString anEglInfo = TCollection_AsciiString()
-      + "\n  EGLVersion:     " + eglQueryString (anEglDisplay, EGL_VERSION)
-      + "\n  EGLVendor:      " + eglQueryString (anEglDisplay, EGL_VENDOR)
-      + "\n  EGLClient APIs: " + eglQueryString (anEglDisplay, EGL_CLIENT_APIS)
-      + "\n  GLvendor:       " + (const char* )glGetString (GL_VENDOR)
-      + "\n  GLdevice:       " + (const char* )glGetString (GL_RENDERER)
-      + "\n  GLversion:      " + (const char* )glGetString (GL_VERSION) + " [GLSL: " + (const char* )glGetString (GL_SHADING_LANGUAGE_VERSION) + "]";
-    ::Message::DefaultMessenger()->Send (anEglInfo, Message_Info);
-
-  if (!myViewer.IsNull())
-  {
-    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
-    Handle(OcctJni_Window)       aWindow = Handle(OcctJni_Window)::DownCast (myView->Window());
-    if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
-    {
-      Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized!", Message_Fail);
-      release();
-      return false;
-    }
-
-    aWindow->SetSize (aWidth, aHeight);
-    myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
-    return true;
-  }
-
-  Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False);
-  aDriver->ChangeOptions().buffersNoSwap = Standard_True;
-//aDriver->ChangeOptions().glslWarnings  = Standard_True; /// for debug only!
-  if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
-  {
-    Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized!", Message_Fail);
-    release();
-    return false;
-  }
-
-  // create viewer
-  myViewer = new V3d_Viewer (aDriver);
-  myViewer->SetDefaultBackgroundColor (Quantity_NOC_BLACK);
-  myViewer->SetDefaultLights();
-  myViewer->SetLightOn();
-
-  // create AIS context
-  myContext = new AIS_InteractiveContext (myViewer);
-  //myContext->SetDisplayMode (AIS_WireFrame, false);
-  myContext->SetDisplayMode (AIS_Shaded, false);
-
-  Handle(OcctJni_Window) aWindow = new OcctJni_Window (aWidth, aHeight);
-  myView = myViewer->CreateView();
-
-  myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
-  myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER);
-
-  initContent();
-  return true;
-}
-
-// =======================================================================
-// function : release
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::release()
-{
-  myContext.Nullify();
-  myView.Nullify();
-  myViewer.Nullify();
-}
-
-// =======================================================================
-// function : resize
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::resize (int theWidth,
-                             int theHeight)
-{
-  if (myContext.IsNull())
-  {
-    Message::DefaultMessenger()->Send ("Resize failed - view is unavailable", Message_Fail);
-    return;
-  }
-
-  Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
-  Handle(OcctJni_Window)       aWindow = Handle(OcctJni_Window)::DownCast (myView->Window());
-  aWindow->SetSize (theWidth, theHeight);
-  //myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed
-
-  EGLContext anEglContext = eglGetCurrentContext();
-  myView->SetImmediateUpdate (Standard_False);
-  myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
-  //saveSnapshot ("/sdcard/Download/tt.png", theWidth, theHeight);
-}
-
-// =======================================================================
-// function : initContent
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::initContent()
-{
-  myContext->RemoveAll (Standard_False);
-
-  OSD_Timer aTimer;
-  aTimer.Start();
-  if (!myShape.IsNull())
-  {
-    Handle(AIS_Shape) aShapePrs = new AIS_Shape (myShape);
-    myContext->Display (aShapePrs, Standard_False);
-  }
-  else
-  {
-    BRepPrimAPI_MakeBox aBuilder (1.0, 2.0, 3.0);
-    Handle(AIS_Shape) aShapePrs = new AIS_Shape (aBuilder.Shape());
-    myContext->Display (aShapePrs, Standard_False);
-  }
-  myView->FitAll();
-
-  aTimer.Stop();
-  Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Presentation computed in " + aTimer.ElapsedTime() + " seconds", Message_Info);
-}
-
-//! Load shape from IGES file
-static TopoDS_Shape loadIGES (const TCollection_AsciiString& thePath)
-{
-  TopoDS_Shape          aShape;
-  IGESControl_Reader    aReader;
-  IFSelect_ReturnStatus aReadStatus = IFSelect_RetFail;
-  try
-  {
-    aReadStatus = aReader.ReadFile (thePath.ToCString());
-  }
-  catch (Standard_Failure)
-  {
-    Message::DefaultMessenger()->Send ("Error: IGES reader, computation error", Message_Fail);
-    return aShape;
-  }
-
-  if (aReadStatus != IFSelect_RetDone)
-  {
-    Message::DefaultMessenger()->Send ("Error: IGES reader, bad file format", Message_Fail);
-    return aShape;
-  }
-
-  // now perform the translation
-  aReader.TransferRoots();
-  if (aReader.NbShapes() <= 0)
-  {
-    Handle(XSControl_WorkSession) aWorkSession = new XSControl_WorkSession();
-    aWorkSession->SelectNorm ("IGES");
-    aReader.SetWS (aWorkSession, Standard_True);
-    aReader.SetReadVisible (Standard_False);
-    aReader.TransferRoots();
-  }
-  if (aReader.NbShapes() <= 0)
-  {
-    Message::DefaultMessenger()->Send ("Error: IGES reader, no shapes has been found", Message_Fail);
-    return aShape;
-  }
-  return aReader.OneShape();
-  /*TopoDS_Shape anImportedShape = aReader.OneShape();
-
-  // apply sewing on the imported shape
-  BRepBuilderAPI_Sewing aTool (0.0);
-  aTool.SetNonManifoldMode  (Standard_False);
-  aTool.SetFloatingEdgesMode(Standard_True);
-  aTool.Load (anImportedShape);
-  aTool.Perform();
-  TopoDS_Shape aSewedShape = aTool.SewedShape();
-
-  if (aSewedShape.IsNull())
-  {
-    Message::DefaultMessenger()->Send ("Error: Sewing result is empty", Message_Fail);
-    return aShape;
-  }
-  if (aSewedShape.IsSame(anImportedShape))
-  {
-    aShape = anImportedShape;
-  }
-  else
-  {
-    // apply shape healing
-    ShapeFix_Shape aShapeFixer(aSewedShape);
-    aShapeFixer.FixSolidMode() = 1;
-    aShapeFixer.FixFreeShellMode() = 1;
-    aShapeFixer.FixFreeFaceMode() = 1;
-    aShapeFixer.FixFreeWireMode() = 0;
-    aShapeFixer.FixSameParameterMode() = 0;
-    aShapeFixer.FixVertexPositionMode() = 0;
-    aShape = aShapeFixer.Perform() ? aShapeFixer.Shape() : aSewedShape;
-  }
-  return aShape;*/
-}
-
-//! Load shape from STEP file
-static TopoDS_Shape loadSTEP (const TCollection_AsciiString& thePath)
-{
-  STEPControl_Reader    aReader;
-  IFSelect_ReturnStatus aReadStatus = IFSelect_RetFail;
-  try
-  {
-    aReadStatus = aReader.ReadFile (thePath.ToCString());
-  }
-  catch (Standard_Failure)
-  {
-    Message::DefaultMessenger()->Send ("Error: STEP reader, computation error", Message_Fail);
-    return TopoDS_Shape();
-  }
-
-  if (aReadStatus != IFSelect_RetDone)
-  {
-    Message::DefaultMessenger()->Send ("Error: STEP reader, bad file format", Message_Fail);
-    return TopoDS_Shape();
-  }
-  else if (aReader.NbRootsForTransfer() <= 0)
-  {
-    Message::DefaultMessenger()->Send ("Error: STEP reader, shape is empty", Message_Fail);
-    return TopoDS_Shape();
-  }
-
-  // now perform the translation
-  aReader.TransferRoots();
-  return aReader.OneShape();
-}
-
-// =======================================================================
-// function : open
-// purpose  :
-// =======================================================================
-bool OcctJni_Viewer::open (const TCollection_AsciiString& thePath)
-{
-  myShape.Nullify();
-  if (!myContext.IsNull())
-  {
-    myContext->RemoveAll (Standard_False);
-  }
-  if (thePath.IsEmpty())
-  {
-    return false;
-  }
-
-  OSD_Timer aTimer;
-  aTimer.Start();
-  TCollection_AsciiString aFormatStr;
-  const Standard_Integer  aLen = thePath.Length();
-  if (aLen >= 5
-  && thePath.Value (aLen - 4) == '.')
-  {
-    aFormatStr = thePath.SubString (aLen - 3, aLen);
-  }
-  else if (aLen >= 4
-   && thePath.Value (aLen - 3) == '.')
-  {
-    aFormatStr = thePath.SubString (aLen - 2, aLen);
-  }
-  else if (aLen >= 3
-        && thePath.Value (aLen - 2) == '.')
-  {
-    aFormatStr = thePath.SubString (aLen - 1, aLen);
-  }
-  aFormatStr.LowerCase();
-
-  TopoDS_Shape aShape;
-  if (aFormatStr == "stp"
-   || aFormatStr == "step")
-  {
-    aShape = loadSTEP (thePath);
-  }
-  else if (aFormatStr == "igs"
-        || aFormatStr == "iges")
-  {
-    aShape = loadIGES (thePath);
-  }
-  else
-      // if (aFormatStr == "brep"
-      //  || aFormatStr == "rle")
-  {
-    BRep_Builder aBuilder;
-    if (!BRepTools::Read (aShape, thePath.ToCString(), aBuilder))
-    {
-      Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Error: file '" + thePath + "' can not be opened!", Message_Info);
-      return false;
-    }
-  }
-  if (aShape.IsNull())
-  {
-    return false;
-  }
-  aTimer.Stop();
-  Message::DefaultMessenger()->Send (TCollection_AsciiString() + "File '" + thePath + "' loaded in " + aTimer.ElapsedTime() + " seconds", Message_Info);
-
-  myShape = aShape;
-  if (myContext.IsNull())
-  {
-    return true;
-  }
-
-  aTimer.Reset();
-  aTimer.Start();
-
-  Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape);
-  myContext->Display (aShapePrs, Standard_False);
-  myView->FitAll();
-
-  aTimer.Stop();
-  Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Presentation computed in " + aTimer.ElapsedTime() + " seconds", Message_Info);
-  return true;
-}
-
-// =======================================================================
-// function : saveSnapshot
-// purpose  :
-// =======================================================================
-bool OcctJni_Viewer::saveSnapshot (const TCollection_AsciiString& thePath,
-                                   int theWidth,
-                                   int theHeight)
-{
-  if (myContext.IsNull()
-   || thePath.IsEmpty())
-  {
-    Message::DefaultMessenger()->Send ("Image dump failed - view is unavailable", Message_Fail);
-    return false;
-  }
-
-  if (theWidth  < 1
-   || theHeight < 1)
-  {
-    myView->Window()->Size (theWidth, theHeight);
-  }
-  if (theWidth  < 1
-   || theHeight < 1)
-  {
-    Message::DefaultMessenger()->Send ("Image dump failed - view is unavailable", Message_Fail);
-    return false;
-  }
-
-  Image_AlienPixMap anAlienImage;
-  if (!anAlienImage.InitTrash (Image_PixMap::ImgBGRA, theWidth, theHeight))
-  {
-    Message::DefaultMessenger()->Send (TCollection_AsciiString() + "RGBA image " + theWidth + "x" + theHeight + " allocation failed", Message_Fail);
-    return false;
-  }
-
-  // OpenGL ES does not support fetching data in BGRA format
-  // while FreeImage does not support RGBA format.
-  Image_PixMap anImage;
-  anImage.InitWrapper (Image_PixMap::ImgRGBA,
-                       anAlienImage.ChangeData(),
-                       anAlienImage.SizeX(),
-                       anAlienImage.SizeY(),
-                       anAlienImage.SizeRowBytes());
-  if (!myView->ToPixMap (anImage, theWidth, theHeight, Graphic3d_BT_RGBA))
-  {
-    Message::DefaultMessenger()->Send (TCollection_AsciiString() + "View dump to the image " + theWidth + "x" + theHeight + " failed", Message_Fail);
-  }
-
-  for (Standard_Size aRow = 0; aRow < anAlienImage.SizeY(); ++aRow)
-  {
-    for (Standard_Size aCol = 0; aCol < anAlienImage.SizeX(); ++aCol)
-    {
-      Image_ColorRGBA& aPixel = anAlienImage.ChangeValue<Image_ColorRGBA> (aRow, aCol);
-      std::swap (aPixel.r(), aPixel.b());
-      //aPixel.a() = 1.0;
-    }
-  }
-
-  if (!anAlienImage.Save (thePath))
-  {
-    Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Image saving to path '" + thePath + "' failed", Message_Fail);
-    return false;
-  }
-  Message::DefaultMessenger()->Send (TCollection_AsciiString() + "View " + theWidth + "x" + theHeight + " dumped to image '" + thePath + "'", Message_Info);
-  return true;
-}
-
-// =======================================================================
-// function : redraw
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::redraw()
-{
-  if (myView.IsNull())
-  {
-    return;
-  }
-
-  myView->Redraw();
-}
-
-// =======================================================================
-// function : fitAll
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::fitAll()
-{
-  if (myView.IsNull())
-  {
-    return;
-  }
-
-  myView->FitAll (0.01, Standard_False);
-  myView->Invalidate();
-}
-
-// =======================================================================
-// function : startRotation
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::startRotation (int theStartX,
-                                    int theStartY)
-{
-  if (myView.IsNull())
-  {
-    return;
-  }
-
-  myView->StartRotation (theStartX, theStartY, 0.45);
-  myView->Invalidate();
-}
-
-// =======================================================================
-// function : onRotation
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::onRotation (int theX,
-                                 int theY)
-{
-  if (myView.IsNull())
-  {
-    return;
-  }
-
-  myView->Rotation (theX, theY);
-  myView->Invalidate();
-}
-
-// =======================================================================
-// function : onPanning
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::onPanning (int theDX,
-                                int theDY)
-{
-  if (myView.IsNull())
-  {
-    return;
-  }
-
-  myView->Pan (theDX, theDY);
-  myView->Invalidate();
-}
-
-// =======================================================================
-// function : onClick
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::onClick (int theX,
-                              int theY)
-{
-  if (myView.IsNull())
-  {
-    return;
-  }
-
-  myContext->MoveTo (theX, theY, myView, Standard_False);
-  myContext->Select (Standard_False);
-  myView->Invalidate();
-}
-
-// =======================================================================
-// function : stopAction
-// purpose  :
-// =======================================================================
-void OcctJni_Viewer::stopAction()
-{
-  if (myView.IsNull())
-  {
-    return;
-  }
-}
-
-#define jexp extern "C" JNIEXPORT
-
-jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppCreate (JNIEnv* theEnv,
-                                                                             jobject theObj)
-{
-  return jlong(new OcctJni_Viewer());
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppDestroy (JNIEnv* theEnv,
-                                                                             jobject theObj,
-                                                                             jlong   theCppPtr)
-{
-  delete (OcctJni_Viewer* )theCppPtr;
-
-  Handle(Message_Messenger) aMsgMgr = Message::DefaultMessenger();
-  aMsgMgr->RemovePrinters (STANDARD_TYPE (OcctJni_MsgPrinter));
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppRelease (JNIEnv* theEnv,
-                                                                             jobject theObj,
-                                                                             jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->release();
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppInit (JNIEnv* theEnv,
-                                                                          jobject theObj,
-                                                                          jlong   theCppPtr)
-{
-  Handle(Message_Messenger) aMsgMgr = Message::DefaultMessenger();
-  aMsgMgr->RemovePrinters (STANDARD_TYPE (OcctJni_MsgPrinter));
-  aMsgMgr->AddPrinter (new OcctJni_MsgPrinter (theEnv, theObj));
-  ((OcctJni_Viewer* )theCppPtr)->init();
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppResize (JNIEnv* theEnv,
-                                                                            jobject theObj,
-                                                                            jlong   theCppPtr,
-                                                                            jint    theWidth,
-                                                                            jint    theHeight)
-{
-  ((OcctJni_Viewer* )theCppPtr)->resize (theWidth, theHeight);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOpen (JNIEnv* theEnv,
-                                                                          jobject theObj,
-                                                                          jlong   theCppPtr,
-                                                                          jstring thePath)
-{
-  const char* aPathPtr = theEnv->GetStringUTFChars (thePath, 0);
-  const TCollection_AsciiString aPath (aPathPtr);
-  theEnv->ReleaseStringUTFChars (thePath, aPathPtr);
-  ((OcctJni_Viewer* )theCppPtr)->open (aPath);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppRedraw (JNIEnv* theEnv,
-                                                                            jobject theObj,
-                                                                            jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->redraw();
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetAxoProj (JNIEnv* theEnv,
-                                                                                jobject theObj,
-                                                                                jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_XposYnegZpos);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetXposProj (JNIEnv* theEnv,
-                                                                                 jobject theObj,
-                                                                                 jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Xpos);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetYposProj (JNIEnv* theEnv,
-                                                                                 jobject theObj,
-                                                                                 jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Ypos);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetZposProj (JNIEnv* theEnv,
-                                                                                 jobject theObj,
-                                                                                 jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Zpos);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetXnegProj (JNIEnv* theEnv,
-                                                                                 jobject theObj,
-                                                                                 jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Xneg);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetYnegProj (JNIEnv* theEnv,
-                                                                                 jobject theObj,
-                                                                                 jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Yneg);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetZnegProj (JNIEnv* theEnv,
-                                                                                 jobject theObj,
-                                                                                 jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Zneg);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppFitAll (JNIEnv* theEnv,
-                                                                            jobject theObj,
-                                                                            jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->fitAll();
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppStartRotation (JNIEnv* theEnv,
-                                                                                   jobject theObj,
-                                                                                   jlong   theCppPtr,
-                                                                                   jint    theStartX,
-                                                                                   jint    theStartY)
-{
-  ((OcctJni_Viewer* )theCppPtr)->startRotation (theStartX, theStartY);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnRotation (JNIEnv* theEnv,
-                                                                                jobject theObj,
-                                                                                jlong   theCppPtr,
-                                                                                jint    theX,
-                                                                                jint    theY)
-{
-  ((OcctJni_Viewer* )theCppPtr)->onRotation (theX, theY);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnPanning (JNIEnv* theEnv,
-                                                                               jobject theObj,
-                                                                               jlong   theCppPtr,
-                                                                               jint    theDX,
-                                                                               jint    theDY)
-{
-  ((OcctJni_Viewer* )theCppPtr)->onPanning (theDX, theDY);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnClick (JNIEnv* theEnv,
-                                                                             jobject theObj,
-                                                                             jlong   theCppPtr,
-                                                                             jint    theX,
-                                                                             jint    theY)
-{
-  ((OcctJni_Viewer* )theCppPtr)->onClick (theX, theY);
-}
-
-jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppStopAction (JNIEnv* theEnv,
-                                                                                jobject theObj,
-                                                                                jlong   theCppPtr)
-{
-  ((OcctJni_Viewer* )theCppPtr)->stopAction();
-}
-
-jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMajorVersion (JNIEnv* theEnv,
-                                                                                       jobject theObj)
-{
-  return OCC_VERSION_MAJOR;
-}
-
-jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMinorVersion (JNIEnv* theEnv,
-                                                                                       jobject theObj)
-{
-  return OCC_VERSION_MINOR;
-}
-
-jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMicroVersion (JNIEnv* theEnv,
-                                                                                       jobject theObj)
-{
-  return OCC_VERSION_MAINTENANCE;
-}
diff --git a/samples/java/jniviewer/jni/OcctJni_Viewer.hxx b/samples/java/jniviewer/jni/OcctJni_Viewer.hxx
deleted file mode 100644 (file)
index 6bd0a41..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <OcctJni_Window.hxx>
-
-#include <AIS_InteractiveContext.hxx>
-#include <TopoDS_Shape.hxx>
-#include <V3d_Viewer.hxx>
-#include <V3d_View.hxx>
-
-//! Main C++ back-end for activity.
-class OcctJni_Viewer
-{
-
-public:
-
-  //! Empty constructor
-  OcctJni_Viewer();
-
-  //! Initialize the viewer
-  bool init();
-
-  //! Release the viewer
-  void release();
-
-  //! Resize the viewer
-  void resize (int theWidth,
-               int theHeight);
-
-  //! Open CAD file
-  bool open (const TCollection_AsciiString& thePath);
-
-  //! Take snapshot
-  bool saveSnapshot (const TCollection_AsciiString& thePath,
-                     int theWidth  = 0,
-                     int theHeight = 0);
-
-  //! Viewer update.
-  void redraw();
-
-  //! Move camera
-  void setProj (V3d_TypeOfOrientation theProj) { if (!myView.IsNull()) myView->SetProj (theProj); }
-
-  //! Fit All.
-  void fitAll();
-
-  //! Start rotation (remember first point position)
-  void startRotation (int theStartX,
-                      int theStartY);
-
-  //! Perform rotation (relative to first point)
-  void onRotation (int theX,
-                   int theY);
-
-  //! Perform panning
-  void onPanning (int theDX,
-                  int theDY);
-
-  //! Perform selection
-  void onClick (int theX,
-                int theY);
-
-  //! Stop previously started action
-  void stopAction();
-
-protected:
-
-  //! Reset viewer content.
-  void initContent();
-
-protected:
-
-  Handle(V3d_Viewer)             myViewer;
-  Handle(V3d_View)               myView;
-  Handle(AIS_InteractiveContext) myContext;
-  TopoDS_Shape                   myShape;
-
-};
diff --git a/samples/java/jniviewer/jni/OcctJni_Window.cxx b/samples/java/jniviewer/jni/OcctJni_Window.cxx
deleted file mode 100644 (file)
index 9202411..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <OcctJni_Window.hxx>
-
-IMPLEMENT_STANDARD_RTTIEXT(OcctJni_Window, Aspect_Window)
diff --git a/samples/java/jniviewer/jni/OcctJni_Window.hxx b/samples/java/jniviewer/jni/OcctJni_Window.hxx
deleted file mode 100644 (file)
index d6b731b..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef OcctJni_Window_H
-#define OcctJni_Window_H
-
-#include <Aspect_Window.hxx>
-
-//! This class defines dummy window
-class OcctJni_Window : public Aspect_Window
-{
-
-public:
-
-  //! Creates a wrapper over existing Window handle
-  OcctJni_Window (const int theWidth, const int theHeight)
-  : myWidth (theWidth), myHeight(theHeight) {}
-
-  //! Returns native Window handle
-  virtual Aspect_Drawable NativeHandle() const Standard_OVERRIDE { return 0; }
-
-  //! Returns parent of native Window handle
-  virtual Aspect_Drawable NativeParentHandle() const Standard_OVERRIDE { return 0; }
-
-  //! Returns nothing on Android
-  virtual Aspect_FBConfig NativeFBConfig() const Standard_OVERRIDE { return 0; }
-
-  virtual void Destroy() {}
-
-  //! Opens the window <me>
-  virtual void Map() const Standard_OVERRIDE {}
-
-  //! Closes the window <me>
-  virtual void Unmap() const Standard_OVERRIDE {}
-
-  //! Applies the resizing to the window <me>
-  virtual Aspect_TypeOfResize DoResize() Standard_OVERRIDE { return Aspect_TOR_UNKNOWN; }
-
-  //! Apply the mapping change to the window <me>
-  virtual Standard_Boolean DoMapping() const Standard_OVERRIDE { return Standard_True; }
-
-  //! Returns True if the window <me> is opened
-  virtual Standard_Boolean IsMapped() const Standard_OVERRIDE { return Standard_True; }
-
-  //! Returns The Window RATIO equal to the physical WIDTH/HEIGHT dimensions
-  virtual Standard_Real Ratio() const Standard_OVERRIDE { return 1.0; }
-
-  //! Returns The Window POSITION in PIXEL
-  virtual void Position (Standard_Integer& theX1,
-                         Standard_Integer& theY1,
-                         Standard_Integer& theX2,
-                         Standard_Integer& theY2) const Standard_OVERRIDE
-  {
-    theX1 = 0;
-    theX2 = myWidth;
-    theY1 = 0;
-    theY2 = myHeight;
-  }
-
-  //! Set The Window POSITION in PIXEL
-  void SetPosition (const Standard_Integer theX1,
-                    const Standard_Integer theY1,
-                    const Standard_Integer theX2,
-                    const Standard_Integer theY2)
-  {
-    myWidth  = theX2 - theX1;
-    myHeight = theY2 - theY1;
-  }
-
-  //! Returns The Window SIZE in PIXEL
-  virtual void Size (Standard_Integer& theWidth,
-                     Standard_Integer& theHeight) const Standard_OVERRIDE
-  {
-    theWidth  = myWidth;
-    theHeight = myHeight;
-  }
-
-  //! Set The Window SIZE in PIXEL
-  void SetSize (const Standard_Integer theWidth,
-                const Standard_Integer theHeight)
-  {
-    myWidth  = theWidth;
-    myHeight = theHeight;
-  }
-
-private:
-
-  int myWidth;
-  int myHeight;
-
-public:
-
-  DEFINE_STANDARD_RTTIEXT(OcctJni_Window,Aspect_Window)
-
-};
-
-DEFINE_STANDARD_HANDLE(OcctJni_Window, Aspect_Window)
-
-#endif // OcctJni_Window_H
diff --git a/samples/java/jniviewer/project.properties b/samples/java/jniviewer/project.properties
deleted file mode 100644 (file)
index 0840b4a..0000000
+++ /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 edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-15
diff --git a/samples/java/jniviewer/res/drawable-hdpi/close_l.png b/samples/java/jniviewer/res/drawable-hdpi/close_l.png
deleted file mode 100644 (file)
index 0125c4a..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/close_l.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/close_p.png b/samples/java/jniviewer/res/drawable-hdpi/close_p.png
deleted file mode 100644 (file)
index b5ce8bd..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/close_p.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/fit.png b/samples/java/jniviewer/res/drawable-hdpi/fit.png
deleted file mode 100644 (file)
index 70daee1..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/fit.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/ic_launcher.png b/samples/java/jniviewer/res/drawable-hdpi/ic_launcher.png
deleted file mode 100755 (executable)
index d27ba82..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/ic_launcher.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/info.png b/samples/java/jniviewer/res/drawable-hdpi/info.png
deleted file mode 100644 (file)
index 88d27c8..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/info.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/info_image.png b/samples/java/jniviewer/res/drawable-hdpi/info_image.png
deleted file mode 100644 (file)
index bac9bea..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/info_image.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/message.png b/samples/java/jniviewer/res/drawable-hdpi/message.png
deleted file mode 100644 (file)
index a3dc8cc..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/message.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/open.png b/samples/java/jniviewer/res/drawable-hdpi/open.png
deleted file mode 100644 (file)
index 68e5265..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/open.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/open_l.png b/samples/java/jniviewer/res/drawable-hdpi/open_l.png
deleted file mode 100644 (file)
index 6069ce3..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/open_l.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/open_p.png b/samples/java/jniviewer/res/drawable-hdpi/open_p.png
deleted file mode 100644 (file)
index c0898e6..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/open_p.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/proj_back.png b/samples/java/jniviewer/res/drawable-hdpi/proj_back.png
deleted file mode 100755 (executable)
index 77ab199..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/proj_back.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/proj_bottom.png b/samples/java/jniviewer/res/drawable-hdpi/proj_bottom.png
deleted file mode 100755 (executable)
index b0bb012..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/proj_bottom.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/proj_front.png b/samples/java/jniviewer/res/drawable-hdpi/proj_front.png
deleted file mode 100755 (executable)
index b93d4d3..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/proj_front.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/proj_left.png b/samples/java/jniviewer/res/drawable-hdpi/proj_left.png
deleted file mode 100755 (executable)
index bce95df..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/proj_left.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/proj_right.png b/samples/java/jniviewer/res/drawable-hdpi/proj_right.png
deleted file mode 100755 (executable)
index 8cdb338..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/proj_right.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/proj_top.png b/samples/java/jniviewer/res/drawable-hdpi/proj_top.png
deleted file mode 100755 (executable)
index 4ad098f..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/proj_top.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-hdpi/view.png b/samples/java/jniviewer/res/drawable-hdpi/view.png
deleted file mode 100644 (file)
index 76ce879..0000000
Binary files a/samples/java/jniviewer/res/drawable-hdpi/view.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-mdpi/ic_launcher.png b/samples/java/jniviewer/res/drawable-mdpi/ic_launcher.png
deleted file mode 100755 (executable)
index 4b86dbf..0000000
Binary files a/samples/java/jniviewer/res/drawable-mdpi/ic_launcher.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-xhdpi/ic_launcher.png b/samples/java/jniviewer/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100755 (executable)
index cd79bea..0000000
Binary files a/samples/java/jniviewer/res/drawable-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/drawable-xxhdpi/ic_launcher.png b/samples/java/jniviewer/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100755 (executable)
index a34301f..0000000
Binary files a/samples/java/jniviewer/res/drawable-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/samples/java/jniviewer/res/layout/activity_main.xml b/samples/java/jniviewer/res/layout/activity_main.xml
deleted file mode 100644 (file)
index e7f3ebf..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
-android:id="@+id/panel_main"\r
-android:layout_width="fill_parent"\r
-android:layout_height="fill_parent"\r
-android:stretchColumns="1">\r
-\r
-    <LinearLayout android:layout_height="fill_parent"\r
-    android:layout_width="fill_parent"\r
-    android:id="@+id/linearLayout2">\r
-\r
-        <FrameLayout\r
-        android:id="@+id/submenu_group"\r
-        android:layout_width="fill_parent"\r
-        android:layout_height="fill_parent" >\r
-\r
-            <com.opencascade.jnisample.OcctJniView\r
-            android:id="@+id/custom_view"\r
-            android:layout_width="fill_parent"\r
-            android:layout_height="fill_parent"\r
-            android:layout_gravity="bottom|end" >\r
-            </com.opencascade.jnisample.OcctJniView>\r
-\r
-            <ImageButton\r
-            android:id="@+id/scroll_btn"\r
-            style="?android:borderlessButtonStyle"\r
-            android:layout_width="match_parent"\r
-            android:layout_height="wrap_content"\r
-            android:background="@null"\r
-            android:src="@drawable/close_p" />\r
-\r
-            <LinearLayout\r
-            android:id="@+id/panel_menu"\r
-            android:layout_width="fill_parent"\r
-            android:layout_height="wrap_content"\r
-            android:orientation="horizontal" >\r
-                <ImageButton\r
-                android:id="@+id/open"\r
-                style="?android:borderlessButtonStyle"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_weight=".2"\r
-                android:background="@color/btnColor"\r
-                android:src="@drawable/open" />\r
-\r
-                <ImageButton\r
-                android:id="@+id/fit"\r
-                style="?android:borderlessButtonStyle"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_weight=".2"\r
-                android:background="@color/btnColor"\r
-                android:src="@drawable/fit" />\r
-\r
-                <ImageButton\r
-                android:id="@+id/view"\r
-                style="?android:borderlessButtonStyle"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_weight=".2"\r
-                android:background="@color/btnColor"\r
-                android:src="@drawable/view" />\r
-\r
-                <ImageButton\r
-                android:id="@+id/info"\r
-                style="?android:borderlessButtonStyle"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_weight=".2"\r
-                android:background="@color/btnColor"\r
-                android:src="@drawable/info" />\r
-\r
-                <ImageButton\r
-                android:id="@+id/message"\r
-                style="?android:borderlessButtonStyle"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_weight=".2"\r
-                android:background="@color/btnColor"\r
-                android:src="@drawable/message" />\r
-            </LinearLayout>\r
-\r
-                <TextView\r
-                android:id="@+id/message_view"\r
-                android:background="@color/viewColor"\r
-                android:text="Message Log"\r
-                android:textSize="16px"\r
-                android:textStyle="bold"\r
-                android:visibility="gone"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"/>\r
-\r
-            <TextView\r
-            android:id="@+id/info_view"\r
-            android:background="@color/viewColor"\r
-            android:gravity="center"\r
-            android:text="info Log"\r
-            android:textSize="16px"\r
-            android:textStyle="bold"\r
-            android:visibility="gone"\r
-            android:layout_width="fill_parent"\r
-            android:layout_height="wrap_content"/>\r
-\r
-            <LinearLayout\r
-            android:id="@+id/view_group"\r
-            android:layout_width="fill_parent"\r
-            android:layout_height="wrap_content"\r
-            android:layout_gravity="bottom|end"\r
-            android:orientation="horizontal" >\r
-\r
-                <ImageButton \r
-                style="?android:borderlessButtonStyle"\r
-                android:background="@color/btnColor" \r
-                android:id="@+id/proj_front"\r
-                android:layout_height="wrap_content" \r
-                android:layout_width="fill_parent"\r
-                android:src="@drawable/proj_front"\r
-                android:layout_weight=".16"/>\r
-\r
-                <ImageButton \r
-                style="?android:borderlessButtonStyle"\r
-                android:background="@color/btnColor" \r
-                android:id="@+id/proj_top"\r
-                android:layout_height="wrap_content" \r
-                android:layout_width="fill_parent"\r
-                android:src="@drawable/proj_top"\r
-                android:layout_weight=".16"/>\r
-\r
-                <ImageButton \r
-                style="?android:borderlessButtonStyle"\r
-                android:background="@color/btnColor" \r
-                android:id="@+id/proj_left"\r
-                android:layout_height="wrap_content" \r
-                android:layout_width="fill_parent"\r
-                android:src="@drawable/proj_left"\r
-                android:layout_weight=".16"/>\r
-\r
-                <ImageButton \r
-                style="?android:borderlessButtonStyle"\r
-                android:background="@color/btnColor" \r
-                android:id="@+id/proj_back"\r
-                android:layout_height="wrap_content" \r
-                android:layout_width="fill_parent"\r
-                android:src="@drawable/proj_back"\r
-                android:layout_weight=".16"/>\r
-\r
-                <ImageButton \r
-                style="?android:borderlessButtonStyle"\r
-                android:background="@color/btnColor" \r
-                android:id="@+id/proj_bottom"\r
-                android:layout_height="wrap_content" \r
-                android:layout_width="fill_parent"\r
-                android:src="@drawable/proj_bottom"\r
-                android:layout_weight=".16"/>\r
-\r
-                <ImageButton \r
-                style="?android:borderlessButtonStyle"\r
-                android:background="@color/btnColor" \r
-                android:id="@+id/proj_right"\r
-                android:layout_height="wrap_content" \r
-                android:layout_width="fill_parent"\r
-                android:src="@drawable/proj_right"\r
-                android:layout_weight=".16"/>\r
-            </LinearLayout>\r
-        </FrameLayout>\r
-    </LinearLayout>\r
-</TableLayout>\r
diff --git a/samples/java/jniviewer/res/values/id.xml b/samples/java/jniviewer/res/values/id.xml
deleted file mode 100644 (file)
index 56bde94..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-   <item name="open" type="id"/>
-   <item name="save" type="id"/>
-   <item name="screenshot" type="id"/>
-   <item name="mesh_none" type="id"/>
-   <item name="mesh_low_q" type="id"/>
-   <item name="mesh_norm_q" type="id"/>
-   <item name="mesh_high_q" type="id"/>
-   <item name="view1" type="id"/>
-   <item name="view2" type="id"/>
-   <item name="view3" type="id"/>
-   <item name="settings" type="id"/>
-   <item name="message" type="id"/>
-   <item name="lock" type="id"/>
-   <item name="info" type="id"/>
-</resources>
diff --git a/samples/java/jniviewer/res/values/strings.xml b/samples/java/jniviewer/res/values/strings.xml
deleted file mode 100644 (file)
index 6f2a431..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="app_name">OpenCASCADE JNI Java Sample</string>
-    <color name="btnColor">#484848</color>
-    <color name="pressedBtnColor">#0099CC</color>
-    <color name="viewColor">#66252525</color>
-        <string-array name="ext_to_save">
-        <item>.png</item>
-        <item>.jpg</item>
-    </string-array>
-    <string-array name="ext_to_exp">
-        <item>.brep</item>
-        <item>.rle</item>
-        <item>.iges</item>
-        <item>.igs</item>
-        <item>.step</item>
-        <item>.stp</item>
-    </string-array>
-    <string name="wireframe_shading_title">wireframe/shading</string>
-    <string name="color_title">color</string>
-    <string name="material_title">material</string>
-    <string name="transparency_title">transparency</string>
-    <string name="hidden_lines_title">show/hide hidden lines</string>
-    <string name="info_html" formatted="false">
-        <![CDATA[
-        <p>OpenCASCADE JNI Java Sample</p>
-        <p>Simple viewer for BREP, STEP and IGES files.</p>
-        <p>Driven by Open CASCADE Technology %d.%d.%d.</p>
-        <p>Copyright 2014 OPEN CASCADE SAS.</p>
-        <p><img src="info_image"></p>
-        <p>http://www.opencascade.com</p>
-        <p>http://www.opencascade.org</p>
-        ]]>
-    </string>
-</resources>
diff --git a/samples/java/jniviewer/settings.gradle b/samples/java/jniviewer/settings.gradle
new file mode 100644 (file)
index 0000000..e7b4def
--- /dev/null
@@ -0,0 +1 @@
+include ':app'
diff --git a/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniActivity.java b/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniActivity.java
deleted file mode 100644 (file)
index 7cb5366..0000000
+++ /dev/null
@@ -1,778 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-package com.opencascade.jnisample;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.List;
-
-import android.app.Activity;
-import android.content.Context;
-
-import android.content.Intent;
-import android.content.res.AssetManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Point;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-
-import android.text.Html;
-import android.text.Html.ImageGetter;
-import android.text.Spanned;
-import android.util.TypedValue;
-import android.view.Display;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.TextView;
-import android.widget.Toast;
-
-//! Main activity
-public class OcctJniActivity extends Activity implements OnClickListener
-{
-
-  //! Auxiliary method to print temporary info messages
-  public static void printShortInfo (Activity     theActivity,
-                                     CharSequence theInfo)
-  {
-    Context aCtx   = theActivity.getApplicationContext();
-    Toast   aToast = Toast.makeText (aCtx, theInfo, Toast.LENGTH_LONG);
-    aToast.show();
-  }
-
-  //! Load single native library
-  private static boolean loadLibVerbose (String        theLibName,
-                                         StringBuilder theLoadedInfo,
-                                         StringBuilder theFailedInfo)
-  {
-    try
-    {
-      System.loadLibrary (theLibName);
-      theLoadedInfo.append ("Info:  native library \"");
-      theLoadedInfo.append (theLibName);
-      theLoadedInfo.append ("\" has been loaded\n");
-      return true;
-    }
-    catch (java.lang.UnsatisfiedLinkError theError)
-    {
-      theFailedInfo.append ("Error: native library \"");
-      theFailedInfo.append (theLibName);
-      theFailedInfo.append ("\" is unavailable:\n  " + theError.getMessage());
-      return false;
-    }
-    catch (SecurityException theError)
-    {
-      theFailedInfo.append ("Error: native library \"");
-      theFailedInfo.append (theLibName);
-      theFailedInfo.append ("\" can not be loaded for security reasons:\n  " + theError.getMessage());
-      return false;
-    }
-  }
-
-  public static boolean wasNativesLoadCalled = false;
-  public static boolean areNativeLoaded      = false;
-  public static String  nativeLoaded         = "";
-  public static String  nativeFailed         = "";
-
-  //! Auxiliary method to load native libraries
-  public boolean loadNatives()
-  {
-    if (wasNativesLoadCalled)
-    {
-      return areNativeLoaded;
-    }
-    wasNativesLoadCalled = true;
-    StringBuilder aLoaded = new StringBuilder();
-    StringBuilder aFailed = new StringBuilder();
-
-    // copy OCCT resources
-    String aResFolder = getFilesDir().getAbsolutePath();
-    copyAssetFolder (getAssets(), "Shaders",   aResFolder + "/Shaders");
-    copyAssetFolder (getAssets(), "SHMessage", aResFolder + "/SHMessage");
-    copyAssetFolder (getAssets(), "XSMessage", aResFolder + "/XSMessage");
-    copyAssetFolder (getAssets(), "TObj",      aResFolder + "/TObj");
-    copyAssetFolder (getAssets(), "UnitsAPI",  aResFolder + "/UnitsAPI");
-
-    // C++ runtime
-    loadLibVerbose ("gnustl_shared", aLoaded, aFailed);
-
-    // 3rd-parties
-    loadLibVerbose ("freetype",  aLoaded, aFailed);
-    loadLibVerbose ("freeimage", aLoaded, aFailed);
-
-    if (// OCCT modeling
-        !loadLibVerbose ("TKernel",      aLoaded, aFailed)
-     || !loadLibVerbose ("TKMath",       aLoaded, aFailed)
-     || !loadLibVerbose ("TKG2d",        aLoaded, aFailed)
-     || !loadLibVerbose ("TKG3d",        aLoaded, aFailed)
-     || !loadLibVerbose ("TKGeomBase",   aLoaded, aFailed)
-     || !loadLibVerbose ("TKBRep",       aLoaded, aFailed)
-     || !loadLibVerbose ("TKGeomAlgo",   aLoaded, aFailed)
-     || !loadLibVerbose ("TKTopAlgo",    aLoaded, aFailed)
-     || !loadLibVerbose ("TKShHealing",  aLoaded, aFailed)
-     || !loadLibVerbose ("TKMesh",       aLoaded, aFailed)
-        // exchange
-     || !loadLibVerbose ("TKPrim",       aLoaded, aFailed)
-     || !loadLibVerbose ("TKBO",         aLoaded, aFailed)
-     || !loadLibVerbose ("TKBool",       aLoaded, aFailed)
-     || !loadLibVerbose ("TKFillet",     aLoaded, aFailed)
-     || !loadLibVerbose ("TKOffset",     aLoaded, aFailed)
-     || !loadLibVerbose ("TKXSBase",     aLoaded, aFailed)
-     || !loadLibVerbose ("TKIGES",       aLoaded, aFailed)
-     || !loadLibVerbose ("TKSTEPBase",   aLoaded, aFailed)
-     || !loadLibVerbose ("TKSTEPAttr",   aLoaded, aFailed)
-     || !loadLibVerbose ("TKSTEP209",    aLoaded, aFailed)
-     || !loadLibVerbose ("TKSTEP",       aLoaded, aFailed)
-        // OCCT Visualization
-     || !loadLibVerbose ("TKService",    aLoaded, aFailed)
-     || !loadLibVerbose ("TKHLR",        aLoaded, aFailed)
-     || !loadLibVerbose ("TKV3d",        aLoaded, aFailed)
-     || !loadLibVerbose ("TKOpenGl",     aLoaded, aFailed)
-        // application code
-     || !loadLibVerbose ("TKJniSample",  aLoaded, aFailed))
-    {
-      nativeLoaded = aLoaded.toString();
-      nativeFailed = aFailed.toString();
-      areNativeLoaded = false;
-      //exitWithError (theActivity, "Broken apk?\n" + theFailedInfo);
-      return false;
-    }
-    nativeLoaded = aLoaded.toString();
-    areNativeLoaded = true;
-    return true;
-  }
-
-  //! Create activity
-  @Override protected void onCreate (Bundle theBundle)
-  {
-    super.onCreate (theBundle);
-
-    boolean isLoaded = loadNatives();
-    if (!isLoaded)
-    {
-      printShortInfo (this, nativeFailed);
-      OcctJniLogger.postMessage (nativeLoaded + "\n" + nativeFailed);
-    }
-
-    setContentView (R.layout.activity_main);
-    
-    myOcctView        = (OcctJniView )findViewById (R.id.custom_view);
-    myMessageTextView = (TextView    )findViewById (R.id.message_view);
-    OcctJniLogger.setTextView (myMessageTextView);
-
-    createViewAndButtons (Configuration.ORIENTATION_LANDSCAPE);
-
-    myButtonPreferSize = defineButtonSize ((LinearLayout )findViewById (R.id.panel_menu));
-    ImageButton aScrollBtn = (ImageButton )findViewById (R.id.scroll_btn);
-    aScrollBtn.setY (myButtonPreferSize);
-    aScrollBtn.setOnTouchListener (new View.OnTouchListener()
-    {
-      @Override
-      public boolean onTouch (View theView, MotionEvent theEvent)
-      {
-        return onScrollBtnTouch (theView, theEvent);
-      }
-    });
-
-    onConfigurationChanged (getResources().getConfiguration());
-
-    Intent anIntent = getIntent();
-    Uri    aDataUrl  = anIntent != null ? anIntent.getData() : null;
-    String aDataPath = aDataUrl != null ? aDataUrl.getPath() : "";
-    myOcctView.open (aDataPath);
-    myLastPath = aDataPath;
-  }
-
-  //! Handle scroll events
-  private boolean onScrollBtnTouch (View        theView,
-                                    MotionEvent theEvent)
-  {
-    switch (theEvent.getAction())
-    {
-      case MotionEvent.ACTION_DOWN:
-      {
-        LinearLayout aPanelMenu = (LinearLayout )findViewById (R.id.panel_menu);
-        boolean isLandscape = (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
-        if (aPanelMenu.getVisibility() == View.VISIBLE)
-        {
-          aPanelMenu.setVisibility (View.GONE);
-          if (!isLandscape)
-          {
-            ((ImageButton )theView).setImageResource (R.drawable.open_p);
-            theView.setY (0);
-          }
-          else
-          {
-            ((ImageButton )theView).setImageResource (R.drawable.open_l);
-            theView.setX (0);
-          }
-        }
-        else
-        {
-          aPanelMenu.setVisibility (View.VISIBLE);
-          if (!isLandscape)
-          {
-            ((ImageButton )theView).setImageResource (R.drawable.close_p);
-            theView.setY (myButtonPreferSize);
-          }
-          else
-          {
-            ((ImageButton )theView).setImageResource (R.drawable.close_l);
-            theView.setX (myButtonPreferSize);
-          }
-        }
-        break;
-      }
-    }
-    return false;
-  }
-
-  //! Initialize views and buttons
-  private void createViewAndButtons (int theOrientation)
-  {
-    // open button
-    ImageButton anOpenButton = (ImageButton )findViewById (R.id.open);
-    anOpenButton.setOnClickListener (this);
-
-    // fit all
-    ImageButton aFitAllButton = (ImageButton )findViewById (R.id.fit);
-    aFitAllButton.setOnClickListener (this);
-    aFitAllButton.setOnTouchListener (new View.OnTouchListener()
-    {
-      @Override
-      public boolean onTouch (View theView, MotionEvent theEvent)
-      {
-        return onTouchButton (theView, theEvent);
-      }
-    });
-    
-    // message
-    ImageButton aMessageButton = (ImageButton )findViewById (R.id.message);
-    aMessageButton.setOnClickListener (this);
-
-    // info
-    ImageButton anInfoButton = (ImageButton )findViewById (R.id.info);
-    anInfoButton.setOnClickListener (this);
-    
-    // font for text view
-    TextView anInfoView = (TextView )findViewById (R.id.info_view);
-    anInfoView.setTextSize (TypedValue.COMPLEX_UNIT_SP, 18);
-
-    // add submenu buttons
-    createSubmenuBtn (R.id.view, R.id.view_group,
-                      Arrays.asList (R.id.proj_front, R.id.proj_top,    R.id.proj_left,
-                                     R.id.proj_back,  R.id.proj_bottom, R.id.proj_right),
-                      Arrays.asList (R.drawable.proj_front, R.drawable.proj_top,    R.drawable.proj_left,
-                                     R.drawable.proj_back,  R.drawable.proj_bottom, R.drawable.proj_right),
-                      4);
-  }
-
-  @Override protected void onNewIntent (Intent theIntent)
-  {
-    super.onNewIntent (theIntent);
-    setIntent (theIntent);
-  }
-
-  @Override protected void onDestroy()
-  {
-    super.onDestroy();
-    OcctJniLogger.setTextView (null);
-  }
-
-  @Override protected void onPause()
-  {
-    super.onPause();
-    myOcctView.onPause();
-  }
-
-  @Override protected void onResume()
-  {
-    super.onResume();
-    myOcctView.onResume();
-
-    Intent anIntent = getIntent();
-    Uri    aDataUrl  = anIntent != null ? anIntent.getData() : null;
-    String aDataPath = aDataUrl != null ? aDataUrl.getPath() : "";
-    if (!aDataPath.equals (myLastPath))
-    {
-      myOcctView.open (aDataPath);
-      myLastPath = aDataPath;
-    }
-  }
-
-  //! Copy folder from assets
-  private boolean copyAssetFolder (AssetManager theAssetMgr,
-                                   String       theAssetFolder,
-                                   String       theFolderPathTo)
-  {
-    try
-    {
-      String[] aFiles  = theAssetMgr.list (theAssetFolder);
-      File     aFolder = new File (theFolderPathTo);
-      aFolder.mkdirs();
-      boolean isOk = true;
-      for (String aFileIter : aFiles)
-      {
-        if (aFileIter.contains ("."))
-        {
-          isOk &= copyAsset (theAssetMgr,
-                             theAssetFolder  + "/" + aFileIter,
-                             theFolderPathTo + "/" + aFileIter);
-        }
-        else
-        {
-          isOk &= copyAssetFolder (theAssetMgr,
-                                   theAssetFolder  + "/" + aFileIter,
-                                   theFolderPathTo + "/" + aFileIter);
-        }
-      }
-      return isOk;
-    }
-    catch (Exception theError)
-    {
-      theError.printStackTrace();
-      return false;
-    }
-  }
-
-  //! Copy single file from assets
-  private boolean copyAsset (AssetManager theAssetMgr,
-                             String       thePathFrom,
-                             String       thePathTo)
-  {
-    try
-    {
-      InputStream aStreamIn = theAssetMgr.open (thePathFrom);
-      File aFileTo = new File (thePathTo);
-      aFileTo.createNewFile();
-      OutputStream aStreamOut = new FileOutputStream (thePathTo);
-      copyStreamContent (aStreamIn, aStreamOut);
-      aStreamIn.close();
-      aStreamIn = null;
-      aStreamOut.flush();
-      aStreamOut.close();
-      aStreamOut = null;
-      return true;
-    }
-    catch (Exception theError)
-    {
-      theError.printStackTrace();
-      return false;
-    }
-  }
-
-  //! Copy single file
-  private static void copyStreamContent (InputStream  theIn,
-                                         OutputStream theOut) throws IOException
-  {
-    byte[] aBuffer = new byte[1024];
-    int aNbReadBytes = 0;
-    while ((aNbReadBytes = theIn.read (aBuffer)) != -1)
-    {
-      theOut.write (aBuffer, 0, aNbReadBytes);
-    }
-  }
-  
-  //! Show/hide text view
-  private void switchTextView (TextView    theTextView,
-                               ImageButton theClickedBtn,
-                               boolean     theToSwitchOn)
-  {
-    if (theTextView != null
-     && theTextView.getVisibility() == View.GONE
-     && theToSwitchOn)
-    {
-      theTextView.setVisibility (View.VISIBLE);
-      theClickedBtn.setBackgroundColor (getResources().getColor(R.color.pressedBtnColor));
-      setTextViewPosition (theTextView);
-    }
-    else
-    {
-      theTextView.setVisibility (View.GONE);
-      theClickedBtn.setBackgroundColor (getResources().getColor (R.color.btnColor));
-    }
-  }
-
-  //! Setup text view position
-  private void setTextViewPosition (TextView theTextView)
-  {
-    if (theTextView.getVisibility() != View.VISIBLE)
-    {
-      return;
-    }
-
-    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
-    {
-      theTextView.setX (myButtonPreferSize);
-      theTextView.setY (0);
-    }
-    else
-    {
-      theTextView.setX (0);
-      theTextView.setY (myButtonPreferSize);
-    }
-  }
-
-  @Override
-  public void onClick (View theButton)
-  {
-    ImageButton aClickedBtn = (ImageButton )theButton;
-    switch (aClickedBtn.getId())
-    {
-      case R.id.message:
-      {
-        switchTextView ((TextView    )findViewById (R.id.info_view),
-                        (ImageButton )findViewById (R.id.info), false);
-        switchTextView (myMessageTextView, aClickedBtn, true);
-        return;
-      }
-      case R.id.info:
-      {
-        String aText = getString (R.string.info_html);
-        aText = String.format (aText, cppOcctMajorVersion(), cppOcctMinorVersion(), cppOcctMicroVersion());
-        Spanned aSpanned = Html.fromHtml (aText, new ImageGetter()
-        {
-          @Override
-          public Drawable getDrawable (String theSource)
-          {
-            Resources aResources = getResources();
-            int anId = aResources.getIdentifier (theSource, "drawable", getPackageName());
-            Drawable aRes = aResources.getDrawable (anId);
-            aRes.setBounds (0, 0, aRes.getIntrinsicWidth(), aRes.getIntrinsicHeight());
-            return aRes;
-          }
-        }, null);
-
-        TextView anInfoView = (TextView )findViewById (R.id.info_view);
-        anInfoView.setText (aSpanned);
-        switchTextView (myMessageTextView, (ImageButton ) findViewById (R.id.message), false);
-        switchTextView (anInfoView,        aClickedBtn,                                true);
-        return;
-      }
-      case R.id.fit:
-      {
-        myOcctView.fitAll();
-        return;
-      }
-      case R.id.proj_front:
-      {
-        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Xpos);
-        return;
-      }
-      case R.id.proj_left:
-      {
-        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Yneg);
-        return;
-      }
-      case R.id.proj_top:
-      {
-        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Zpos);
-        return;
-      }
-      case R.id.proj_back:
-      {
-        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Xneg);
-        return;
-      }
-      case R.id.proj_right:
-      {
-        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Ypos);
-        return;
-      }
-      case R.id.proj_bottom:
-      {
-        myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Zneg);
-        return;
-      }
-      case R.id.open:
-      {
-        File aPath = Environment.getExternalStorageDirectory();
-        aClickedBtn.setBackgroundColor (getResources().getColor(R.color.pressedBtnColor));
-        if (myFileOpenDialog == null)
-        {
-          myFileOpenDialog = new OcctJniFileDialog (this, aPath);
-          myFileOpenDialog.setFileEndsWith (".brep");
-          myFileOpenDialog.setFileEndsWith (".rle");
-          myFileOpenDialog.setFileEndsWith (".iges");
-          myFileOpenDialog.setFileEndsWith (".igs");
-          myFileOpenDialog.setFileEndsWith (".step");
-          myFileOpenDialog.setFileEndsWith (".stp");
-          myFileOpenDialog.addFileListener (new OcctJniFileDialog.FileSelectedListener()
-          {
-            public void fileSelected (File theFile)
-            {
-              if (theFile != null && myOcctView != null)
-              {
-                myOcctView.open (theFile.getPath());
-              }
-            }
-          });
-          myFileOpenDialog.addDialogDismissedListener (new OcctJniFileDialog.DialogDismissedListener()
-          {
-            @Override
-            public void dialogDismissed()
-            {
-              ImageButton openButton = (ImageButton )findViewById (R.id.open);
-              openButton.setBackgroundColor (getResources().getColor(R.color.btnColor));
-            }
-          });
-        }
-        myFileOpenDialog.showDialog();
-        return;
-      }
-    }
-  }
-
-  private void createSubmenuBtn (int     theParentBtnId,
-                                 int     theParentLayoutId,
-                                 final List<Integer> theNewButtonIds,
-                                 final List<Integer> theNewButtonImageIds,
-                                 int     thePosition)
-  {
-    int aPosInList = 0;
-    final ImageButton aParentBtn = (ImageButton )findViewById (theParentBtnId);
-
-    ViewGroup.LayoutParams aParams = null;
-    LinearLayout parentLayout = (LinearLayout ) findViewById (theParentLayoutId);
-    for (Integer newButtonId : theNewButtonIds)
-    {
-      ImageButton aNewButton = (ImageButton )findViewById (newButtonId);
-      if (aNewButton == null)
-      {
-        aNewButton = (ImageButton )new ImageButton (this);
-        aNewButton.setId (newButtonId);
-        aNewButton.setImageResource (theNewButtonImageIds.get (aPosInList));
-        aNewButton.setLayoutParams (aParams);
-        parentLayout.addView (aNewButton);
-      }
-
-      aNewButton.setOnClickListener (this);
-      aNewButton.setVisibility (View.GONE);
-
-      aNewButton.setOnTouchListener (new View.OnTouchListener()
-      {
-        @Override
-        public boolean onTouch (View theView, MotionEvent theEvent)
-        {
-          return onTouchButton (theView, theEvent);
-        }
-      });
-      ++aPosInList;
-    }
-
-    if (aParentBtn != null)
-    {
-      aParentBtn.setOnTouchListener (null);
-      aParentBtn.setOnTouchListener (new View.OnTouchListener()
-      {
-        @Override
-        public boolean onTouch (View theView, MotionEvent theEvent)
-        {
-          if (theEvent.getAction () == MotionEvent.ACTION_DOWN)
-          {
-            Boolean isVisible = false;
-            for (Integer aNewButtonId : theNewButtonIds)
-            {
-              ImageButton anBtn = (ImageButton )findViewById (aNewButtonId);
-              if (anBtn != null)
-              {
-                if (anBtn.getVisibility() == View.GONE)
-                {
-                  anBtn.setVisibility (View.VISIBLE);
-                  isVisible = true;
-                }
-                else
-                {
-                  anBtn.setVisibility (View.GONE);
-                }
-              }
-            }
-            aParentBtn.setBackgroundColor (!isVisible ? getResources().getColor(R.color.btnColor) : getResources().getColor(R.color.pressedBtnColor));
-          }
-          return false;
-        }
-      });
-    }
-  }
-
-  //! Implements onTouch functionality
-  private boolean onTouchButton (View        theView,
-                                 MotionEvent theEvent)
-  {
-    switch (theEvent.getAction())
-    {
-      case MotionEvent.ACTION_DOWN:
-        ((ImageButton )theView).setBackgroundColor (getResources().getColor (R.color.pressedBtnColor));
-        break;
-      case MotionEvent.ACTION_UP:
-        ((ImageButton )theView).setBackgroundColor (getResources().getColor (R.color.btnColor));
-        break;
-    }
-    return false;
-  }
-
-  //! Handle configuration change event
-  @Override
-  public void onConfigurationChanged (Configuration theNewConfig)
-  {
-    super.onConfigurationChanged (theNewConfig);
-    LinearLayout aLayoutPanelMenu       = (LinearLayout )findViewById (R.id.panel_menu);
-    LayoutParams aPanelMenuLayoutParams = aLayoutPanelMenu.getLayoutParams();
-
-    LinearLayout aLayoutViewGroup       = (LinearLayout )findViewById (R.id.view_group);
-    LayoutParams aViewGroupLayoutParams = aLayoutViewGroup.getLayoutParams();
-    ImageButton  aScrollBtn             = (ImageButton )findViewById (R.id.scroll_btn);
-    LayoutParams aScrollBtnLayoutParams = aScrollBtn.getLayoutParams();
-
-    myButtonPreferSize = defineButtonSize ((LinearLayout )findViewById (R.id.panel_menu));
-    defineButtonSize ((LinearLayout )findViewById (R.id.view_group));
-
-    switch (theNewConfig.orientation)
-    {
-      case Configuration.ORIENTATION_PORTRAIT:
-      {
-        setHorizontal (aLayoutPanelMenu, aPanelMenuLayoutParams);
-        setHorizontal (aLayoutViewGroup, aViewGroupLayoutParams);
-        aLayoutViewGroup.setGravity (Gravity.BOTTOM);
-
-        aScrollBtnLayoutParams.height = LayoutParams.WRAP_CONTENT;
-        aScrollBtnLayoutParams.width  = LayoutParams.MATCH_PARENT;
-        aScrollBtn.setLayoutParams (aScrollBtnLayoutParams);
-        if (aLayoutPanelMenu.getVisibility() == View.VISIBLE)
-        {
-          aScrollBtn.setImageResource (R.drawable.close_p);
-          aScrollBtn.setY (myButtonPreferSize);
-          aScrollBtn.setX (0);
-        }
-        else
-        {
-          aScrollBtn.setImageResource (R.drawable.open_p);
-          aScrollBtn.setY (0);
-          aScrollBtn.setX (0);
-        }
-        break;
-      }
-      case Configuration.ORIENTATION_LANDSCAPE:
-      {
-        setVertical (aLayoutPanelMenu, aPanelMenuLayoutParams);
-        setVertical (aLayoutViewGroup, aViewGroupLayoutParams);
-        aLayoutViewGroup.setGravity (Gravity.RIGHT);
-
-        aScrollBtnLayoutParams.height = LayoutParams.MATCH_PARENT;
-        aScrollBtnLayoutParams.width  = LayoutParams.WRAP_CONTENT;
-        aScrollBtn.setLayoutParams (aScrollBtnLayoutParams);
-        if (aLayoutPanelMenu.getVisibility() == View.VISIBLE)
-        {
-          aScrollBtn.setImageResource (R.drawable.close_l);
-          aScrollBtn.setX (myButtonPreferSize);
-          aScrollBtn.setY (0);
-        }
-        else
-        {
-          aScrollBtn.setImageResource (R.drawable.open_l);
-          aScrollBtn.setY (0);
-          aScrollBtn.setX (0);
-        }
-        break;
-      }
-    }
-    setTextViewPosition (myMessageTextView);
-    setTextViewPosition ((TextView )findViewById (R.id.info_view));
-  }
-
-  private void setHorizontal (LinearLayout theLayout,
-                              LayoutParams theLayoutParams)
-  {
-    theLayout.setOrientation (LinearLayout.HORIZONTAL);
-    theLayoutParams.height = LayoutParams.WRAP_CONTENT;
-    theLayoutParams.width  = LayoutParams.MATCH_PARENT;
-    theLayout.setLayoutParams (theLayoutParams);
-  }
-
-  private void setVertical (LinearLayout theLayout,
-                            LayoutParams theLayoutParams)
-  {
-    theLayout.setOrientation (LinearLayout.VERTICAL);
-    theLayoutParams.height = LayoutParams.MATCH_PARENT;
-    theLayoutParams.width  = LayoutParams.WRAP_CONTENT;
-    theLayout.setLayoutParams (theLayoutParams);
-  }
-
-  //! Define button size
-  private int defineButtonSize (LinearLayout theLayout)
-  {
-    boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
-    Display aDisplay    = getWindowManager().getDefaultDisplay();
-    Point   aDispPnt    = new Point();
-    aDisplay.getSize (aDispPnt);
-
-    int aNbChildren = theLayout.getChildCount();
-    int aHeight     = aDispPnt.y / aNbChildren;
-    int aWidth      = aDispPnt.x / aNbChildren;
-    int aResultSize = 0;
-    for (int aChildIter = 0; aChildIter < aNbChildren; ++aChildIter)
-    {
-      View aView = theLayout.getChildAt (aChildIter);
-      if (aView instanceof ImageButton)
-      {
-        ImageButton aButton = (ImageButton )aView;
-        if (isLandscape)
-        {
-          aButton.setMinimumWidth (aHeight);
-        }
-        else
-        {
-          aButton.setMinimumHeight (aWidth);
-        }
-      }
-    }
-    if (isLandscape)
-    {
-      aResultSize = aHeight;
-    }
-    else
-    {
-      aResultSize = aWidth;
-    }
-    return aResultSize;
-  }
-
-  //! OCCT major version
-  private native long cppOcctMajorVersion();
-
-  //! OCCT minor version
-  private native long cppOcctMinorVersion();
-
-  //! OCCT micro version
-  private native long cppOcctMicroVersion();
-
-  private OcctJniView       myOcctView;
-  private TextView          myMessageTextView;
-  private String            myLastPath;
-  private OcctJniFileDialog myFileOpenDialog;
-  private int               myButtonPreferSize = 65;
-
-}
diff --git a/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniFileDialog.java b/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniFileDialog.java
deleted file mode 100644 (file)
index e12cc1a..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-package com.opencascade.jnisample;
-
-import java.io.File;
-import java.io.FilenameFilter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import com.opencascade.jnisample.ListenerList.FireHandler;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.graphics.Color;
-import android.os.Environment;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.Spinner;
-
-//! Simple open file dialog
-public class OcctJniFileDialog
-{
-
-  public enum DialogMode
-  {
-    FileOpen, FileExport, FileSave
-  }
-
-  private static final String PARENT_DIR = "..";
-  private String[]   myFileList;
-  private File       myCurrentPath;
-  private DialogMode myDialogMode = DialogMode.FileOpen;
-
-  private ListenerList<FileSelectedListener>    myFileListenerList    = new ListenerList<OcctJniFileDialog.FileSelectedListener>();
-  private ListenerList<DialogDismissedListener> myDialogDismissedList = new ListenerList<DialogDismissedListener>();
-  private final Activity myActivity;
-  private List<String>   myFileEndsWith;
-  private EditText myFileNameInput;
-  private Spinner  myFileExtSpinner;
-  int myCurrentExtPositionInList = 0;
-
-  public interface FileSelectedListener
-  {
-    void fileSelected (File theFile);
-  }
-
-  public interface DialogDismissedListener
-  {
-    void dialogDismissed();
-  }
-
-  //! Main constructor.
-  public OcctJniFileDialog (Activity theActivity,
-                            File     thePath)
-  {
-    myActivity = theActivity;
-    if (!thePath.exists())
-    {
-      thePath = Environment.getExternalStorageDirectory();
-    }
-    loadFileList (thePath);
-  }
-
-  //! Create new dialog
-  public Dialog createFileDialog()
-  {
-    final Object[] anObjWrapper = new Object[1];
-    Dialog aDialog = null;
-    AlertDialog.Builder aBuilder = new AlertDialog.Builder (myActivity);
-
-    aBuilder.setTitle (myCurrentPath.getPath());
-    LinearLayout aTitleLayout = new LinearLayout (myActivity);
-    aTitleLayout.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
-    aTitleLayout.setOrientation (LinearLayout.VERTICAL);
-
-    ListView list = new ListView (myActivity);
-    list.setScrollingCacheEnabled(false);
-    list.setBackgroundColor (Color.parseColor ("#33B5E5"));
-
-    list.setAdapter (new ArrayAdapter<String> (myActivity, android.R.layout.select_dialog_item, myFileList));
-    list.setOnItemClickListener (new AdapterView.OnItemClickListener ()
-    {
-
-      public void onItemClick (AdapterView<?> arg0, View view, int pos, long id)
-      {
-        String fileChosen = myFileList[pos];
-        File aChosenFile = getChosenFile (fileChosen);
-        if (aChosenFile.isDirectory())
-        {
-          loadFileList (aChosenFile);
-          ((Dialog )anObjWrapper[0]).cancel();
-          ((Dialog )anObjWrapper[0]).dismiss();
-          showDialog();
-        }
-        else
-        {
-          if (myDialogMode == DialogMode.FileOpen)
-          {
-            ((Dialog )anObjWrapper[0]).cancel();
-            ((Dialog )anObjWrapper[0]).dismiss();
-            fireFileSelectedEvent (aChosenFile);
-          }
-          else
-          {
-            myFileNameInput.setText (aChosenFile.getName());
-          }
-        }
-      }
-    });
-    list.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 0.6f));
-    aTitleLayout.addView (list);
-
-    if (myDialogMode == DialogMode.FileSave
-     || myDialogMode == DialogMode.FileExport)
-    {
-      myFileNameInput  = new EditText (myActivity);
-      myFileExtSpinner = new Spinner  (myActivity);
-      ArrayAdapter<CharSequence> adapter = null;
-      if (myDialogMode == DialogMode.FileExport)
-      {
-        adapter = ArrayAdapter.createFromResource (myActivity, R.array.ext_to_exp,
-            android.R.layout.simple_spinner_item);
-      }
-      else
-      {
-        adapter = ArrayAdapter.createFromResource (myActivity, R.array.ext_to_save,
-            android.R.layout.simple_spinner_item);
-      }
-      // Specify the layout to use when the list of choices appears
-      adapter.setDropDownViewResource (android.R.layout.simple_spinner_dropdown_item);
-      // Apply the adapter to the spinner
-      myFileExtSpinner.setAdapter (adapter);
-      myFileExtSpinner.setSelection (myCurrentExtPositionInList);
-
-      myFileExtSpinner.setOnItemSelectedListener (new AdapterView.OnItemSelectedListener()
-      {
-
-        @Override
-        public void onNothingSelected (AdapterView<?> theParentView)
-        {
-          // your code here
-        }
-
-        @Override
-        public void onItemSelected (AdapterView<?> theParent, View theView, int thePosition, long theId)
-        {
-          if (myCurrentExtPositionInList != thePosition)
-          {
-            myCurrentExtPositionInList = thePosition;
-            setFileEndsWith (Arrays.asList (myFileExtSpinner.getSelectedItem().toString()));
-            loadFileList (myCurrentPath);
-            ((Dialog )anObjWrapper[0]).cancel();
-            ((Dialog )anObjWrapper[0]).dismiss();
-            showDialog();
-          }
-        }
-      });
-
-      myFileExtSpinner.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT,
-          LayoutParams.WRAP_CONTENT, 0.2f));
-      // titleLayout.addView(fileExtSpinner);
-      myFileNameInput.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT,
-          LayoutParams.WRAP_CONTENT, 0.2f));
-      LinearLayout aControlsView = new LinearLayout (myActivity);
-
-      aControlsView.addView (myFileNameInput);
-      aControlsView.addView (myFileExtSpinner);
-
-      aTitleLayout.addView (aControlsView);
-      aBuilder.setView (aTitleLayout);
-      aBuilder.setPositiveButton ("OK", new DialogInterface.OnClickListener()
-      {
-        @Override
-        public void onClick (DialogInterface theDialog, int theWhich)
-        {
-          if (theWhich >= 0)
-          {
-            String aFileChosen = myFileList[theWhich];
-            File aChosenFile = getChosenFile (aFileChosen);
-            fireFileSelectedEvent (aChosenFile);
-          }
-        }
-      }).setNegativeButton ("Cancel", null);
-    }
-    else
-    {
-      aBuilder.setNegativeButton ("Cancel", null);
-    }
-
-    aBuilder.setView (aTitleLayout);
-
-    aDialog = aBuilder.show();
-    aDialog.setOnDismissListener (new DialogInterface.OnDismissListener()
-    {
-      @Override
-      public void onDismiss (DialogInterface theDialog)
-      {
-        fireDialogDismissedEvent();
-      }
-    });
-    anObjWrapper[0] = aDialog;
-    return aDialog;
-  }
-
-  public void addFileListener (FileSelectedListener theListener)
-  {
-    myFileListenerList.add (theListener);
-  }
-
-  public void addDialogDismissedListener (DialogDismissedListener theListener)
-  {
-    myDialogDismissedList.add (theListener);
-  }
-
-  //! Show file dialog
-  public void showDialog()
-  {
-    createFileDialog().show();
-  }
-
-  private void fireFileSelectedEvent (final File theFile)
-  {
-    myFileListenerList.fireEvent (new FireHandler<OcctJniFileDialog.FileSelectedListener>()
-    {
-      public void fireEvent (FileSelectedListener theListener)
-      {
-        theListener.fileSelected (theFile);
-      }
-    });
-  }
-
-  private void fireDialogDismissedEvent()
-  {
-    myDialogDismissedList.fireEvent (new FireHandler<OcctJniFileDialog.DialogDismissedListener>()
-    {
-      public void fireEvent (DialogDismissedListener theListener)
-      {
-        theListener.dialogDismissed();
-      }
-    });
-  }
-
-  private void loadFileList (File thePath)
-  {
-    myCurrentPath = thePath;
-    List<String> aList = new ArrayList<String>();
-    if (thePath.exists())
-    {
-      if (thePath.getParentFile() != null)
-      {
-        aList.add (PARENT_DIR);
-      }
-      FilenameFilter aFilter = new FilenameFilter()
-      {
-        public boolean accept (File theDir, String theFilename)
-        {
-          File aSel = new File (theDir, theFilename);
-          if (!aSel.canRead())
-          {
-            return false;
-          }
-          boolean isEndWith = false;
-          if (myFileEndsWith != null)
-          {
-            for (String aFileExtIter : myFileEndsWith)
-            {
-              if (theFilename.toLowerCase().endsWith (aFileExtIter))
-              {
-                isEndWith = true;
-                break;
-              }
-            }
-          }
-          return isEndWith || aSel.isDirectory();
-        }
-      };
-      String[] aFileList1 = thePath.list (aFilter);
-      if (aFileList1 != null)
-      {
-        for (String aFileIter : aFileList1)
-        {
-          aList.add (aFileIter);
-        }
-      }
-    }
-    myFileList = (String[] )aList.toArray (new String[] {});
-  }
-
-  private File getChosenFile (String theFileChosen)
-  {
-    if (theFileChosen.equals (PARENT_DIR))
-      return myCurrentPath.getParentFile();
-    else
-      return new File (myCurrentPath, theFileChosen);
-  }
-
-  public void setFileEndsWith (String fileEndsWith)
-  {
-    if (myFileEndsWith == null)
-    {
-      myFileEndsWith = new ArrayList<String>();
-    }
-    if (myFileEndsWith.indexOf (fileEndsWith) == -1)
-    {
-      myFileEndsWith.add (fileEndsWith);
-    }
-  }
-
-  public void setFileEndsWith (List<String> theFileEndsWith)
-  {
-    myFileEndsWith = theFileEndsWith;
-  }
-
-  public DialogMode DialogMode()
-  {
-    return myDialogMode;
-  }
-
-  public void DialogMode (DialogMode theMode)
-  {
-    myDialogMode = theMode;
-  }
-}
-
-class ListenerList<L>
-{
-  private List<L> myListenerList = new ArrayList<L>();
-
-  public interface FireHandler<L>
-  {
-    void fireEvent (L theListener);
-  }
-
-  public void add (L theListener)
-  {
-    myListenerList.add (theListener);
-  }
-
-  public void fireEvent (FireHandler<L> theFireHandler)
-  {
-    List<L> aCopy = new ArrayList<L> (myListenerList);
-    for (L anIter : aCopy)
-    {
-      theFireHandler.fireEvent (anIter);
-    }
-  }
-
-  public void remove (L theListener)
-  {
-    myListenerList.remove (theListener);
-  }
-
-  public List<L> getListenerList()
-  {
-    return myListenerList;
-  }
-}
diff --git a/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniLogger.java b/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniLogger.java
deleted file mode 100644 (file)
index cc8b1e4..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-package com.opencascade.jnisample;
-
-import java.util.concurrent.locks.ReentrantLock;
-
-import android.util.Log;
-import android.widget.TextView;
-
-//! Auxiliary class for logging messages
-public class OcctJniLogger
-{
-
-  //! Setup text view
-  public static void setTextView (TextView theTextView)
-  {
-    if (myTextView != null)
-    {
-      myLog = myTextView.getText().toString();
-    }
-
-    myTextView = theTextView;
-    if (myTextView != null)
-    {
-      myTextView.setText (myLog);
-      myLog = "";
-    }
-  }
-
-  //! Interface implementation
-  public static void postMessage (String theText)
-  {
-    final String aCopy = new String (theText);
-    Log.e (myTag, theText);
-
-    myMutex.lock();
-    final TextView aView = myTextView;
-    if (aView == null)
-    {
-      myLog += aCopy;
-      myMutex.unlock();
-      return;
-    }
-
-    aView.post (new Runnable()
-    {
-      public void run()
-      {
-        aView.setText (aView.getText() + aCopy + "\n");
-      }
-    });
-    myMutex.unlock();
-  }
-
-  private static final String        myTag      = "occtJniViewer";
-  private static final ReentrantLock myMutex    = new ReentrantLock (true);
-  private static TextView            myTextView = null;
-  private static String              myLog      = "";
-
-}
diff --git a/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniRenderer.java b/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniRenderer.java
deleted file mode 100644 (file)
index 731037a..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-package com.opencascade.jnisample;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-import android.opengl.GLSurfaceView;
-
-//! Wrapper for C++ OCCT viewer.
-public class OcctJniRenderer implements GLSurfaceView.Renderer
-{
-
-  //! Wrapper for V3d_TypeOfOrientation
-  enum TypeOfOrientation
-  {
-    Xpos, // front
-    Ypos, // left
-    Zpos, // top
-    Xneg, // back
-    Yneg, // right
-    Zneg  // bottom
-  };
-
-  //! Empty constructor.
-  OcctJniRenderer()
-  {
-    if (OcctJniActivity.areNativeLoaded)
-    {
-      myCppViewer = cppCreate();
-    }
-  }
-
-  //! Open file.
-  public void open (String thePath)
-  {
-    if (myCppViewer != 0)
-    {
-      cppOpen (myCppViewer, thePath);
-    }
-  }
-
-  //! Update viewer.
-  public void onDrawFrame (GL10 theGl)
-  {
-    if (myCppViewer != 0)
-    {
-      cppRedraw (myCppViewer);
-    }
-  }
-
-  //! (re)initialize viewer.
-  public void onSurfaceChanged (GL10 theGl, int theWidth, int theHeight)
-  {
-    if (myCppViewer != 0)
-    {
-      cppResize (myCppViewer, theWidth, theHeight);
-    }
-  }
-
-  public void onSurfaceCreated (GL10 theGl, EGLConfig theEglConfig)
-  {
-    if (myCppViewer != 0)
-    {
-      cppInit (myCppViewer);
-    }
-  }
-
-  //! Initialize rotation (remember first point position)
-  public void onStartRotation (int theStartX, int theStartY)
-  {
-    if (myCppViewer != 0)
-    {
-      cppStartRotation (myCppViewer, theStartX, theStartY);
-    }
-  }
-
-  //! Perform rotation (relative to first point)
-  public void onRotation (int theX, int theY)
-  {
-    if (myCppViewer != 0)
-    {
-      cppOnRotation (myCppViewer, theX, theY);
-    }
-  }
-
-  //! Perform panning
-  public void onPanning (int theDX, int theDY)
-  {
-    if (myCppViewer != 0)
-    {
-      cppOnPanning (myCppViewer, theDX, theDY);
-    }
-  }
-
-  //! Perform selection
-  public void onClick (int theX, int theY)
-  {
-    if (myCppViewer != 0)
-    {
-      cppOnClick (myCppViewer, theX, theY);
-    }
-  }
-
-  //! Stop previously active action (e.g. discard first rotation point)
-  public void onStopAction()
-  {
-    if (myCppViewer != 0)
-    {
-      cppStopAction (myCppViewer);
-    }
-  }
-
-  //! Fit All
-  public void fitAll()
-  {
-    if (myCppViewer != 0)
-    {
-      cppFitAll (myCppViewer);
-    }
-  }
-
-  //! Move camera
-  public void setProj (TypeOfOrientation theProj)
-  {
-    if (myCppViewer == 0)
-    {
-      return;
-    }
-
-    switch (theProj)
-    {
-      case Xpos: cppSetXposProj (myCppViewer); break;
-      case Ypos: cppSetYposProj (myCppViewer); break;
-      case Zpos: cppSetZposProj (myCppViewer); break;
-      case Xneg: cppSetXnegProj (myCppViewer); break;
-      case Yneg: cppSetYnegProj (myCppViewer); break;
-      case Zneg: cppSetZnegProj (myCppViewer); break;
-    }
-  }
-
-  //! Post message to the text view.
-  public void postMessage (String theText)
-  {
-    OcctJniLogger.postMessage (theText);
-  }
-
-  //! Create instance of C++ class
-  private native long cppCreate();
-
-  //! Destroy instance of C++ class
-  private native void cppDestroy (long theCppPtr);
-
-  //! Initialize OCCT viewer (steal OpenGL ES context bound to this thread)
-  private native void cppInit    (long theCppPtr);
-
-  //! Resize OCCT viewer
-  private native void cppResize  (long theCppPtr, int theWidth, int theHeight);
-
-  //! Open CAD file
-  private native void cppOpen    (long theCppPtr, String thePath);
-
-  //! Handle detection in the viewer
-  private native void cppMoveTo  (long theCppPtr, int theX, int theY);
-
-  //! Redraw OCCT viewer
-  private native void cppRedraw  (long theCppPtr);
-
-  //! Fit All
-  private native void cppFitAll  (long theCppPtr);
-
-  //! Move camera
-  private native void cppSetXposProj (long theCppPtr);
-
-  //! Move camera
-  private native void cppSetYposProj (long theCppPtr);
-
-  //! Move camera
-  private native void cppSetZposProj (long theCppPtr);
-
-  //! Move camera
-  private native void cppSetXnegProj (long theCppPtr);
-
-  //! Move camera
-  private native void cppSetYnegProj (long theCppPtr);
-
-  //! Move camera
-  private native void cppSetZnegProj (long theCppPtr);
-
-  //! Initialize rotation
-  private native void cppStartRotation (long theCppPtr, int theStartX, int theStartY);
-
-  //! Perform rotation
-  private native void cppOnRotation    (long theCppPtr, int theX,  int theY);
-
-  //! Perform panning
-  private native void cppOnPanning     (long theCppPtr, int theDX, int theDY);
-
-  //! Perform selection
-  private native void cppOnClick       (long theCppPtr, int theX,  int theY);
-
-  //! Stop action (rotation / panning / scaling)
-  private native void cppStopAction    (long theCppPtr);
-
-  private long myCppViewer = 0;   //!< pointer to c++ class instance
-
-}
diff --git a/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniView.java b/samples/java/jniviewer/src/com/opencascade/jnisample/OcctJniView.java
deleted file mode 100644 (file)
index 7909d9c..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright (c) 2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-package com.opencascade.jnisample;
-
-import android.app.ActionBar.LayoutParams;
-import android.content.Context;
-import android.graphics.PointF;
-import android.opengl.GLSurfaceView;
-import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.view.MotionEvent;
-import android.widget.RelativeLayout;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-
-//! OpenGL ES 2.0+ view.
-//! Performs rendering in parallel thread.
-class OcctJniView extends GLSurfaceView
-{
-
-  // ! Default constructor.
-  public OcctJniView (Context      theContext,
-                      AttributeSet theAttrs)
-  {
-    super (theContext, theAttrs);
-
-    setPreserveEGLContextOnPause (true);
-    setEGLContextFactory (new ContextFactory());
-    setEGLConfigChooser  (new ConfigChooser());
-
-    RelativeLayout.LayoutParams aLParams = new RelativeLayout.LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-    aLParams.addRule (RelativeLayout.ALIGN_TOP);
-
-    myRenderer = new OcctJniRenderer();
-    setRenderer (myRenderer);
-  }
-
-  //! Open file.
-  public void open (String thePath)
-  {
-    final String aPath = thePath;
-    queueEvent (new Runnable() { public void run() { myRenderer.open (aPath); }});
-  }
-
-  //! Create OpenGL ES 2.0+ context
-  private static class ContextFactory implements GLSurfaceView.EGLContextFactory
-  {
-    private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-    public EGLContext createContext (EGL10      theEgl,
-                                     EGLDisplay theEglDisplay,
-                                     EGLConfig  theEglConfig)
-    {
-      if (theEglConfig == null)
-      {
-        return null;
-      }
-
-      // reset EGL errors stack
-      int anError = EGL10.EGL_SUCCESS;
-      while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS) {}
-
-      int[]      anAttribs   = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
-      EGLContext aEglContext = theEgl.eglCreateContext (theEglDisplay, theEglConfig, EGL10.EGL_NO_CONTEXT, anAttribs);
-
-      while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS)
-      {
-        OcctJniLogger.postMessage ("Error: eglCreateContext() " + String.format ("0x%x", anError));
-      }
-      return aEglContext;
-    }
-
-    public void destroyContext (EGL10      theEgl,
-                                EGLDisplay theEglDisplay,
-                                EGLContext theEglContext)
-    {
-      theEgl.eglDestroyContext (theEglDisplay, theEglContext);
-    }
-  }
-
-  //! Search for RGB24 config with depth and stencil buffers
-  private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser
-  {
-    //! Reset EGL errors stack
-    private void popEglErrors (EGL10 theEgl)
-    {
-      int anError = EGL10.EGL_SUCCESS;
-      while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS)
-      {
-        OcctJniLogger.postMessage ("EGL Error: " + String.format ("0x%x", anError));
-      }
-    }
-
-    //! Auxiliary method to dump EGL configuration - for debugging purposes
-    @SuppressWarnings("unused")
-    private void printConfig (EGL10      theEgl,
-                              EGLDisplay theEglDisplay,
-                              EGLConfig  theEglConfig)
-    {
-      int[] THE_ATTRIBS =
-      {
-        EGL10.EGL_BUFFER_SIZE, EGL10.EGL_ALPHA_SIZE, EGL10.EGL_BLUE_SIZE, EGL10.EGL_GREEN_SIZE, EGL10.EGL_RED_SIZE, EGL10.EGL_DEPTH_SIZE, EGL10.EGL_STENCIL_SIZE,
-        EGL10.EGL_CONFIG_CAVEAT,
-        EGL10.EGL_CONFIG_ID,
-        EGL10.EGL_LEVEL,
-        EGL10.EGL_MAX_PBUFFER_HEIGHT, EGL10.EGL_MAX_PBUFFER_PIXELS, EGL10.EGL_MAX_PBUFFER_WIDTH,
-        EGL10.EGL_NATIVE_RENDERABLE,  EGL10.EGL_NATIVE_VISUAL_ID,   EGL10.EGL_NATIVE_VISUAL_TYPE,
-        0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
-        EGL10.EGL_SAMPLES, EGL10.EGL_SAMPLE_BUFFERS,
-        EGL10.EGL_SURFACE_TYPE,
-        EGL10.EGL_TRANSPARENT_TYPE, EGL10.EGL_TRANSPARENT_RED_VALUE, EGL10.EGL_TRANSPARENT_GREEN_VALUE, EGL10.EGL_TRANSPARENT_BLUE_VALUE,
-        0x3039, 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGB, EGL10.EGL_BIND_TO_TEXTURE_RGBA,
-        0x303B, 0x303C, // EGL10.EGL_MIN_SWAP_INTERVAL, EGL10.EGL_MAX_SWAP_INTERVAL
-        EGL10.EGL_LUMINANCE_SIZE, EGL10.EGL_ALPHA_MASK_SIZE,
-        EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RENDERABLE_TYPE,
-        0x3042 // EGL10.EGL_CONFORMANT
-      };
-      String[] THE_NAMES =
-      {
-        "EGL_BUFFER_SIZE", "EGL_ALPHA_SIZE", "EGL_BLUE_SIZE", "EGL_GREEN_SIZE", "EGL_RED_SIZE", "EGL_DEPTH_SIZE", "EGL_STENCIL_SIZE",
-        "EGL_CONFIG_CAVEAT",
-        "EGL_CONFIG_ID",
-        "EGL_LEVEL",
-        "EGL_MAX_PBUFFER_HEIGHT", "EGL_MAX_PBUFFER_PIXELS", "EGL_MAX_PBUFFER_WIDTH",
-        "EGL_NATIVE_RENDERABLE",  "EGL_NATIVE_VISUAL_ID",   "EGL_NATIVE_VISUAL_TYPE",
-        "EGL_PRESERVED_RESOURCES",
-        "EGL_SAMPLES", "EGL_SAMPLE_BUFFERS",
-        "EGL_SURFACE_TYPE",
-        "EGL_TRANSPARENT_TYPE", "EGL_TRANSPARENT_RED_VALUE", "EGL_TRANSPARENT_GREEN_VALUE", "EGL_TRANSPARENT_BLUE_VALUE",
-        "EGL_BIND_TO_TEXTURE_RGB", "EGL_BIND_TO_TEXTURE_RGBA",
-        "EGL_MIN_SWAP_INTERVAL", "EGL_MAX_SWAP_INTERVAL",
-        "EGL_LUMINANCE_SIZE", "EGL_ALPHA_MASK_SIZE",
-        "EGL_COLOR_BUFFER_TYPE", "EGL_RENDERABLE_TYPE",
-        "EGL_CONFORMANT"
-      };
-      int[] aValue = new int[1];
-      for (int anAttrIter = 0; anAttrIter < THE_ATTRIBS.length; ++anAttrIter)
-      {
-        int    anAttr = THE_ATTRIBS[anAttrIter];
-        String aName  = THE_NAMES  [anAttrIter];
-        if (theEgl.eglGetConfigAttrib (theEglDisplay, theEglConfig, anAttr, aValue))
-        {
-          OcctJniLogger.postMessage (String.format ("  %s: %d\n", aName, aValue[0]));
-        }
-        else
-        {
-          popEglErrors (theEgl);
-        }
-      }
-    }
-
-    //! Interface implementation
-    public EGLConfig chooseConfig (EGL10      theEgl,
-                                   EGLDisplay theEglDisplay)
-    {
-      int EGL_OPENGL_ES2_BIT = 4;
-      int[] aCfgAttribs =
-      {
-        EGL10.EGL_RED_SIZE,     8,
-        EGL10.EGL_GREEN_SIZE,   8,
-        EGL10.EGL_BLUE_SIZE,    8,
-        EGL10.EGL_ALPHA_SIZE,   0,
-        EGL10.EGL_DEPTH_SIZE,  24,
-        EGL10.EGL_STENCIL_SIZE, 8,
-        EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-        EGL10.EGL_NONE
-      };
-
-      EGLConfig aConfigs[] = new EGLConfig[1];
-      int[]     aNbConfigs = new int[1];
-      if (!theEgl.eglChooseConfig (theEglDisplay, aCfgAttribs, aConfigs, 1, aNbConfigs)
-       || aConfigs[0] == null)
-      {
-        aCfgAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
-        popEglErrors (theEgl);
-        if (!theEgl.eglChooseConfig (theEglDisplay, aCfgAttribs, aConfigs, 1, aNbConfigs)
-         || aConfigs[0] == null)
-        {
-          OcctJniLogger.postMessage ("Error: eglChooseConfig() has failed!");
-          return null;
-        }
-      }
-
-      //printConfig (theEgl, theEglDisplay, aConfigs[0]);
-      return aConfigs[0];
-    }
-  }
-
-  //! Callback to handle touch events
-  @Override public boolean onTouchEvent (MotionEvent theEvent)
-  {
-    int aPointerIndex = theEvent.getActionIndex();
-    int aPointerId    = theEvent.getPointerId (aPointerIndex);
-    int aMaskedAction = theEvent.getActionMasked();
-    switch (aMaskedAction)
-    {
-      case MotionEvent.ACTION_DOWN:
-      case MotionEvent.ACTION_POINTER_DOWN:
-      {
-        PointF aPntLast = null;
-        if (myActivePointers.size() >= 1)
-        {
-          aPntLast = myActivePointers.get (myActivePointers.keyAt (0));
-        }
-
-        final PointF aPnt = new PointF();
-        aPnt.x = theEvent.getX (aPointerIndex);
-        aPnt.y = theEvent.getY (aPointerIndex);
-        myActivePointers.put (aPointerId, aPnt);
-
-        switch (myActivePointers.size())
-        {
-          case 1:
-          {
-            final int aStartX = (int )aPnt.x;
-            final int aStartY = (int )aPnt.y;
-            queueEvent (new Runnable() { public void run() { myRenderer.onStartRotation (aStartX, aStartY); }});
-            break;
-          }
-          case 2:
-          {
-            myPanFrom.x = (aPntLast.x + aPnt.x) * 0.5f;
-            myPanFrom.y = (aPntLast.y + aPnt.y) * 0.5f;
-            break;
-          }
-        }
-
-        break;
-      }
-      case MotionEvent.ACTION_MOVE:
-      {
-        for (int aNbPointers = theEvent.getPointerCount(), aPntIter = 0; aPntIter < aNbPointers; ++aPntIter)
-        {
-          PointF aPnt = myActivePointers.get (theEvent.getPointerId (aPntIter));
-          if (aPnt != null)
-          {
-            aPnt.x = theEvent.getX (aPntIter);
-            aPnt.y = theEvent.getY (aPntIter);
-          }
-        }
-
-        switch (myActivePointers.size())
-        {
-          case 1:
-          {
-            PointF aPnt = myActivePointers.get (theEvent.getPointerId (0));
-            final int anX = (int )aPnt.x;
-            final int anY = (int )aPnt.y;
-            queueEvent (new Runnable() { public void run() { myRenderer.onRotation (anX, anY); }});
-            break;
-          }
-          case 2:
-          {
-            PointF aPnt1 = myActivePointers.get (myActivePointers.keyAt (0));
-            PointF aPnt2 = myActivePointers.get (myActivePointers.keyAt (1));
-            PointF aPntAver = new PointF ((aPnt1.x + aPnt2.x) * 0.5f,
-                                          (aPnt1.y + aPnt2.y) * 0.5f);
-            final int aDX = (int )(aPntAver.x - myPanFrom.x);
-            final int aDY = (int )(myPanFrom.y -aPntAver.y);
-            myPanFrom.x = aPntAver.x;
-            myPanFrom.y = aPntAver.y;
-            queueEvent (new Runnable() { public void run() { myRenderer.onPanning (aDX, aDY); }});
-          }
-        }
-        break;
-      }
-      case MotionEvent.ACTION_UP:
-      case MotionEvent.ACTION_POINTER_UP:
-      case MotionEvent.ACTION_CANCEL:
-      {
-        myActivePointers.remove (aPointerId);
-        if (myActivePointers.size() == 0)
-        {
-          final int aPressX      = (int )theEvent.getX (aPointerIndex);
-          final int aPressY      = (int )theEvent.getY (aPointerIndex);
-          double    aPressTimeMs = theEvent.getEventTime() - theEvent.getDownTime();
-          if (aPressTimeMs < 100.0)
-          {
-            queueEvent (new Runnable() { public void run() { myRenderer.onClick (aPressX, aPressY); }});
-            break;
-          }
-        }
-        else if (myActivePointers.size() == 1)
-        {
-          PointF    aPnt    = myActivePointers.get (myActivePointers.keyAt (0));
-          final int aStartX = (int )aPnt.x;
-          final int aStartY = (int )aPnt.y;
-          queueEvent (new Runnable() { public void run() { myRenderer.onStartRotation (aStartX, aStartY); }});
-        }
-        //queueEvent (new Runnable() { public void run() { myRenderer.onStopAction(); }});
-        break;
-      }
-    }
-    ///invalidate();
-    return true;
-  }
-
-  //! Fit All
-  public void fitAll()
-  {
-    queueEvent (new Runnable() { public void run() { myRenderer.fitAll(); }});
-  }
-
-  //! Move camera
-  public void setProj (final OcctJniRenderer.TypeOfOrientation theProj)
-  {
-    queueEvent (new Runnable() { public void run() { myRenderer.setProj (theProj); }});
-  }
-
-  //! OCCT viewer
-  private OcctJniRenderer     myRenderer = null;
-
-  //! Touch events cache
-  private SparseArray<PointF> myActivePointers = new SparseArray<PointF>();
-
-  //! Starting point for panning event
-  private PointF              myPanFrom  = new PointF (0.0f, 0.0f);
-
-}