OSDN Git Service

initial
authorMRSa <mrsa@myad.jp>
Sat, 26 Aug 2017 13:00:45 +0000 (22:00 +0900)
committerMRSa <mrsa@myad.jp>
Sat, 26 Aug 2017 13:00:45 +0000 (22:00 +0900)
109 files changed:
.gitignore [new file with mode: 0644]
app/.gitignore [new file with mode: 0644]
app/build.gradle [new file with mode: 0644]
app/libs/LICENSE.txt [new file with mode: 0644]
app/libs/olycamerakit.jar [new file with mode: 0644]
app/proguard-rules.pro [new file with mode: 0644]
app/src/main/AndroidManifest.xml [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/A01dMain.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/ConfirmationDialog.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/IChangeScene.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/IInterfaceProvider.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/IOlympusInterfaceProvider.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyArrayAdapter.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyArrayItem.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyLoader.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyOperator.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyValueSelector.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/ICametaPropertyUpdateNotify.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/OlyCameraPropertyListFragment.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/operation/CameraPowerOff.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/CameraPropertyUtilities.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/ICameraHardwareStatus.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/ICameraRunMode.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/IOlyCameraProperty.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/IOlyCameraPropertyProvider.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/OlympusInterfaceProvider.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/CameraConnectSequence.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/CameraDisconnectSequence.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/ICameraStatusReceiver.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/IOlyCameraConnection.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/OlyCameraConnection.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/CameraLiveImageView.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/CameraLiveViewListenerImpl.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/IAutoFocusFrameDisplay.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/ICameraPanelDrawer.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/ICameraStatusDisplay.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/ILiveImageStatusNotify.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/IStatusViewDrawer.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/LiveViewClickListener.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/LiveViewFragment.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/ScalableImageViewPanel.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/ConvertNothing.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/IPreviewImageConverter.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/ImageConvertFactory.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/GridFrameDrawerDefault.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/GridFrameFactory.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/IGridFrameDrawer.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/message/IMessageDrawer.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/message/IMessageHolder.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/liveview/message/ShowMessageHolder.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/preference/IPreferencePropertyAccessor.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/preference/PreferenceFragment.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/preference/PreferenceSynchronizer.java [new file with mode: 0644]
app/src/main/res/color/setting_text_color.xml [new file with mode: 0644]
app/src/main/res/drawable/a01d_default.jpg [new file with mode: 0644]
app/src/main/res/drawable/a01d_ini.jpg [new file with mode: 0644]
app/src/main/res/drawable/ic_block_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_build_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_camera_roll_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_check_box_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_check_box_outline_blank_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_cloud_done_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_cloud_off_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_cloud_queue_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_grid_off_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_grid_on_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_indeterminate_check_box_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_linked_camera_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_mode_edit_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_photo_camera_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_refresh_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_restore_page_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_save_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_settings_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_web_asset_black_24dp.xml [new file with mode: 0644]
app/src/main/res/layout-land/activity_a01d_main.xml [new file with mode: 0644]
app/src/main/res/layout-land/fragmant_camera_property.xml [new file with mode: 0644]
app/src/main/res/layout-land/fragment_live_view.xml [new file with mode: 0644]
app/src/main/res/layout-land/listarrayitems.xml [new file with mode: 0644]
app/src/main/res/layout/activity_a01d_main.xml [new file with mode: 0644]
app/src/main/res/layout/fragmant_camera_property.xml [new file with mode: 0644]
app/src/main/res/layout/fragment_live_view.xml [new file with mode: 0644]
app/src/main/res/layout/listarrayitems.xml [new file with mode: 0644]
app/src/main/res/mipmap-hdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-hdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/mipmap-mdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-mdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/mipmap-xhdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/mipmap-xxhdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/values-ja/arrays.xml [new file with mode: 0644]
app/src/main/res/values-ja/colors.xml [new file with mode: 0644]
app/src/main/res/values-ja/strings.xml [new file with mode: 0644]
app/src/main/res/values-ja/styles.xml [new file with mode: 0644]
app/src/main/res/values/arrays.xml [new file with mode: 0644]
app/src/main/res/values/colors.xml [new file with mode: 0644]
app/src/main/res/values/strings.xml [new file with mode: 0644]
app/src/main/res/values/styles.xml [new file with mode: 0644]
app/src/main/res/xml/preferences.xml [new file with mode: 0644]
build.gradle [new file with mode: 0644]
gradle.properties [new file with mode: 0644]
gradle/wrapper/gradle-wrapper.jar [new file with mode: 0644]
gradle/wrapper/gradle-wrapper.properties [new file with mode: 0644]
gradlew [new file with mode: 0644]
gradlew.bat [new file with mode: 0644]
settings.gradle [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..39fb081
--- /dev/null
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644 (file)
index 0000000..a774788
--- /dev/null
@@ -0,0 +1,2 @@
+/build
+
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644 (file)
index 0000000..4273b82
--- /dev/null
@@ -0,0 +1,30 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 26
+    buildToolsVersion "26.0.1"
+    defaultConfig {
+        applicationId "net.osdn.gokigen.a01d"
+        minSdkVersion 14
+        targetSdkVersion 26
+        versionCode 100
+        versionName "1.0.0"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile 'com.android.support:appcompat-v7:26.+'
+    compile 'com.android.support.constraint:constraint-layout:1.0.2'
+    compile 'com.android.support:preference-v14:26.+'
+    //provided 'com.google.android.things:androidthings:0.4.1-devpreview'
+    compile 'com.android.support:preference-v7:26.+'
+    compile 'com.android.support:exifinterface:26.+'
+    compile files('libs/olycamerakit.jar')
+}
diff --git a/app/libs/LICENSE.txt b/app/libs/LICENSE.txt
new file mode 100644 (file)
index 0000000..c062f29
Binary files /dev/null and b/app/libs/LICENSE.txt differ
diff --git a/app/libs/olycamerakit.jar b/app/libs/olycamerakit.jar
new file mode 100644 (file)
index 0000000..528d4ad
Binary files /dev/null and b/app/libs/olycamerakit.jar differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644 (file)
index 0000000..2b164b0
--- /dev/null
@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\APL\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..0a08243
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="net.osdn.gokigen.a01d">
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.CAMERA" />
+
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:name="android.hardware.camera.autofocus" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+        <activity android:name=".A01dMain">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <meta-data android:name="android.max_aspect" android:value="ratio_float"/>
+    </application>
+</manifest>
+
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/A01dMain.java b/app/src/main/java/net/osdn/gokigen/a01d/A01dMain.java
new file mode 100644 (file)
index 0000000..81be876
--- /dev/null
@@ -0,0 +1,149 @@
+package net.osdn.gokigen.a01d;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.OlympusInterfaceProvider;
+import net.osdn.gokigen.a01d.liveview.LiveViewFragment;
+import net.osdn.gokigen.a01d.preference.PreferenceFragment;
+
+/**
+ *
+ *
+ */
+public class A01dMain extends AppCompatActivity implements IChangeScene
+{
+    private IOlympusInterfaceProvider interfaceProvider = null;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState)
+    {
+        final int REQUEST_NEED_PERMISSIONS = 1010;
+
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_a01d_main);
+
+        ActionBar bar = getSupportActionBar();
+        if (bar != null)
+        {
+            // タイトルバーは表示しない
+            bar.hide();
+        }
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+        // 外部メモリアクセス権のオプトイン
+        if ((ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)||
+                (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)||
+                (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
+                (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED))
+        {
+            ActivityCompat.requestPermissions(this,
+                    new String[]{
+                            Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                            Manifest.permission.ACCESS_NETWORK_STATE,
+                            Manifest.permission.ACCESS_WIFI_STATE,
+                            Manifest.permission.INTERNET,
+                    },
+                    REQUEST_NEED_PERMISSIONS);
+        }
+        initializeClass();
+        initializeFragment();
+        onReadyClass();
+    }
+
+    /**
+     *   クラスの初期化
+     *
+     */
+    private void initializeClass()
+    {
+        try
+        {
+            interfaceProvider = new OlympusInterfaceProvider();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *   初期化終了時の処理
+     *
+     */
+    private void onReadyClass()
+    {
+
+
+    }
+
+    /**
+     *   フラグメントの初期化
+     *
+     */
+    private void initializeFragment()
+    {
+        LiveViewFragment fragment = new LiveViewFragment();
+        fragment.prepare(this);
+        fragment.setRetainInstance(true);
+        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+        transaction.replace(R.id.fragment1, fragment);
+        transaction.commitAllowingStateLoss();
+    }
+
+    /**
+     *   カメラのプロパティ一覧画面を開く
+     *   (カメラと接続中のときのみ)
+     *
+     */
+    @Override
+    public void changeSceneToCameraPropertyList()
+    {
+
+    }
+
+    /**
+     *   設定画面を開く
+     *
+     */
+    @Override
+    public void changeSceneToConfiguration()
+    {
+        PreferenceFragment fragment = new PreferenceFragment();
+        fragment.setInterface(this, interfaceProvider, this);
+        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+        transaction.replace(R.id.fragment1, fragment);
+        // backstackに追加
+        transaction.addToBackStack(null);
+        transaction.commit();
+
+    }
+
+    /**
+     *   カメラとの接続・切断のシーケンス
+     *
+     */
+    @Override
+    public void changeCameraConnection()
+    {
+
+    }
+
+    /**
+     *   アプリを抜ける
+     *
+     */
+    @Override
+    public void exitApplication()
+    {
+
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/ConfirmationDialog.java b/app/src/main/java/net/osdn/gokigen/a01d/ConfirmationDialog.java
new file mode 100644 (file)
index 0000000..8e5c53c
--- /dev/null
@@ -0,0 +1,67 @@
+package net.osdn.gokigen.a01d;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.support.v7.app.AlertDialog;
+
+public class ConfirmationDialog
+{
+    private final Context context;
+
+    public ConfirmationDialog(Context context)
+    {
+        this.context = context;
+    }
+
+    public void show(int titleResId, int messageResId, final Callback callback)
+    {
+        String title = "";
+        String message = "";
+
+        // タイトルとメッセージをのダイアログを表示する
+        if (context != null)
+        {
+            title = context.getString(titleResId);
+            message = context.getString(messageResId);
+        }
+        show(title, message, callback);
+    }
+
+    public void show(String title, String message, final Callback callback)
+    {
+        // 確認ダイアログの生成
+        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
+        alertDialog.setTitle(title);
+        alertDialog.setIcon(android.R.drawable.ic_dialog_alert);
+        alertDialog.setMessage(message);
+        alertDialog.setCancelable(true);
+
+        // ボタンを設定する(実行ボタン)
+        alertDialog.setPositiveButton(context.getString(R.string.dialog_positive_execute),
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which)
+                    {
+                        callback.confirm();
+                        dialog.dismiss();
+                    }
+                });
+
+        // ボタンを設定する (キャンセルボタン)
+        alertDialog.setNegativeButton(context.getString(R.string.dialog_negative_cancel),
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which)
+                    {
+                        dialog.cancel();
+                    }
+                });
+
+        // 確認ダイアログを表示する
+        alertDialog.show();
+    }
+
+    // コールバックインタフェース
+    public interface Callback
+    {
+        void confirm();
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/IChangeScene.java b/app/src/main/java/net/osdn/gokigen/a01d/IChangeScene.java
new file mode 100644 (file)
index 0000000..49298ca
--- /dev/null
@@ -0,0 +1,12 @@
+package net.osdn.gokigen.a01d;
+
+/**
+ *
+ */
+public interface IChangeScene
+{
+    void changeSceneToCameraPropertyList();
+    void changeSceneToConfiguration();
+    void changeCameraConnection();
+    void exitApplication();
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/IInterfaceProvider.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/IInterfaceProvider.java
new file mode 100644 (file)
index 0000000..2a6b29b
--- /dev/null
@@ -0,0 +1,11 @@
+package net.osdn.gokigen.a01d.camera;
+
+import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
+
+/**
+ *
+ */
+public interface IInterfaceProvider
+{
+    IOlympusInterfaceProvider getOlympusInterface();
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/IOlympusInterfaceProvider.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/IOlympusInterfaceProvider.java
new file mode 100644 (file)
index 0000000..1520d37
--- /dev/null
@@ -0,0 +1,16 @@
+package net.osdn.gokigen.a01d.camera.olympus;
+
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.ICameraHardwareStatus;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.ICameraRunMode;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+
+/**
+ *
+ */
+public interface IOlympusInterfaceProvider
+{
+    ICameraHardwareStatus getHardwareStatus();
+    IOlyCameraPropertyProvider getCameraPropertyProvider();
+    ICameraRunMode getCameraRunMode();
+
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyArrayAdapter.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyArrayAdapter.java
new file mode 100644 (file)
index 0000000..45c3eef
--- /dev/null
@@ -0,0 +1,61 @@
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+public class CameraPropertyArrayAdapter extends ArrayAdapter<CameraPropertyArrayItem>
+{
+    private LayoutInflater inflater = null;
+    private final int textViewResourceId;
+    private List<CameraPropertyArrayItem> listItems = null;
+
+    public CameraPropertyArrayAdapter(Context context, int textId, List<CameraPropertyArrayItem> items)
+    {
+        super(context, textId, items);
+
+        textViewResourceId = textId;
+        listItems = items;
+
+        inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+    }
+
+    /**
+     *
+     */
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent)
+    {
+        View view;
+        if(convertView != null)
+        {
+            view = convertView;
+        }
+        else
+        {
+            view = inflater.inflate(textViewResourceId, null);
+        }
+
+        CameraPropertyArrayItem item = listItems.get(position);
+
+        ImageView imageView = view.findViewWithTag("icon");
+        imageView.setImageResource(item.getIconResource());
+
+        TextView titleView = view.findViewWithTag("name");
+        titleView.setText(item.getPropertyName());
+
+        TextView detailView = view.findViewWithTag("title");
+        detailView.setText(item.getPropertyTitle());
+
+        TextView optionView = view.findViewWithTag("value");
+        optionView.setText(item.getPropertyValueTitle());
+
+        return (view);
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyArrayItem.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyArrayItem.java
new file mode 100644 (file)
index 0000000..bbcb0a0
--- /dev/null
@@ -0,0 +1,79 @@
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+public class CameraPropertyArrayItem
+{
+    private int iconResource = 0;
+    private final String propertyName;
+    private final String propertyTitle;
+    private final String initialValue;
+    private final String initialValueTitle;
+    private final int    initialIconResource;
+    private String propertyValue = "";
+    private String propertyValueTitle = "";
+
+    public CameraPropertyArrayItem(String name, String title, String valueTitle, String value, int iconId1)
+    {
+        iconResource = iconId1;
+        propertyName = name;
+        propertyTitle = title;
+        propertyValueTitle = valueTitle;
+        propertyValue = value;
+        initialValueTitle = valueTitle;
+        initialValue = value;
+        initialIconResource = iconId1;
+    }
+
+    public boolean isChanged()
+    {
+        return (!propertyValue.equals(initialValue));
+    }
+
+    public String getPropertyName()
+    {
+        return (propertyName);
+    }
+
+    public String getPropertyTitle()
+    {
+        return (propertyTitle);
+    }
+
+    public String getInitialValue()
+    {
+        return (initialValue);
+    }
+
+    public int getIconResource()
+    {
+        return (iconResource);
+    }
+
+    public void setIconResource(int iconId)
+    {
+        iconResource = iconId;
+    }
+
+    public String getPropertyValueTitle()
+    {
+        return (propertyValueTitle);
+    }
+
+    public String getPropertyValue()
+    {
+        return (propertyValue);
+    }
+
+    public void setPropertyValue(String valueTitle, String value)
+    {
+        propertyValueTitle = valueTitle;
+        propertyValue = value;
+    }
+
+    public void resetValue()
+    {
+        propertyValue = initialValue;
+        propertyValueTitle = initialValueTitle;
+        iconResource = initialIconResource;
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyLoader.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyLoader.java
new file mode 100644 (file)
index 0000000..d0e5240
--- /dev/null
@@ -0,0 +1,88 @@
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Set;
+
+public class CameraPropertyLoader implements Runnable
+{
+    private final String TAG = toString();
+    private final IOlyCameraPropertyProvider propertyInterface;
+    private final IPropertyLoaderCallback callback;
+    private ArrayList<CameraPropertyArrayItem> propertyItems = null;
+
+    public CameraPropertyLoader(IOlyCameraPropertyProvider propertyInterface, IPropertyLoaderCallback callback)
+    {
+        this.propertyInterface = propertyInterface;
+        this.callback = callback;
+    }
+
+    @Override
+    public void run()
+    {
+        Log.v(TAG, "CameraPropertyLoader::run() START");
+
+        propertyItems = new ArrayList<>();
+
+        // カメラプロパティを設定する
+        Set<String> names = propertyInterface.getCameraPropertyNames();
+        for (String name : names)
+        {
+            String title = propertyInterface.getCameraPropertyTitle(name);
+            String value = propertyInterface.getCameraPropertyValue(name);
+            String rawValue = propertyInterface.getCameraPropertyValueTitle(value);
+            int iconId = (propertyInterface.canSetCameraProperty(name)) ? R.drawable.ic_web_asset_black_24dp : R.drawable.ic_block_black_24dp;
+
+            propertyItems.add(new CameraPropertyArrayItem(name, title, rawValue, value, iconId));
+        }
+
+        // プロパティ名でソートしてしまおう。。。
+        Collections.sort(propertyItems, new Comparator<CameraPropertyArrayItem>() {
+            public int compare(CameraPropertyArrayItem o1, CameraPropertyArrayItem o2) {
+                return o1.getPropertyName().compareTo(o2.getPropertyName());
+            }
+        });
+
+
+
+        // 終了通知
+        callback.finished();
+
+        Log.v(TAG, "CameraPropertyLoader::run() END");
+    }
+
+    public void resetProperty()
+    {
+        Log.v(TAG, "CameraPropertyLoader::resetProperty() START");
+
+        for (CameraPropertyArrayItem item : propertyItems)
+        {
+            item.resetValue();
+        }
+        callback.resetProperty();
+        Log.v(TAG, "CameraPropertyLoader::resetProperty() END");
+
+    }
+
+    /**
+     *   プロパティ一覧を応答
+     *
+     */
+    public ArrayList<CameraPropertyArrayItem> getItemList()
+    {
+        return (propertyItems);
+    }
+
+    public interface IPropertyLoaderCallback
+    {
+        void finished();
+        void resetProperty();
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyOperator.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyOperator.java
new file mode 100644 (file)
index 0000000..5e8c3e6
--- /dev/null
@@ -0,0 +1,61 @@
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+
+import net.osdn.gokigen.a01d.ConfirmationDialog;
+import net.osdn.gokigen.a01d.R;
+
+public class CameraPropertyOperator implements View.OnClickListener
+{
+    private final String TAG = toString();
+
+    private final Context context;
+    private final CameraPropertyLoader loader;
+
+
+    public CameraPropertyOperator(Context context, CameraPropertyLoader loader)
+    {
+        this.context = context;
+        this.loader = loader;
+    }
+
+    @Override
+    public void onClick(View view)
+    {
+        int id = view.getId();
+        Log.v(TAG, "onClick() : " + id);
+        switch (id)
+        {
+            case R.id.propertySettings_restore:
+                processRestoreCameraProperty();
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    private void processRestoreCameraProperty()
+    {
+        try
+        {
+            final ConfirmationDialog dialog = new ConfirmationDialog(context);
+            dialog.show(R.string.dialog_title_confirmation,
+                    R.string.dialog_message_restore_camera_property,
+                    new ConfirmationDialog.Callback() {
+                        @Override
+                        public void confirm()
+                        {
+                            loader.resetProperty();
+                        }
+                    });
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyValueSelector.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/CameraPropertyValueSelector.java
new file mode 100644 (file)
index 0000000..468afc3
--- /dev/null
@@ -0,0 +1,141 @@
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.support.v7.app.AlertDialog;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+
+import java.util.List;
+
+public class CameraPropertyValueSelector implements ListView.OnItemClickListener, ListView.OnLongClickListener, DialogInterface.OnClickListener
+{
+    private final String TAG = toString();
+    private final Context context;
+    private final IOlyCameraPropertyProvider propertyInterface;
+    private final ICametaPropertyUpdateNotify updater;
+
+    private List<String> valueList = null;
+    private CameraPropertyArrayItem item = null;
+
+    /**
+     *  選択されたアイテムの更新を行う
+     *
+     *
+     */
+    public CameraPropertyValueSelector(Context context, IOlyCameraPropertyProvider propertyInterface, ICametaPropertyUpdateNotify updater)
+    {
+        this.context = context;
+        this.propertyInterface = propertyInterface;
+        this.updater = updater;
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
+    {
+        Log.v(TAG, "onItemClick() : " + i);
+        CameraPropertyArrayAdapter arrayAdapter = (CameraPropertyArrayAdapter) adapterView.getAdapter();
+        item = arrayAdapter.getItem(i);
+        //item = (CameraPropertyArrayItem) listView.getSelectedItem();
+        if ((item == null)||(propertyInterface == null))
+        {
+            Log.i(TAG, "----- selectedItem is NULL. -----");
+            return;
+        }
+
+        String propertyName = item.getPropertyName();
+        String propertyValue = propertyInterface.getCameraPropertyValue(propertyName);
+        Log.v(TAG, "TARGET PROPERTY : " + propertyName + " " + propertyValue);
+
+        valueList = propertyInterface.getCameraPropertyValueList(propertyName);
+        if ((valueList == null)||(valueList.size() == 0))
+        {
+            Log.v(TAG, "Value List is NULL : " + item.getPropertyName() + " " + propertyValue);
+            return;
+        }
+        String[] items;
+        if (item.getIconResource() == R.drawable.ic_block_black_24dp)
+        {
+            // Read only, 値の変更はできない
+            items = new String[1];
+            items[0] =  propertyInterface.getCameraPropertyValueTitle(propertyValue);
+        }
+        else
+        {
+            // 設定可能な選択肢を一覧表示する
+            items = new String[valueList.size()];
+            for (int index = 0; index < valueList.size(); index++)
+            {
+                String propValue = valueList.get(index);
+                if (propValue.equals(item.getInitialValue()))
+                {
+                    Log.v(TAG, "INIT: " + propValue);
+
+                    // 初期値には、(*) マークを表示したい
+                    items[index] = propertyInterface.getCameraPropertyValueTitle(propValue) + " (*)";
+                }
+                else
+                {
+                    items[index] = propertyInterface.getCameraPropertyValueTitle(propValue);
+                }
+            }
+        }
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setSingleChoiceItems(items, valueList.indexOf(item.getPropertyValue()), this);
+        builder.setCancelable(true);
+        builder.show();
+    }
+
+    @Override
+    public boolean onLongClick(View view)
+    {
+        return (false);
+    }
+
+    @Override
+    public void onClick(DialogInterface dialogInterface, int which)
+    {
+        dialogInterface.dismiss();
+        if (propertyInterface == null)
+        {
+            Log.i(TAG, "----- PROPERTY CHANGE INTERFACE IS NULL -----");
+            return;
+        }
+
+        String propertyValue = valueList.get(which);
+        String rawValue = propertyInterface.getCameraPropertyValueTitle(propertyValue);
+
+        // パラメータ設定 (アイテムを個別に設定する場合は有効に...)
+        //propertyInterface.setCameraPropertyValue(propertyName, propertyValue);
+
+        if (item.getIconResource() == R.drawable.ic_block_black_24dp)
+        {
+            // Read Only パラメータは設定しない。
+            return;
+        }
+
+        item.setPropertyValue(rawValue, propertyValue);
+        String initialValue = item.getInitialValue();
+        if (!initialValue.equals(propertyValue))
+        {
+            // 値を変更したマークにする
+            item.setIconResource(R.drawable.ic_mode_edit_black_24dp);
+        }
+        else
+        {
+            // デフォルト値なので、アイコンを初期アイコンに戻す
+            item.setIconResource(R.drawable.ic_web_asset_black_24dp);
+        }
+        if (updater != null)
+        {
+            updater.onCameraPropertyUpdate(which);
+        }
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/ICametaPropertyUpdateNotify.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/ICametaPropertyUpdateNotify.java
new file mode 100644 (file)
index 0000000..dcc056a
--- /dev/null
@@ -0,0 +1,7 @@
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+public interface ICametaPropertyUpdateNotify
+{
+    void onCameraPropertyUpdate(int which);
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/OlyCameraPropertyListFragment.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/cameraproperty/OlyCameraPropertyListFragment.java
new file mode 100644 (file)
index 0000000..889f858
--- /dev/null
@@ -0,0 +1,263 @@
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+import java.util.HashMap;
+
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+
+public class OlyCameraPropertyListFragment extends Fragment implements CameraPropertyLoader.IPropertyLoaderCallback
+{
+    private final String TAG = toString();
+    private IOlyCameraPropertyProvider propertyInterface = null;
+
+    private CameraPropertyLoader propertyLoader = null;
+    private CameraPropertyOperator propertyOperator = null;
+    private ProgressDialog busyDialog = null;
+    private ListView listView = null;
+
+    /**
+     *  カメラプロパティをやり取りするインタフェースを生成する
+     *
+     */
+    public void setInterface(Context context, IOlyCameraPropertyProvider propertyInterface)
+    {
+        Log.v(TAG, "setInterface()");
+        this.propertyInterface = propertyInterface;
+        if (propertyLoader == null)
+        {
+            propertyLoader = new CameraPropertyLoader(propertyInterface, this);
+        }
+        if (propertyOperator == null)
+        {
+            propertyOperator = new CameraPropertyOperator(context, propertyLoader);
+        }
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+        super.onCreate(savedInstanceState);
+        Log.v(TAG, "onCreate()");
+
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void onAttach(Context context)
+    {
+        super.onAttach(context);
+        Log.v(TAG, "onAttach()");
+    }
+    /**
+     *
+     *
+     */
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+    {
+        Log.v(TAG, "onCreateView()");
+
+        View view = inflater.inflate(R.layout.fragmant_camera_property, container, false);
+        setHasOptionsMenu(true);
+
+        listView = view.findViewById(R.id.CameraPropertyListView);
+
+        ImageView restore_properties = view.findViewById(R.id.propertySettings_restore);
+        restore_properties.setOnClickListener(propertyOperator);
+
+        return (view);
+    }
+
+    /**
+     *
+     */
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
+    {
+        AppCompatActivity activity = (AppCompatActivity)getActivity();
+        ActionBar bar = activity.getSupportActionBar();
+        if (bar != null)
+        {
+            bar.setTitle(getString(R.string.app_name));
+        }
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    @Override
+    public void onStart()
+    {
+        super.onStart();
+        Log.v(TAG, "onStart()");
+
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void onResume()
+    {
+        super.onResume();
+        Log.v(TAG, "onResume() Start");
+
+        loadCameraPropertyItems(true);
+
+        Log.v(TAG, "onResume() End");
+    }
+    /**
+     *
+     *
+     */
+    @Override
+    public void onPause()
+    {
+        super.onPause();
+        Log.v(TAG, "onPause() Start");
+
+        try
+        {
+            commitCameraPropertyItems();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+
+        Log.v(TAG, "onPause() End");
+    }
+
+    private void runOnUiThread(Runnable action)
+    {
+        Activity activity = getActivity();
+        if (activity == null)
+        {
+            return;
+        }
+        activity.runOnUiThread(action);
+    }
+
+    private void loadCameraPropertyItems(boolean isPropertyLoad)
+    {
+        // 実行中ダイアログを取得する
+        busyDialog = new ProgressDialog(getActivity());
+        busyDialog.setTitle(getString(R.string.dialog_title_loading_properties));
+        busyDialog.setMessage(getString(R.string.dialog_message_loading_properties));
+        busyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+        busyDialog.setCancelable(false);
+        busyDialog.show();
+
+        // データ読み込み処理(別スレッドで実行)
+        if (isPropertyLoad)
+        {
+            new Thread(propertyLoader).start();
+        }
+    }
+
+    private void commitCameraPropertyItems()
+    {
+        ListAdapter adapter = listView.getAdapter();
+        int count = adapter.getCount();
+        Log.v(TAG, "----- CHANGED CAMERA PROPERTIES { -----");
+        final HashMap<String, String> propertiesToChange = new HashMap<>();
+        for (int index = 0; index < count; index++)
+        {
+            CameraPropertyArrayItem item = (CameraPropertyArrayItem) adapter.getItem(index);
+            if (item.isChanged())
+            {
+                Log.v(TAG, ">> " + item.getPropertyName() + " " + item.getPropertyValue());
+                propertiesToChange.put(item.getPropertyName(), item.getPropertyValue());
+            }
+        }
+        Log.v(TAG, "----- } CHANGED CAMERA PROPERTIES -----");
+        if (!propertiesToChange.isEmpty())
+        {
+            if (propertyInterface != null)
+            {
+                propertyInterface.setCameraPropertyValues(propertiesToChange);
+            }
+            else
+            {
+                Log.i(TAG, "----- PROPERTY CHANGE INTERFACE IS NULL -----");
+            }
+        }
+    }
+
+    @Override
+    public void finished()
+    {
+        runOnUiThread(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                // アイテムをListに反映
+                if (listView != null)
+                {
+                    final CameraPropertyArrayAdapter adapter = new CameraPropertyArrayAdapter(getContext(), R.layout.listarrayitems, propertyLoader.getItemList());
+                    CameraPropertyValueSelector selector = new CameraPropertyValueSelector(getContext(), propertyInterface, new ICametaPropertyUpdateNotify() {
+                        @Override
+                        public void onCameraPropertyUpdate(int which)
+                        {
+                            Log.v(TAG, "onCameraPropertyUpdate()");
+                            adapter.notifyDataSetChanged();
+                        }
+                    });
+                    listView.setAdapter(adapter);
+                    listView.setOnItemClickListener(selector);
+                    listView.setOnLongClickListener(selector);
+                }
+
+                if (busyDialog != null)
+                {
+                    busyDialog.dismiss();
+                    busyDialog = null;
+                }
+                System.gc();
+            }
+        });
+    }
+
+    @Override
+    public void resetProperty()
+    {
+        try
+        {
+            Log.v(TAG, "resetProperty()");
+            CameraPropertyArrayAdapter adapter = (CameraPropertyArrayAdapter)listView.getAdapter();
+            adapter.notifyDataSetChanged();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/operation/CameraPowerOff.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/operation/CameraPowerOff.java
new file mode 100644 (file)
index 0000000..b9ff9a7
--- /dev/null
@@ -0,0 +1,80 @@
+package net.osdn.gokigen.a01d.camera.olympus.operation;
+
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import net.osdn.gokigen.a01d.ConfirmationDialog;
+import net.osdn.gokigen.a01d.IChangeScene;
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor;
+
+/**
+ *  Preferenceがクリックされた時に処理するクラス
+ *
+ */
+public class CameraPowerOff implements Preference.OnPreferenceClickListener, ConfirmationDialog.Callback
+{
+    private final Context context;
+    private final IChangeScene changeScene;
+    private String preferenceKey = null;
+
+    /**
+     *   コンストラクタ
+     *
+     */
+    public CameraPowerOff(Context context, IChangeScene changeScene)
+    {
+        this.context = context;
+        this.changeScene = changeScene;
+    }
+
+    /**
+     *   クラスの準備
+     *
+     */
+    public void prepare()
+    {
+        // 何もしない
+    }
+
+    /**
+     *
+     *
+     * @param preference クリックしたpreference
+     * @return false : ハンドルしない / true : ハンドルした
+     */
+    @Override
+    public boolean onPreferenceClick(Preference preference)
+    {
+        if (!preference.hasKey())
+        {
+            return (false);
+        }
+
+        preferenceKey = preference.getKey();
+        if (preferenceKey.contains(IPreferencePropertyAccessor.EXIT_APPLICATION))
+        {
+
+            // 確認ダイアログの生成と表示
+            ConfirmationDialog dialog = new ConfirmationDialog(context);
+            dialog.show(R.string.dialog_title_confirmation, R.string.dialog_message_power_off, this);
+            return (true);
+        }
+        return (false);
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void confirm()
+    {
+        if (preferenceKey.contains(IPreferencePropertyAccessor.EXIT_APPLICATION))
+        {
+            // カメラの電源をOFFにしたうえで、アプリケーションを終了する。
+            changeScene.exitApplication();
+        }
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/CameraPropertyUtilities.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/CameraPropertyUtilities.java
new file mode 100644 (file)
index 0000000..580d5f3
--- /dev/null
@@ -0,0 +1,52 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+/**
+ *   カメラプロパティに関する雑多な処理...
+ *
+ */
+public class CameraPropertyUtilities
+{
+    /**
+     *   toLiveViewSize() : スクリーンサイズの文字列から、OLYCamera.LiveViewSize型へ変換する
+     *
+     * @param quality スクリーンサイズ文字列
+     * @return OLYCamera.LiveViewSize型
+     */
+    public static OLYCamera.LiveViewSize toLiveViewSizeType(String quality)
+    {
+        if (quality == null)
+        {
+            return OLYCamera.LiveViewSize.QVGA;
+        }
+        if (quality.equalsIgnoreCase("QVGA"))
+        {
+            return OLYCamera.LiveViewSize.QVGA;
+        }
+        else if (quality.equalsIgnoreCase("VGA"))
+        {
+            return OLYCamera.LiveViewSize.VGA;
+        } else if (quality.equalsIgnoreCase("SVGA"))
+        {
+            return OLYCamera.LiveViewSize.SVGA;
+        } else if (quality.equalsIgnoreCase("XGA"))
+        {
+            return OLYCamera.LiveViewSize.XGA;
+        } else if (quality.equalsIgnoreCase("QUAD_VGA"))
+        {
+            return OLYCamera.LiveViewSize.QUAD_VGA;
+        }
+        return OLYCamera.LiveViewSize.QVGA;
+    }
+
+    public static String getPropertyValue(String value)
+    {
+        if (value == null)
+        {
+            return ("");
+        }
+        String[] keyValue = OLYCamera.decodeCameraPropertyValue(value);
+        return (keyValue[1]);
+    }
+ }
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/ICameraHardwareStatus.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/ICameraHardwareStatus.java
new file mode 100644 (file)
index 0000000..30c5a67
--- /dev/null
@@ -0,0 +1,19 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+import java.util.Map;
+
+/**
+ *
+ *
+ */
+public interface ICameraHardwareStatus
+{
+    String getLensMountStatus();
+    String getMediaMountStatus();
+
+    float getMinimumFocalLength();
+    float getMaximumFocalLength();
+    float getActualFocalLength();
+
+    Map<String, Object> inquireHardwareInformation();
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/ICameraRunMode.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/ICameraRunMode.java
new file mode 100644 (file)
index 0000000..8f98df8
--- /dev/null
@@ -0,0 +1,8 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+public interface ICameraRunMode
+{
+    /** カメラの動作モード変更 **/
+    void changeRunMode(boolean isRecording);
+    boolean isRecordingMode();
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/IOlyCameraProperty.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/IOlyCameraProperty.java
new file mode 100644 (file)
index 0000000..6ab4e0f
--- /dev/null
@@ -0,0 +1,16 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+/**
+ *   使用するカメラプロパティのキー一覧
+ *
+ *
+ */
+public interface IOlyCameraProperty
+{
+    String TAKE_MODE = "TAKEMODE";
+    String SOUND_VOLUME_LEVEL = "SOUND_VOLUME_LEVEL";
+    String RAW = "RAW";
+
+    //String TAKE_MODE_MOVIE = "<TAKEMODE/movie>";
+    //String DRIVE_MODE_SINGLE = "<TAKE_DRIVE/DRIVE_NORMAL>";
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/IOlyCameraPropertyProvider.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/IOlyCameraPropertyProvider.java
new file mode 100644 (file)
index 0000000..c3c1f22
--- /dev/null
@@ -0,0 +1,35 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public interface IOlyCameraPropertyProvider
+{
+    // 現在利用可能なカメラプロパティ名のリスト
+    Set<String> getCameraPropertyNames();
+
+    // カメラプロパティに設定されている値を取得 : 戻りは "<WB/WB_AUTO>" な感じ
+    String getCameraPropertyValue(String name);
+
+    // カメラプロパティに設定されている値を一括取得
+    Map<String, String> getCameraPropertyValues(Set<String> names);
+
+    // カメラプロパティの名称
+    String getCameraPropertyTitle(String name);
+
+    // 設定可能なカメラプロパティ値のリストを取得する
+    List<String> getCameraPropertyValueList(String name);
+
+    // カメラプロパティの表示値
+    String getCameraPropertyValueTitle(String propertyValue);
+
+    // カメラプロパティに値を設定
+    void setCameraPropertyValue        (String name, String value);
+
+    // カメラプロパティに値を一括設定
+    void setCameraPropertyValues(Map<String, String> values);
+
+    // カメラプロパティに値を設定できるかを検査
+    boolean canSetCameraProperty(String name);
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/OlympusInterfaceProvider.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/OlympusInterfaceProvider.java
new file mode 100644 (file)
index 0000000..10c5e0f
--- /dev/null
@@ -0,0 +1,34 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
+
+
+/**
+ *
+ *
+ */
+public class OlympusInterfaceProvider implements IOlympusInterfaceProvider
+{
+    public OlympusInterfaceProvider()
+    {
+
+    }
+
+    @Override
+    public ICameraHardwareStatus getHardwareStatus()
+    {
+        return null;
+    }
+
+    @Override
+    public IOlyCameraPropertyProvider getCameraPropertyProvider()
+    {
+        return null;
+    }
+
+    @Override
+    public ICameraRunMode getCameraRunMode()
+    {
+        return null;
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/CameraConnectSequence.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/CameraConnectSequence.java
new file mode 100644 (file)
index 0000000..643c5d6
--- /dev/null
@@ -0,0 +1,87 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+import android.content.Context;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.R;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+
+/**
+ *   Olympusカメラとの接続処理
+ *
+ */
+class CameraConnectSequence implements Runnable
+{
+    private final String TAG = this.toString();
+    private final Context context;
+    private final OLYCamera camera;
+    private final ICameraStatusReceiver cameraStatusReceiver;
+
+    /**
+     *   コンストラクタ
+     */
+    CameraConnectSequence(Context context, OLYCamera camera, ICameraStatusReceiver statusReceiver)
+    {
+        Log.v(TAG, "CameraConnectSequence");
+        this.context = context;
+        this.camera =camera;
+        this.cameraStatusReceiver = statusReceiver;
+    }
+
+    /**
+     *   カメラとの接続実処理
+     *
+     */
+    @Override
+    public void run()
+    {
+        String statusMessage = context.getString(R.string.connect_start);
+        try
+        {
+            statusMessage = context.getString(R.string.connect_check_wifi);
+            cameraStatusReceiver.onStatusNotify(statusMessage);
+            camera.connect(OLYCamera.ConnectionType.WiFi);
+
+            // ライブビューの自動スタート設定の場合、自動スタートをやめる
+            if (camera.isAutoStartLiveView())
+            {
+                camera.setAutoStartLiveView(false);
+            }
+
+            // 一度カメラの動作モードを確認する
+            OLYCamera.RunMode runMode = camera.getRunMode();
+            if (runMode == OLYCamera.RunMode.Unknown)
+            {
+                // UNKNOWNモードは動作しない、メッセージを作って応答する
+                statusMessage = context.getString(R.string.fatal_cannot_use_camera);
+                cameraStatusReceiver.onCameraOccursException(statusMessage, new IllegalStateException(context.getString(R.string.camera_reset_required)));
+                Log.w(TAG, "DETECT : OLYCamera.RunMode.Unknown");
+            }
+            if (runMode != OLYCamera.RunMode.Recording)
+            {
+                // Recordingモードでない場合は切り替える
+                statusMessage = context.getString(R.string.connect_change_run_mode);
+                cameraStatusReceiver.onStatusNotify(statusMessage);
+                camera.changeRunMode(OLYCamera.RunMode.Recording);
+            }
+       }
+        catch (OLYCameraKitException e)
+        {
+            cameraStatusReceiver.onCameraOccursException(statusMessage, e);
+            e.printStackTrace();
+            return;
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            return;
+        }
+        Log.v(TAG, "CameraConnectSequence:: connected.");
+
+        // カメラとの接続確立を通知する
+        cameraStatusReceiver.onStatusNotify(context.getString(R.string.connect_connected));
+        cameraStatusReceiver.onCameraConnected();
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/CameraDisconnectSequence.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/CameraDisconnectSequence.java
new file mode 100644 (file)
index 0000000..07bea74
--- /dev/null
@@ -0,0 +1,46 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+import android.util.Log;
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+
+/**
+ *   Olympusカメラとの切断処理
+ *
+ */
+class CameraDisconnectSequence implements Runnable
+{
+    private final String TAG = this.toString();
+
+    private final OLYCamera camera;
+    private final boolean powerOff;
+
+    /**
+     *   コンストラクタ
+     *
+     */
+    CameraDisconnectSequence(OLYCamera camera, boolean isOff)
+    {
+        this.camera = camera;
+        this.powerOff = isOff;
+    }
+
+    @Override
+    public void run()
+    {
+        // カメラをPowerOffして接続を切る
+        try
+        {
+            camera.disconnectWithPowerOff(powerOff);
+        }
+        catch (OLYCameraKitException e)
+        {
+            // エラー情報をログに出力する
+            Log.w(TAG, "To disconnect from the camera is failed. : " + e.getLocalizedMessage());
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/ICameraStatusReceiver.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/ICameraStatusReceiver.java
new file mode 100644 (file)
index 0000000..79feab8
--- /dev/null
@@ -0,0 +1,13 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+/**
+ *
+ *
+ */
+public interface ICameraStatusReceiver
+{
+    void onStatusNotify(String message);
+    void onCameraConnected();
+    void onCameraDisconnected();
+    void onCameraOccursException(String message, Exception e);
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/IOlyCameraConnection.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/IOlyCameraConnection.java
new file mode 100644 (file)
index 0000000..157499d
--- /dev/null
@@ -0,0 +1,20 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+import android.content.Context;
+
+/**
+ *   カメラの接続/切断
+ *
+ */
+public interface IOlyCameraConnection
+{
+    // WIFI 接続系
+    void startWatchWifiStatus(Context context);
+    void stopWatchWifiStatus(Context context);
+    boolean isWatchWifiStatus();
+
+    /** カメラ接続系 **/
+    void disconnect(final boolean powerOff);
+    void connect();
+
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/OlyCameraConnection.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/olympus/wrapper/connection/OlyCameraConnection.java
new file mode 100644 (file)
index 0000000..372c400
--- /dev/null
@@ -0,0 +1,266 @@
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+import android.support.v7.app.AlertDialog;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.R;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraConnectionListener;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+
+
+/**
+ *   カメラの接続・切断処理クラス
+ *
+ *
+ * Created by MRSa on 2017/02/28.
+ */
+class OlyCameraConnection implements IOlyCameraConnection, OLYCameraConnectionListener
+{
+    private final String TAG = toString();
+    private final Activity context;
+    private final OLYCamera camera;
+    private final Executor cameraExecutor = Executors.newFixedThreadPool(1);
+    private final BroadcastReceiver connectionReceiver;
+    private final ICameraStatusReceiver statusReceiver;
+
+    private boolean isWatchingWifiStatus = false;
+
+    private ConnectivityManager connectivityManager;
+    //private ConnectivityManager.NetworkCallback networkCallback = null;
+
+    // Handler for dealing with network connection timeouts.
+    private Handler networkConnectionTimeoutHandler;
+
+
+    // Message to notify the network request timout handler that too much time has passed.
+    private static final int MESSAGE_CONNECTIVITY_TIMEOUT = 1;
+
+    /**
+     *    コンストラクタ
+     *
+     */
+    OlyCameraConnection(final Activity context, OLYCamera camera, ICameraStatusReceiver statusReceiver)
+    {
+        Log.v(TAG, "OlyCameraConnection()");
+        this.context = context;
+        this.camera = camera;
+        connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+        networkConnectionTimeoutHandler = new Handler()
+        {
+            @Override
+            public void handleMessage(Message msg)
+            {
+                switch (msg.what)
+                {
+                    case MESSAGE_CONNECTIVITY_TIMEOUT:
+                        Log.d(TAG, "Network connection timeout");
+                        alertConnectingFailed(context.getString(R.string.network_connection_timeout));
+                        break;
+                }
+            }
+        };
+        this.statusReceiver = statusReceiver;
+        connectionReceiver = new BroadcastReceiver()
+        {
+            @Override
+            public void onReceive(Context context, Intent intent)
+            {
+                onReceiveBroadcastOfConnection(context, intent);
+            }
+        };
+
+    }
+
+    /**
+     *   Wifiが使える状態だったら、カメラと接続して動作するよ
+     *
+     */
+    private void onReceiveBroadcastOfConnection(Context context, Intent intent)
+    {
+        statusReceiver.onStatusNotify(context.getString(R.string.connect_check_wifi));
+        Log.v(TAG,context.getString(R.string.connect_check_wifi));
+
+        String action = intent.getAction();
+        if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION))
+        {
+            WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+            WifiInfo info = wifiManager.getConnectionInfo();
+            if (wifiManager.isWifiEnabled() && info != null && info.getNetworkId() != -1)
+            {
+                // カメラとの接続処理を行う
+                connectToCamera();
+            }
+        }
+    }
+
+    /**
+     * Wifi接続状態の監視
+     * (接続の実処理は onReceiveBroadcastOfConnection() で実施)
+     */
+    @Override
+    public void startWatchWifiStatus(Context context)
+    {
+        Log.v(TAG, "startWatchWifiStatus()");
+        statusReceiver.onStatusNotify("prepare");
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        context.registerReceiver(connectionReceiver, filter);
+        isWatchingWifiStatus = true;
+    }
+
+    /**
+     * Wifi接続状態の監視終了
+     */
+    @Override
+    public void stopWatchWifiStatus(Context context)
+    {
+        Log.v(TAG, "stopWatchWifiStatus()");
+        context.unregisterReceiver(connectionReceiver);
+        isWatchingWifiStatus = false;
+        disconnect(false);
+    }
+
+    /**
+     * Wifi接続状態の監視処理を行っているかどうか
+     *
+     * @return true : 監視中 / false : 停止中
+     */
+    @Override
+    public boolean isWatchWifiStatus() {
+        return (isWatchingWifiStatus);
+    }
+
+    /**
+     *   カメラとの接続を解除する
+     *
+     * @param powerOff 真ならカメラの電源オフを伴う
+     */
+    @Override
+    public void disconnect(final boolean powerOff)
+    {
+        Log.v(TAG, "disconnect()");
+        disconnectFromCamera(powerOff);
+        statusReceiver.onCameraDisconnected();
+    }
+
+    /**
+     * カメラとの再接続を指示する
+     */
+    @Override
+    public void connect() {
+        connectToCamera();
+    }
+
+    /**
+     * カメラの通信状態変化を監視するためのインターフェース
+     *
+     * @param camera 例外が発生した OLYCamera
+     * @param e      カメラクラスの例外
+     */
+    @Override
+    public void onDisconnectedByError(OLYCamera camera, OLYCameraKitException e)
+    {
+        // カメラが切れた時に通知する
+        statusReceiver.onCameraDisconnected();
+    }
+
+    /**
+     * カメラとの切断処理
+     */
+    private void disconnectFromCamera(final boolean powerOff)
+    {
+        Log.v(TAG, "disconnectFromCamera()");
+        try
+        {
+            cameraExecutor.execute(new CameraDisconnectSequence(camera, powerOff));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * カメラとの接続処理
+     */
+    private void connectToCamera()
+    {
+        Log.v(TAG, "connectToCamera()");
+        try
+        {
+            cameraExecutor.execute(new CameraConnectSequence(context, camera, statusReceiver));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+    /**
+     *   接続リトライのダイアログを出す
+     *
+     * @param message 表示用のメッセージ
+     */
+    private void alertConnectingFailed(String message)
+    {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(context)
+                .setTitle(context.getString(R.string.dialog_title_connect_failed))
+                .setMessage(message)
+                .setPositiveButton(context.getString(R.string.dialog_title_button_retry), new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which)
+                    {
+                        connect();
+                    }
+                })
+                .setNeutralButton(R.string.dialog_title_button_network_settings, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which)
+                    {
+                        try
+                        {
+                            // Wifi 設定画面を表示する
+                            context.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
+                        }
+                        catch (android.content.ActivityNotFoundException ex)
+                        {
+                            // Activity が存在しなかった...設定画面が起動できなかった
+                            Log.v(TAG, "android.content.ActivityNotFoundException...");
+
+                            // この場合は、再試行と等価な動きとする
+                            connect();
+                        }
+                        catch (Exception e)
+                        {
+                            e.printStackTrace();
+                        }
+                    }
+                });
+        context.runOnUiThread(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                builder.show();
+            }
+        });
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/CameraLiveImageView.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/CameraLiveImageView.java
new file mode 100644 (file)
index 0000000..b9525f3
--- /dev/null
@@ -0,0 +1,905 @@
+package net.osdn.gokigen.a01d.liveview;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.media.ExifInterface;
+import android.os.Looper;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.liveview.bitmapconvert.IPreviewImageConverter;
+import net.osdn.gokigen.a01d.liveview.bitmapconvert.ImageConvertFactory;
+import net.osdn.gokigen.a01d.liveview.gridframe.GridFrameFactory;
+import net.osdn.gokigen.a01d.liveview.gridframe.IGridFrameDrawer;
+import net.osdn.gokigen.a01d.liveview.message.IMessageDrawer;
+import net.osdn.gokigen.a01d.liveview.message.IMessageHolder;
+import net.osdn.gokigen.a01d.liveview.message.ShowMessageHolder;
+import net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor;
+
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+/**
+ *   CameraLiveImageView :
+ *    (OLYMPUS の ImageCaptureSample そのまま)
+ *
+ */
+public class CameraLiveImageView extends View implements CameraLiveViewListenerImpl.IImageDataReceiver, IAutoFocusFrameDisplay, ILiveImageStatusNotify
+{
+    private final String TAG = this.toString();
+
+    private static final String EXIF_ORIENTATION = "Orientation";
+
+    private boolean focusAssistFeature = false;
+    private boolean showGridFeature = false;
+    private ImageView.ScaleType imageScaleType;
+    private Bitmap imageBitmap;
+    private int imageRotationDegrees;
+    private boolean showingFocusFrame = false;
+    private IAutoFocusFrameDisplay.FocusFrameStatus focusFrameStatus;
+    private RectF focusFrameRect;
+    private Timer focusFrameHideTimer;
+
+    private IGridFrameDrawer gridFrameDrawer = null;
+    private IPreviewImageConverter bitmapConverter = null;
+    private IMessageHolder messageHolder;
+
+    public CameraLiveImageView(Context context)
+    {
+        super(context);
+        initComponent(context);
+    }
+
+    public CameraLiveImageView(Context context, AttributeSet attrs)
+    {
+        super(context, attrs);
+        initComponent(context);
+    }
+
+    public CameraLiveImageView(Context context, AttributeSet attrs, int defStyleAttr)
+    {
+        super(context, attrs, defStyleAttr);
+        initComponent(context);
+    }
+
+    private void initComponent(Context context)
+    {
+        messageHolder = new ShowMessageHolder();
+        imageScaleType = ImageView.ScaleType.FIT_CENTER;
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+
+        // Gridの表示/非表示
+        int framingGridStatus = 0;
+        gridFrameDrawer = GridFrameFactory.getGridFrameDrawer(framingGridStatus);
+        showGridFeature = preferences.getBoolean(IPreferencePropertyAccessor.SHOW_GRID_STATUS, false);
+
+        int converterType = 0;
+        bitmapConverter = ImageConvertFactory.getImageConverter(converterType);
+
+        // ダミーのビットマップデータ読み込み...画面表示のテスト用ロジック
+        try
+        {
+            imageBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.a01d_default);
+        }
+        catch (Throwable t)
+        {
+            t.printStackTrace();
+            imageBitmap = null;
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+    }
+
+    @Override
+    protected void onDetachedFromWindow()
+    {
+        super.onDetachedFromWindow();
+
+        imageBitmap = null;
+        if (focusFrameHideTimer != null)
+        {
+            focusFrameHideTimer.cancel();
+            focusFrameHideTimer = null;
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas)
+    {
+        super.onDraw(canvas);
+        drawCanvas(canvas);
+
+        // メッセージの表示 (Overwrite)
+        drawInformationMessages(canvas);
+
+        // レベルゲージの表示
+        if (messageHolder.isLevel())
+        {
+            drawLevelGauge(canvas);
+        }
+    }
+
+    @Override
+    public float getContentSizeWidth() {
+        return getIntrinsicContentSizeWidth();
+    }
+
+    @Override
+    public float getContentSizeHeight() {
+        return getIntrinsicContentSizeHeight();
+    }
+
+
+    private float getIntrinsicContentSizeWidth()
+    {
+        if (imageBitmap == null)
+        {
+            return (1.0f);
+        }
+        return (imageBitmap.getWidth());
+    }
+
+    private float getIntrinsicContentSizeHeight()
+    {
+        if (imageBitmap == null)
+        {
+            return (1.0f);
+        }
+        return (imageBitmap.getHeight());
+    }
+
+    /**
+     * Sets a image to view.
+     * (CameraLiveViewListenerImpl.IImageDataReceiver の実装)
+     *
+     * @param data     A image of live-view.
+     * @param metadata A metadata of the image.
+     */
+    public void setImageData(byte[] data, Map<String, Object> metadata) {
+        Bitmap bitmap;
+        int rotationDegrees;
+
+        if (data != null && metadata != null) {
+            // Create a bitmap.
+            try {
+                bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+            } catch (OutOfMemoryError e) {
+                e.printStackTrace();
+                return;
+            }
+
+            // Acquire a rotation degree of image.
+            int orientation = ExifInterface.ORIENTATION_UNDEFINED;
+            if (metadata.containsKey(EXIF_ORIENTATION)) {
+                orientation = Integer.parseInt((String) metadata.get(EXIF_ORIENTATION));
+            }
+            switch (orientation) {
+                case ExifInterface.ORIENTATION_NORMAL:
+                    rotationDegrees = 0;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_90:
+                    rotationDegrees = 90;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_180:
+                    rotationDegrees = 180;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_270:
+                    rotationDegrees = 270;
+                    break;
+                default:
+                    rotationDegrees = 0;
+                    break;
+            }
+            imageBitmap = bitmap;
+            imageRotationDegrees = rotationDegrees;
+        }
+
+        refreshCanvas();
+    }
+
+    /**
+     * Returns a point which is detected by a motion event.
+     *
+     * @param event A motion event.
+     * @return A point in the view finder. if a point is equal to null, the point is out of the view finder.
+     */
+    public PointF getPointWithEvent(MotionEvent event)
+    {
+        if (event == null || imageBitmap == null)
+        {
+            return null;
+        }
+
+        PointF pointOnView = new PointF(event.getX(), event.getY());
+        PointF pointOnImage = convertPointFromViewArea(pointOnView);
+        float imageWidth;
+        float imageHeight;
+        if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+            imageWidth = imageBitmap.getWidth();
+            imageHeight = imageBitmap.getHeight();
+        } else {
+            imageWidth = imageBitmap.getHeight();
+            imageHeight = imageBitmap.getWidth();
+        }
+        return (OLYCamera.convertPointOnLiveImageIntoViewfinder(pointOnImage, imageWidth, imageHeight, imageRotationDegrees));
+    }
+
+    /**
+     * Returns whether a image area contains a specified point.
+     *
+     * @param point The point to examine.
+     * @return true if the image is not null or empty and the point is located within the rectangle; otherwise, false.
+     */
+    public boolean isContainsPoint(PointF point)
+    {
+        return ((point != null) && (new RectF(0, 0, 1, 1)).contains(point.x, point.y));
+    }
+
+    /**
+     * Hides the forcus frame.
+     */
+    public void hideFocusFrame()
+    {
+        if (focusFrameHideTimer != null)
+        {
+            focusFrameHideTimer.cancel();
+            focusFrameHideTimer = null;
+        }
+        showingFocusFrame = false;
+
+        refreshCanvas();
+    }
+
+    /**
+     * Shows the focus frame.
+     *
+     * @param rect     A rectangle of the focus frame on view area.
+     * @param status   A status of the focus frame.
+     * @param duration A duration of the focus frame showing.
+     */
+    @Override
+    public void showFocusFrame(RectF rect, FocusFrameStatus status, double duration)
+    {
+        if (focusFrameHideTimer != null)
+        {
+            focusFrameHideTimer.cancel();
+            focusFrameHideTimer = null;
+        }
+
+        showingFocusFrame = true;
+        focusFrameStatus = status;
+        focusFrameRect = rect;
+
+        refreshCanvas();
+
+        if (duration > 0)
+        {
+            focusFrameHideTimer = new Timer();
+            focusFrameHideTimer.schedule(new TimerTask() {
+                @Override
+                public void run() {
+                    hideFocusFrame();
+                }
+            }, (long) (duration * 1000));
+        }
+    }
+
+    private void refreshCanvas()
+    {
+        if (Looper.getMainLooper().getThread() == Thread.currentThread())
+        {
+            invalidate();
+        }
+        else
+        {
+            postInvalidate();
+        }
+    }
+
+    /**
+     *   ビットマップの表示
+     *
+     * @param canvas キャンバス
+     */
+    private void drawCanvas(Canvas canvas)
+    {
+        // Clears the canvas.
+        canvas.drawARGB(255, 0, 0, 0);
+
+        // ビットマップの取得
+        Bitmap bitmapToShow;
+        if ((focusAssistFeature)&&(bitmapConverter != null))
+        {
+            // フォーカスアシスト実行時の処理...
+            bitmapToShow = bitmapConverter.getModifiedBitmap(imageBitmap);
+        }
+        else
+        {
+            bitmapToShow = imageBitmap;
+        }
+        if (bitmapToShow == null)
+        {
+            // 表示するビットマップがないときは、すぐに折り返す
+            return;
+        }
+
+        // Rotates the image.
+        int centerX = canvas.getWidth() / 2;
+        int centerY = canvas.getHeight() / 2;
+        canvas.rotate(imageRotationDegrees, centerX, centerY);
+
+        RectF viewRect = null;
+
+        //  Calculate the viewport of bitmap.
+        if (imageScaleType == ImageView.ScaleType.FIT_CENTER)
+        {
+            viewRect = decideViewRect(canvas, bitmapToShow, imageRotationDegrees);
+
+            // Draws the bitmap.
+            Rect imageRect = new Rect(0, 0, bitmapToShow.getWidth(), bitmapToShow.getHeight());
+            canvas.drawBitmap(bitmapToShow, imageRect, viewRect, null);
+        }
+        else
+        {
+            // Sorry, other scale types are not supported.
+            Log.v(TAG, "Sorry, other scale types are not supported. " + imageScaleType);
+        }
+
+        // Cancels rotation of the canvas.
+        canvas.rotate(-imageRotationDegrees, centerX, centerY);
+
+        // フォーカスフレームを表示する
+        if ((focusFrameRect != null) && (showingFocusFrame))
+        {
+            if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+                drawFocusFrame(canvas, bitmapToShow.getWidth(), bitmapToShow.getHeight());
+            } else {
+                drawFocusFrame(canvas, bitmapToShow.getHeight(), bitmapToShow.getWidth());
+            }
+        }
+
+        // グリッド(撮影補助線)の表示
+        if ((viewRect != null)&&(showGridFeature)&&(gridFrameDrawer != null))
+        {
+            drawGridFrame(canvas, viewRect);
+        }
+    }
+
+    private RectF decideViewRect(Canvas canvas, Bitmap bitmapToShow, int degrees)
+    {
+        final int srcWidth;
+        final int srcHeight;
+        if ((degrees == 0) || (degrees == 180))
+        {
+            srcWidth = bitmapToShow.getWidth();
+            srcHeight = bitmapToShow.getHeight();
+        }
+        else
+        {
+            // Replaces width and height.
+            srcWidth = bitmapToShow.getHeight();
+            srcHeight = bitmapToShow.getWidth();
+        }
+
+        int maxWidth = canvas.getWidth();
+        int maxHeight = canvas.getHeight();
+
+        int centerX = canvas.getWidth() / 2;
+        int centerY = canvas.getHeight() / 2;
+
+        float widthRatio = maxWidth / (float) srcWidth;
+        float heightRatio = maxHeight / (float) srcHeight;
+        float smallRatio = Math.min(widthRatio, heightRatio);
+
+        final int dstWidth;
+        final int dstHeight;
+        if (widthRatio < heightRatio)
+        {
+            // Fits to maxWidth with keeping aspect ratio.
+            dstWidth = maxWidth;
+            dstHeight = (int)(smallRatio * srcHeight);
+        }
+        else
+        {
+            // Fits to maxHeight with keeping aspect ratio.
+            dstHeight = maxHeight;
+            dstWidth = (int)(smallRatio * srcWidth);
+        }
+
+        final float halfWidth = dstWidth * 0.5f;
+        final float halfHeight = dstHeight * 0.5f;
+        if ((degrees == 0) || (degrees == 180))
+        {
+            return (new RectF(
+                    centerX - halfWidth,
+                    centerY - halfHeight,
+                    centerX - halfWidth + dstWidth,
+                    centerY - halfHeight + dstHeight));
+        }
+
+        // Replaces the width and height.
+        return (new RectF(
+                centerX - halfHeight,
+                centerY - halfWidth,
+                centerX - halfHeight + dstHeight,
+                centerY - halfWidth + dstWidth));
+    }
+
+    /**
+     *   AF枠の表示
+     *
+     * @param canvas        キャンバス
+     * @param imageWidth   幅
+     * @param imageHeight  高さ
+     */
+    private void drawFocusFrame(Canvas canvas, float imageWidth, float imageHeight)
+    {
+        //Log.v(TAG, "drawFocusFrame() :" + focusFrameStatus);
+
+        //  Calculate the rectangle of focus.
+        RectF focusRectOnImage = OLYCamera.convertRectOnViewfinderIntoLiveImage(focusFrameRect, imageWidth, imageHeight, imageRotationDegrees);
+        RectF focusRectOnView = convertRectFromImageArea(focusRectOnImage);
+
+        // Draw a rectangle to the canvas.
+        Paint focusFramePaint = new Paint();
+        focusFramePaint.setStyle(Paint.Style.STROKE);
+        switch (focusFrameStatus)
+        {
+            case Running:
+                focusFramePaint.setColor(Color.WHITE);
+                break;
+
+            case Focused:
+                focusFramePaint.setColor(Color.GREEN);
+                break;
+
+            case Failed:
+                focusFramePaint.setColor(Color.RED);
+                break;
+
+            case Errored:
+                focusFramePaint.setColor(Color.YELLOW);
+                break;
+        }
+        float focusFrameStrokeWidth = 2.0f;
+        DisplayMetrics dm = getResources().getDisplayMetrics();
+        float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, focusFrameStrokeWidth, dm);
+        focusFramePaint.setStrokeWidth(strokeWidth);
+        canvas.drawRect(focusRectOnView, focusFramePaint);
+    }
+
+    /**
+     *   グリッドの表示
+     *
+     * @param canvas    キャンバスエリア
+     * @param viewRect  表示領域
+     */
+    private void drawGridFrame(Canvas canvas, RectF viewRect)
+    {
+        RectF gridRect;
+        if ((imageRotationDegrees == 0) || (imageRotationDegrees == 180)) {
+            gridRect = new RectF(viewRect);
+        } else {
+            float height = viewRect.right - viewRect.left;
+            float width = viewRect.bottom - viewRect.top;
+            float left = (canvas.getWidth() / 2.0f) - (width / 2.0f);
+            float top = (canvas.getHeight() / 2.0f) - (height / 2.0f);
+            gridRect = new RectF(left, top, left + width, top + height);
+        }
+
+        Paint framePaint = new Paint();
+        framePaint.setStyle(Paint.Style.STROKE);
+        framePaint.setAntiAlias(true);
+        framePaint.setStrokeWidth(0.0f);
+        framePaint.setColor(gridFrameDrawer.getDrawColor());
+        gridFrameDrawer.drawFramingGrid(canvas, gridRect, framePaint);
+    }
+
+    /**
+     *   画面にメッセージを表示する
+     */
+    private void drawInformationMessages(Canvas canvas)
+    {
+        String message;
+        RectF viewRect;
+        if (imageBitmap != null)
+        {
+            // ビットマップの表示エリアに合わせて位置をチューニングする
+            viewRect = decideViewRect(canvas, imageBitmap, 0);
+        }
+        else
+        {
+            // 適当なサイズ...
+            viewRect = new RectF(5.0f, 0.0f, canvas.getWidth() - 5.0f, canvas.getHeight() - 55.0f);
+        }
+
+        // 画面の中心に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.CENTER);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paint = new Paint();
+            paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.CENTER));
+            paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.CENTER));
+            paint.setAntiAlias(true);
+            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+            float cx = (canvas.getWidth() / 2.0f) - (paint.measureText(message) / 2.0f);
+            float cy = (canvas.getHeight() / 2.0f) - ((fontMetrics.ascent + fontMetrics.descent) / 2.0f);
+            canvas.drawText(message, cx, cy, paint);
+        }
+
+        // 画面上部左側に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.UPLEFT);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paintUp = new Paint();
+            paintUp.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.UPLEFT));
+            paintUp.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.UPLEFT));
+            paintUp.setAntiAlias(true);
+            Paint.FontMetrics fontMetrics = paintUp.getFontMetrics();
+            canvas.drawText(message, viewRect.left + 3.0f, viewRect.top + (fontMetrics.descent - fontMetrics.ascent), paintUp);
+        }
+
+        // 画面上部右側に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.UPRIGHT);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paintUp = new Paint();
+            paintUp.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.UPRIGHT));
+            paintUp.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.UPRIGHT));
+            paintUp.setAntiAlias(true);
+            float width = paintUp.measureText(message);
+            Paint.FontMetrics fontMetrics = paintUp.getFontMetrics();
+            canvas.drawText(message, (viewRect.right - 3.0f) - width, viewRect.top + (fontMetrics.descent - fontMetrics.ascent), paintUp);
+        }
+
+        // 画面下部左側に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LOWLEFT);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paint = new Paint();
+            paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LOWLEFT));
+            paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LOWLEFT));
+            paint.setAntiAlias(true);
+            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+            canvas.drawText(message, viewRect.left + 3.0f, viewRect.bottom - fontMetrics.bottom, paint);
+        }
+
+        // 画面下部右側に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LOWRIGHT);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paint = new Paint();
+            paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LOWRIGHT));
+            paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LOWRIGHT));
+            paint.setAntiAlias(true);
+            float width = paint.measureText(message);
+            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+            canvas.drawText(message, (viewRect.right - 3.0f) - width, viewRect.bottom - fontMetrics.bottom, paint);
+        }
+
+        // 画面上部中央に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.UPCENTER);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paintUp = new Paint();
+            paintUp.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.UPCENTER));
+            paintUp.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.UPCENTER));
+            paintUp.setAntiAlias(true);
+            float width = paintUp.measureText(message) / 2.0f;
+            Paint.FontMetrics fontMetrics = paintUp.getFontMetrics();
+            canvas.drawText(message, (viewRect.centerX()) - width, viewRect.top + (fontMetrics.descent - fontMetrics.ascent), paintUp);
+        }
+
+        // 画面下部中央に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LOWCENTER);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paint = new Paint();
+            paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LOWCENTER));
+            paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LOWCENTER));
+            paint.setAntiAlias(true);
+            float width = paint.measureText(message) / 2.0f;
+            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+            canvas.drawText(message, (viewRect.centerX()) - width, viewRect.bottom - fontMetrics.bottom, paint);
+        }
+
+        // 画面中央左に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LEFTCENTER);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paint = new Paint();
+            paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LEFTCENTER));
+            paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LEFTCENTER));
+            paint.setAntiAlias(true);
+            paint.setShadowLayer(5.0f, 3.0f, 3.0f, Color.BLACK);  // これで文字に影をつけたい
+            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+            float cy = (canvas.getHeight() / 2.0f) - ((fontMetrics.ascent + fontMetrics.descent) / 2.0f);
+            canvas.drawText(message, viewRect.left + 3.0f, cy, paint);
+        }
+
+        // 画面中央右に表示する
+        message = messageHolder.getMessage(ShowMessageHolder.MessageArea.RIGHTCENTER);
+        if ((message != null)&&(message.length() > 0))
+        {
+            Paint paint = new Paint();
+            paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.RIGHTCENTER));
+            paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.RIGHTCENTER));
+            paint.setAntiAlias(true);
+            paint.setShadowLayer(5.0f, 3.0f, 3.0f, Color.BLACK);  // これで文字に影をつけたい
+            float width = paint.measureText(message);
+            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+            float cy = (canvas.getHeight() / 2.0f) - ((fontMetrics.ascent + fontMetrics.descent) / 2.0f);
+            canvas.drawText(message, (viewRect.right - 3.0f) - width, cy, paint);
+        }
+
+    }
+
+    /**
+     *   レベルゲージ(デジタル水準器)の表示
+     *
+     */
+    private void drawLevelGauge(Canvas canvas)
+    {
+        // レベルゲージの表示位置
+        int height = canvas.getHeight();
+        int width = canvas.getWidth();
+        int centerX = width / 2;
+        int centerY = height / 2;
+
+        float maxBandWidth = width / 3.0f;     // ゲージの最大長 (画面の 1/3 ぐらい)
+        float maxBandHeight = height / 3.0f;   // ゲージの最大長 (画面の 1/3 ぐらい)
+        int barWidthInitial = 5;               // 表示するゲージの幅(の初期値)
+        int barWidth;                          // 実際に表示するゲージの幅
+
+        Paint paint = new Paint();
+
+        // 垂直線
+        float verticalValue = messageHolder.getLevel(IMessageDrawer.LevelArea.LEVEL_VERTICAL);
+        float verticalSize = verticalValue / 60.0f * maxBandHeight;  // 45度で切り替わるはずだが、一応...
+        if (Math.abs(verticalSize) < 1.0f)
+        {
+            // 線引き限界以下、水平検出とする (この時の線は倍の長さにする)
+            verticalSize = 1.0f;
+            barWidth = barWidthInitial * 2;
+        }
+        else
+        {
+            barWidth = barWidthInitial;
+        }
+        paint.setStrokeWidth(barWidth);
+        paint.setColor(messageHolder.getLevelColor(verticalValue));
+        canvas.drawLine((width - barWidth), centerY, (width - barWidth), (centerY + verticalSize), paint);
+
+        // 水平線
+        float horizontalValue = messageHolder.getLevel(IMessageDrawer.LevelArea.LEVEL_HORIZONTAL);
+        float horizontalSize = horizontalValue / 60.0f * maxBandWidth;  // 45度ぐらいで切り替わるはずだが、一応...
+        if (Math.abs(horizontalSize) < 1.0f)
+        {
+            // 線引き限界以下、水平検出とする (この時の線は倍の長さにする)
+            horizontalSize = 1.0f;
+            barWidth = barWidthInitial * 2;
+        }
+        else
+        {
+            barWidth = barWidthInitial;
+        }
+        paint.setStrokeWidth(barWidth);
+        paint.setColor(messageHolder.getLevelColor(horizontalValue));
+        canvas.drawLine(centerX, (height - barWidth), (centerX + horizontalSize),  (height - barWidth), paint);
+
+        // 水平線 (スクリーン内の線)
+        float horizontalValue0 = messageHolder.getLevel(IMessageDrawer.LevelArea.LEVEL_HORIZONTAL);
+        paint.setStrokeWidth(2.0f);
+        paint.setAntiAlias(true);
+        paint.setColor(messageHolder.getLevelColor(horizontalValue0));
+        if ((imageRotationDegrees == 0) || (imageRotationDegrees == 180))
+        {
+            // 通常状態
+            float YY = canvas.getHeight() / 2.0f; // centerY
+            float diffY = (float) Math.sin(Math.toRadians(horizontalValue0)) * (float) centerX;
+            canvas.drawLine(0, (YY + diffY), width, (YY - diffY), paint);
+        }
+        else
+        {
+            // 縦持ち状態
+            float XX = canvas.getWidth() / 2.0f; // centerX
+            float diffX = (float) Math.sin(Math.toRadians(horizontalValue0)) * (float) centerY;
+            canvas.drawLine((XX + diffX), 0, (XX - diffX), canvas.getHeight(), paint);
+
+        }
+    }
+
+    /**
+     * Converts a point on image area to a point on view area.
+     *
+     * @param point A point on image area. (e.g. a live preview image)
+     * @return A point on view area. (e.g. a touch panel view)
+     */
+    private PointF convertPointFromImageArea(PointF point) {
+        if (imageBitmap == null) {
+            return new PointF();
+        }
+
+        float viewPointX = point.x;
+        float viewPointY = point.y;
+        float imageSizeWidth;
+        float imageSizeHeight;
+        if (imageRotationDegrees == 0 || imageRotationDegrees == 180)
+        {
+            imageSizeWidth = imageBitmap.getWidth();
+            imageSizeHeight = imageBitmap.getHeight();
+        }
+        else
+        {
+            imageSizeWidth = imageBitmap.getHeight();
+            imageSizeHeight = imageBitmap.getWidth();
+        }
+        float viewSizeWidth = this.getWidth();
+        float viewSizeHeight = this.getHeight();
+        float ratioX = viewSizeWidth / imageSizeWidth;
+        float ratioY = viewSizeHeight / imageSizeHeight;
+        float scale;
+
+        switch (imageScaleType) {
+            case FIT_XY:
+                viewPointX *= ratioX;
+                viewPointY *= ratioY;
+                break;
+            case FIT_CENTER:   // go to next label.
+            case CENTER_INSIDE:
+                scale = Math.min(ratioX, ratioY);
+                viewPointX *= scale;
+                viewPointY *= scale;
+                viewPointX += (viewSizeWidth  - imageSizeWidth  * scale) / 2.0f;
+                viewPointY += (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+                break;
+            case CENTER_CROP:
+                scale = Math.max(ratioX, ratioY);
+                viewPointX *= scale;
+                viewPointY *= scale;
+                viewPointX += (viewSizeWidth  - imageSizeWidth  * scale) / 2.0f;
+                viewPointY += (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+                break;
+            case CENTER:
+                viewPointX += viewSizeWidth / 2.0  - imageSizeWidth  / 2.0f;
+                viewPointY += viewSizeHeight / 2.0 - imageSizeHeight / 2.0f;
+                break;
+            default:
+                break;
+        }
+
+        return new PointF(viewPointX, viewPointY);
+    }
+
+    /**
+     * Converts a point on view area to a point on image area.
+     *
+     * @param point A point on view area. (e.g. a touch panel view)
+     * @return A point on image area. (e.g. a live preview image)
+     */
+    private PointF convertPointFromViewArea(PointF point)
+    {
+        if (imageBitmap == null)
+        {
+            return new PointF();
+        }
+
+        float imagePointX = point.x;
+        float imagePointY = point.y;
+        float imageSizeWidth;
+        float imageSizeHeight;
+        if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+            imageSizeWidth = imageBitmap.getWidth();
+            imageSizeHeight = imageBitmap.getHeight();
+        } else {
+            imageSizeWidth = imageBitmap.getHeight();
+            imageSizeHeight = imageBitmap.getWidth();
+        }
+        float viewSizeWidth = this.getWidth();
+        float viewSizeHeight = this.getHeight();
+        float ratioX = viewSizeWidth / imageSizeWidth;
+        float ratioY = viewSizeHeight / imageSizeHeight;
+        float scale;
+
+        switch (imageScaleType) {
+            case FIT_XY:
+                imagePointX /= ratioX;
+                imagePointY /= ratioY;
+                break;
+            case FIT_CENTER:   // go to next label.
+            case CENTER_INSIDE:
+                scale = Math.min(ratioX, ratioY);
+                imagePointX -= (viewSizeWidth  - imageSizeWidth  * scale) / 2.0f;
+                imagePointY -= (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+                imagePointX /= scale;
+                imagePointY /= scale;
+                break;
+            case CENTER_CROP:
+                scale = Math.max(ratioX, ratioY);
+                imagePointX -= (viewSizeWidth  - imageSizeWidth  * scale) / 2.0f;
+                imagePointY -= (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+                imagePointX /= scale;
+                imagePointY /= scale;
+                break;
+            case CENTER:
+                imagePointX -= (viewSizeWidth - imageSizeWidth)  / 2.0f;
+                imagePointY -= (viewSizeHeight - imageSizeHeight) / 2.0f;
+                break;
+            default:
+                break;
+        }
+
+        return new PointF(imagePointX, imagePointY);
+    }
+
+    /**
+     * Converts a rectangle on image area to a rectangle on view area.
+     *
+     * @param rect A rectangle on image area. (e.g. a live preview image)
+     * @return A rectangle on view area. (e.g. a touch panel view)
+     */
+    private RectF convertRectFromImageArea(RectF rect)
+    {
+        if (imageBitmap == null)
+        {
+            return new RectF();
+        }
+
+        PointF imageTopLeft =  new PointF(rect.left, rect.top);
+        PointF imageBottomRight = new PointF(rect.right, rect.bottom);
+
+        PointF viewTopLeft = convertPointFromImageArea(imageTopLeft);
+        PointF viewBottomRight = convertPointFromImageArea(imageBottomRight);
+
+        return (new RectF(viewTopLeft.x, viewTopLeft.y, viewBottomRight.x, viewBottomRight.y));
+    }
+
+    @Override
+    public void toggleFocusAssist()
+    {
+        focusAssistFeature = !focusAssistFeature;
+    }
+
+    @Override
+    public void toggleShowGridFrame()
+    {
+        showGridFeature = !showGridFeature;
+        SharedPreferences preferences = android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(getContext());
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putBoolean(IPreferencePropertyAccessor.SHOW_GRID_STATUS, showGridFeature);
+        editor.apply();
+    }
+
+    public boolean isShowGrid()
+    {
+        return (showGridFeature);
+    }
+
+    @Override
+    public IMessageDrawer getMessageDrawer()
+    {
+        return (messageHolder.getMessageDrawer());
+    }
+
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/CameraLiveViewListenerImpl.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/CameraLiveViewListenerImpl.java
new file mode 100644 (file)
index 0000000..43633a8
--- /dev/null
@@ -0,0 +1,54 @@
+package net.osdn.gokigen.a01d.liveview;
+
+import java.util.Map;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraLiveViewListener;
+
+/**
+ *  OLYCameraLiveViewListener の実装
+ *  (LiveViewFragment用)
+ *
+ */
+public class CameraLiveViewListenerImpl implements OLYCameraLiveViewListener
+{
+    private IImageDataReceiver imageView = null;
+
+    /**
+     * コンストラクタ
+     */
+    public CameraLiveViewListenerImpl()
+    {
+        //
+    }
+
+    /**
+     * 更新するImageViewを拾う
+     *
+     */
+    public void setCameraLiveImageView(IImageDataReceiver target)
+    {
+        this.imageView = target;
+    }
+
+    /**
+     * LiveViewの画像データを更新する
+     *
+     */
+    @Override
+    public void onUpdateLiveView(OLYCamera camera, byte[] data, Map<String, Object> metadata)
+    {
+        if (imageView != null)
+        {
+            imageView.setImageData(data, metadata);
+        }
+    }
+
+    /**
+     *   CameraLiveImageView
+     */
+    public interface IImageDataReceiver
+    {
+        void setImageData(byte[] data, Map<String, Object> metadata);
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/IAutoFocusFrameDisplay.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/IAutoFocusFrameDisplay.java
new file mode 100644 (file)
index 0000000..7b5a6a5
--- /dev/null
@@ -0,0 +1,30 @@
+package net.osdn.gokigen.a01d.liveview;
+
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.view.MotionEvent;
+
+/**
+ *   フォーカスフレームの表示クラス
+ *
+ */
+public interface IAutoFocusFrameDisplay
+{
+    // フォーカスフレームの状態
+    enum FocusFrameStatus
+    {
+        Running,
+        Focused,
+        Failed,
+        Errored,
+    }
+
+    float getContentSizeWidth();
+    float getContentSizeHeight();
+
+    PointF getPointWithEvent(MotionEvent event);
+    boolean isContainsPoint(PointF point);
+
+    void showFocusFrame(RectF rect, FocusFrameStatus status, double duration);
+    void hideFocusFrame();
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/ICameraPanelDrawer.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/ICameraPanelDrawer.java
new file mode 100644 (file)
index 0000000..e3e6d2d
--- /dev/null
@@ -0,0 +1,12 @@
+package net.osdn.gokigen.a01d.liveview;
+
+import android.graphics.Canvas;
+
+/**
+ *   カメラパネルの描画
+ *
+ */
+public interface ICameraPanelDrawer
+{
+    void drawCameraPanel(Canvas canvas);
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/ICameraStatusDisplay.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/ICameraStatusDisplay.java
new file mode 100644 (file)
index 0000000..f4d49dc
--- /dev/null
@@ -0,0 +1,17 @@
+package net.osdn.gokigen.a01d.liveview;
+
+/**
+ *
+ */
+public interface ICameraStatusDisplay
+{
+    void updateTakeMode();
+    void updateDriveMode();
+    void updateWhiteBalance();
+    void updateBatteryLevel();
+    void updateAeMode();
+    void updateAeLockState();
+    void updateCameraStatus();
+    void updateCameraStatus(String message);
+    void updateLevelGauge(String orientation, float roll, float pitch);
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/ILiveImageStatusNotify.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/ILiveImageStatusNotify.java
new file mode 100644 (file)
index 0000000..b3e75b9
--- /dev/null
@@ -0,0 +1,14 @@
+package net.osdn.gokigen.a01d.liveview;
+
+import net.osdn.gokigen.a01d.liveview.message.IMessageDrawer;
+
+/**
+ *
+ *
+ */
+interface ILiveImageStatusNotify
+{
+    void toggleFocusAssist();
+    void toggleShowGridFrame();
+    IMessageDrawer getMessageDrawer();
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/IStatusViewDrawer.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/IStatusViewDrawer.java
new file mode 100644 (file)
index 0000000..1b23efd
--- /dev/null
@@ -0,0 +1,20 @@
+package net.osdn.gokigen.a01d.liveview;
+
+interface IStatusViewDrawer
+{
+    void updateGridIcon();
+    void updateConnectionStatus();
+    /*
+    void updateStatusView(String message);
+    void updateFocusAssistStatus();
+    void updateGridFrameStatus();
+    void showFavoriteSettingDialog();
+
+    void toggleTimerStatus();
+
+    void toggleGpsTracking();
+    void updateGpsTrackingStatus();
+
+    IMessageDrawer getMessageDrawer();
+*/
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/LiveViewClickListener.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/LiveViewClickListener.java
new file mode 100644 (file)
index 0000000..4edf831
--- /dev/null
@@ -0,0 +1,69 @@
+package net.osdn.gokigen.a01d.liveview;
+
+import android.util.Log;
+import android.view.View;
+
+import net.osdn.gokigen.a01d.IChangeScene;
+import net.osdn.gokigen.a01d.R;
+
+/**
+ *
+ *
+ */
+
+class LiveViewClickListener implements View.OnClickListener
+{
+    final String TAG = toString();
+    final ILiveImageStatusNotify statusNotify;
+    final IStatusViewDrawer statusViewDrawer;
+    final IChangeScene changeScene;
+
+
+    LiveViewClickListener(ILiveImageStatusNotify imageStatusNotify, IStatusViewDrawer statusView, IChangeScene changeScene)
+    {
+        this.statusNotify = imageStatusNotify;
+        this.statusViewDrawer = statusView;
+        this.changeScene = changeScene;
+    }
+
+
+    @Override
+    public void onClick(View view)
+    {
+        int id = view.getId();
+        try
+        {
+            switch (id)
+            {
+                case R.id.show_hide_grid_button:
+                    // グリッドの ON/OFF
+                    statusNotify.toggleShowGridFrame();
+                    statusViewDrawer.updateGridIcon();
+                    break;
+
+                case R.id.show_preference_button:
+                    // カメラの設定
+                    changeScene.changeSceneToConfiguration();
+                    break;
+
+                case R.id.camera_property_settings_button:
+                    // カメラのプロパティ設定
+                    changeScene.changeSceneToCameraPropertyList();
+                    break;
+
+                case R.id.connect_disconnect_button:
+                    // カメラと接続・切断のボタンが押された
+                    changeScene.changeCameraConnection();
+                    break;
+
+                default:
+                    Log.v(TAG, "onClick() : " + id);
+                    break;
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/LiveViewFragment.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/LiveViewFragment.java
new file mode 100644 (file)
index 0000000..8c1ffac
--- /dev/null
@@ -0,0 +1,756 @@
+package net.osdn.gokigen.a01d.liveview;
+
+import android.app.Activity;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.content.res.ResourcesCompat;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import net.osdn.gokigen.a01d.IChangeScene;
+import net.osdn.gokigen.a01d.R;
+
+import java.io.File;
+
+
+/**
+ *  撮影用ライブビュー画面
+ *
+ */
+public class LiveViewFragment extends Fragment implements IStatusViewDrawer
+{
+    private final String TAG = this.toString();
+    private static final int COMMAND_MY_PROPERTY = 0x00000100;
+
+//    private IOlyCameraCoordinator camera = null;
+//    private MyInterfaceProvider factory = null;
+//    private ICameraRunMode changeRunModeExecutor = null;
+//    private OlyCameraLiveViewOnTouchListener onTouchListener = null;
+    private CameraLiveViewListenerImpl liveViewListener = null;
+//    private CameraStatusListenerImpl statusListener = null;
+//    private IGpsLocationPicker locationPicker = null;
+
+    private IChangeScene changeScene = null;
+
+    private LiveViewClickListener onClickListener = null;
+
+
+    private TextView statusArea = null;
+    private CameraLiveImageView imageView = null;
+    //private CameraControlPanel cameraPanel = null;
+
+/*
+    private ImageView manualFocus = null;
+    private ImageView afLock = null;
+    private ImageView aeLock = null;
+    private ImageView focusAssist = null;
+*/
+    private ImageButton showGrid = null;
+    private ImageButton connectStatus = null;
+
+    private boolean imageViewCreated = false;
+    private View myView = null;
+    private String messageValue = "";
+
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+        super.onCreate(savedInstanceState);
+        Log.v(TAG, "onCreate()");
+
+        if (liveViewListener == null)
+        {
+            liveViewListener = new CameraLiveViewListenerImpl();
+        }
+
+
+/*
+
+        if (onTouchListener == null)
+        {
+            onTouchListener = new OlyCameraLiveViewOnTouchListener(getContext().getApplicationContext());
+        }
+        if (statusListener == null)
+        {
+            statusListener = new CameraStatusListenerImpl(getContext().getApplicationContext(), this);
+        }
+        if (locationPicker == null)
+        {
+            locationPicker = new GpsLocationPicker(getContext().getApplicationContext(), onTouchListener);
+        }
+*/
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void onAttach(Context context)
+    {
+        super.onAttach(context);
+        Log.v(TAG, "onAttach()");
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+    {
+        super.onCreateView(inflater, container, savedInstanceState);
+
+        Log.v(TAG, "onCreateView()");
+
+        if ((imageViewCreated)&&(myView != null))
+        {
+            // Viewを再利用。。。
+            Log.v(TAG, "onCreateView() : called again, so do nothing...");
+            return (myView);
+        }
+        View view = inflater.inflate(R.layout.fragment_live_view, container, false);
+        myView = view;
+        imageViewCreated = true;
+
+        imageView = view.findViewById(R.id.cameraLiveImageView);
+
+        if (onClickListener == null)
+        {
+            onClickListener = new LiveViewClickListener(imageView, this, changeScene);
+        }
+
+        /*
+        imageView.setOnClickListener(onTouchListener);
+        imageView.setOnTouchListener(onTouchListener);
+*/
+/*
+        liveViewListener.setCameraLiveImageView(imageView);
+        if (factory != null)
+        {
+            factory.setAutoFocusFrameDisplay(imageView);
+        }
+*/
+/*
+        // 画面下部のスマホカメラ領域
+        PhoneCameraView phoneCameraView = (PhoneCameraView) view.findViewById(R.id.phoneCameraView);
+
+        // カメラ画像の大きさを動的に調整(したい)
+        //phoneCameraView.getViewTreeObserver().addOnGlobalLayoutListener(phoneCameraView);
+
+        ImageView shutter = (ImageView) view.findViewById(R.id.shutterImageView);
+        shutter.setOnClickListener(onTouchListener);
+
+        ImageView config = (ImageView) view.findViewById(R.id.configImageView);
+        config.setOnClickListener(onTouchListener);
+
+        ImageView build = (ImageView) view.findViewById(R.id.buildImageView);
+        build.setOnClickListener(onTouchListener);
+
+        ImageButton gps = (ImageButton) view.findViewById(R.id.gpsLocationButton);
+        if ((locationPicker.prepare(camera.getCameraPropertyProvider()))&&(locationPicker.hasGps()))
+        {
+            // GPSボタンの状態を更新しておく
+            updateGpsTrackingStatus();
+
+            // GPSが使用可能な状態のとき...ボタンを押せるようにする
+            gps.setOnClickListener(onTouchListener);
+        }
+        else
+        {
+            // GPSが利用不可のとき、、、ボタンは無効(非表示)にする
+            gps.setEnabled(false);
+            gps.setVisibility(View.INVISIBLE);
+        }
+
+        manualFocus = (ImageView) view.findViewById(R.id.manualFocusImageView);
+        manualFocus.setOnClickListener(onTouchListener);
+
+        afLock = (ImageView) view.findViewById(R.id.AutoFocusLockImageView);
+        afLock.setOnClickListener(onTouchListener);
+
+        aeLock = (ImageView) view.findViewById(R.id.AutoExposureLockImageView);
+        aeLock.setOnClickListener(onTouchListener);
+
+        focusAssist = (ImageView) view.findViewById(R.id.FocusAssistImageView);
+        focusAssist.setOnClickListener(onTouchListener);
+*/
+       try
+       {
+           view.findViewById(R.id.show_preference_button).setOnClickListener(onClickListener);
+           view.findViewById(R.id.camera_property_settings_button).setOnClickListener(onClickListener);
+
+           showGrid = view.findViewById(R.id.show_hide_grid_button);
+           showGrid.setOnClickListener(onClickListener);
+           updateGridIcon();
+
+           connectStatus = view.findViewById(R.id.connect_disconnect_button);
+           connectStatus.setOnClickListener(onClickListener);
+           updateConnectionStatus();
+
+           statusArea = view.findViewById(R.id.informationMessageTextView);
+       }
+       catch (Exception e)
+       {
+           e.printStackTrace();
+       }
+       return (view);
+    }
+
+    /**
+     *
+     */
+    public void prepare(IChangeScene sceneSelector)
+    {
+        this.changeScene = sceneSelector;
+    }
+
+
+    /**
+     *  カメラとの接続状態の更新
+     *
+     */
+    @Override
+    public void updateConnectionStatus()
+    {
+        try
+        {
+            int id = R.drawable.ic_cloud_off_black_24dp;
+            connectStatus.setImageDrawable(ResourcesCompat.getDrawable(getResources(), id, null));
+            connectStatus.invalidate();
+            imageView.invalidate();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *  グリッドの表示・非表示の更新
+     *
+     */
+    @Override
+    public void updateGridIcon()
+    {
+        try
+        {
+            int id = (imageView.isShowGrid()) ? R.drawable.ic_grid_off_black_24dp : R.drawable.ic_grid_on_black_24dp;
+            showGrid.setImageDrawable(ResourcesCompat.getDrawable(getResources(), id, null));
+            showGrid.invalidate();
+            imageView.invalidate();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *   作例表示モードの画像のURIを応答する
+     *
+     * @return Uri : 作例表示する画像のURI
+     */
+    private Uri isSetupSampleImageFile(String fileName)
+    {
+        try
+        {
+            File file = new File(fileName);
+            if (file.exists())
+            {
+                Log.v(TAG, "isSetupSampleImageFile() : " + file.toString());
+                return (Uri.fromFile(file));
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+
+        Log.v(TAG, "isSetupSampleImageFile() : nothing");
+        return (null);
+    }
+
+    /**
+     *   画面下部の表示エリアの用途を切り替える
+     *
+     */
+    private void setupLowerDisplayArea()
+    {
+/*
+        ScalableImageViewPanel sampleImageView = (ScalableImageViewPanel) getActivity().findViewById(R.id.favoriteImageView);
+        PhoneCameraView phoneCameraView = (PhoneCameraView) getActivity().findViewById(R.id.phoneCameraView);
+
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
+        String value = preferences.getString(IPreferencePropertyAccessor.SHOW_SAMPLE_IMAGE, IPreferencePropertyAccessor.SHOW_SAMPLE_IMAGE_DEFAULT_VALUE);
+        if (value.equals("2"))
+        {
+            // 操作パネル表示モード
+            try
+            {
+                phoneCameraView.setVisibility(View.GONE);
+                sampleImageView.setVisibility(View.VISIBLE);
+                CameraControlPanel cameraPanel = new CameraControlPanel(sampleImageView, camera.getCameraPropertyProvider());
+                statusListener.setDelegateListener(cameraPanel);
+                sampleImageView.setOnClickListener(cameraPanel);
+                sampleImageView.setOnTouchListener(cameraPanel);
+                sampleImageView.setOnLongClickListener(cameraPanel);
+                sampleImageView.setCameraPanelDrawer(true, cameraPanel);
+                sampleImageView.invalidate();
+                return;
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+        }
+
+        statusListener.setDelegateListener(null);
+        sampleImageView.setOnClickListener(null);
+        sampleImageView.setOnTouchListener(null);
+        sampleImageView.setOnLongClickListener(null);
+        sampleImageView.setCameraPanelDrawer(false, null);
+
+        Uri uri = null;
+        if (value.equals("1"))
+        {
+            // 作例表示用の画像を取得
+            uri = isSetupSampleImageFile(preferences.getString(IPreferencePropertyAccessor.SELECT_SAMPLE_IMAGE, ""));
+        }
+        if (uri != null)
+        {
+            // 作例表示モード
+            phoneCameraView.setVisibility(View.GONE);
+            sampleImageView.setVisibility(View.VISIBLE);
+            sampleImageView.setImageURI(uri);
+            sampleImageView.invalidate();
+        }
+        else
+        {
+            // デュアルカメラモード
+            phoneCameraView.setVisibility(View.VISIBLE);
+            sampleImageView.setVisibility(View.GONE);
+
+            // カメラの画像にタッチリスナを付与
+            phoneCameraView.setOnClickListener(onTouchListener);
+            phoneCameraView.setOnTouchListener(onTouchListener);
+        }
+*/
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    @Override
+    public void onStart()
+    {
+        super.onStart();
+        Log.v(TAG, "onStart()");
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void onResume()
+    {
+        super.onResume();
+        Log.v(TAG, "onResume() Start");
+/*
+        // 撮影モードかどうかを確認して、撮影モードではなかったら撮影モードに切り替える
+        if ((changeRunModeExecutor != null)&&(!changeRunModeExecutor.isRecordingMode()))
+        {
+            // Runモードを切り替える。(でも切り替えると、設定がクリアされてしまう...。
+            changeRunModeExecutor.changeRunMode(true);
+        }
+
+        // ステータスの変更を通知してもらう
+        camera.setCameraStatusListener(statusListener);
+
+        // 画面下部の表示エリアの用途を切り替える
+        setupLowerDisplayArea();
+
+        // propertyを取得
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
+
+        // グリッド・フォーカスアシストの情報を戻す
+        imageView.setShowGridFrame(preferences.getBoolean(IPreferencePropertyAccessor.SHOW_GRID_STATUS, false));
+        imageView.setFocusAssist(preferences.getBoolean(IPreferencePropertyAccessor.SHOW_FOCUS_ASSIST_STATUS, false));
+        updateCameraPropertyStatus();
+
+        // ステータスの初期情報を表示する
+        updateStatusView(camera.getCameraStatusSummary(statusListener));
+
+        // ライブビューの開始
+        camera.changeLiveViewSize(preferences.getString(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY, IPreferencePropertyAccessor.LIVE_VIEW_QUALITY_DEFAULT_VALUE));
+        camera.setLiveViewListener(liveViewListener);
+        liveViewListener.setCameraLiveImageView(imageView);
+        camera.startLiveView();
+
+        // GPSボタンの更新
+        updateGpsTrackingStatus();
+
+        // デジタル水準器を有効にするかどうか
+        if (statusListener != null)
+        {
+            statusListener.updateLevelGaugeChecking();
+        }
+*/
+        Log.v(TAG, "onResume() End");
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void onPause()
+    {
+        super.onPause();
+        Log.v(TAG, "onPause() Start");
+
+/*
+        // ライブビューの停止
+        camera.stopLiveView();
+        camera.setLiveViewListener(null);
+        liveViewListener.setCameraLiveImageView(null);
+
+        if (locationPicker != null)
+        {
+            // GPS監視の終了
+            locationPicker.controlGps(false);
+            camera.clearGeolocation();
+        }
+*/
+        Log.v(TAG, "onPause() End");
+    }
+
+    /**
+     * カメラクラスをセットする
+     *
+     */
+/*
+    public void setInterfaces(IOlyCameraCoordinator camera, MyInterfaceProvider factory)
+    {
+        Log.v(TAG, "setInterfaces()");
+        this.camera = camera;
+        this.factory = factory;
+        this.changeRunModeExecutor = camera.getChangeRunModeExecutor();
+
+        factory.setStatusInterface(this);
+        factory.setStatusViewDrawer(this);
+        //if (imageView != null)
+        {
+        //    factory.setAutoFocusFrameDisplay(imageView);
+        }
+    }
+*/
+/*
+    @Override
+    public void updateFocusAssistStatus()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateGridFrameStatus()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateTakeMode()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateDriveMode()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateWhiteBalance()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateBatteryLevel()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateAeMode()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateAeLockState()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateCameraStatus()
+    {
+        updateCameraPropertyStatus();
+    }
+
+    @Override
+    public void updateCameraStatus(String message)
+    {
+        updateStatusView(message);
+    }
+*/
+/*
+    @Override
+    public void updateLevelGauge(String orientation, float roll, float pitch)
+    {
+        if (imageView == null)
+        {
+            return;
+        }
+
+        // レベルゲージ(デジタル水準器の情報)が更新されたとき
+        //Log.v(TAG, String.format(Locale.getDefault(), "LEVEL GAUGE : %s roll: %3.3f pitch: %3.3f", orientation, roll, pitch));
+        try
+        {
+            if ((Float.isNaN(roll))||(Float.isNaN(pitch)))
+            {
+                // roll と pitch のどちらかがNaNなら、表示を消す
+                imageView.getMessageDrawer().setMessageToShow(IMessageDrawer.MessageArea.LOWRIGHT, Color.argb(0xff, 0x6e, 0x6e, 0x6e), IMessageDrawer.SIZE_STD, "");
+                imageView.getMessageDrawer().setLevelToShow(IMessageDrawer.LevelArea.LEVEL_HORIZONTAL, Float.NaN);
+                imageView.getMessageDrawer().setLevelToShow(IMessageDrawer.LevelArea.LEVEL_VERTICAL, Float.NaN);
+                return;
+            }
+
+            // 傾きのデータを設定する
+            String message = String.format(Locale.getDefault(), "[%3.1f, %3.1f]", roll, pitch);
+            imageView.getMessageDrawer().setMessageToShow(IMessageDrawer.MessageArea.LOWRIGHT, Color.argb(0xff, 0x6e, 0x6e, 0x6e), IMessageDrawer.SIZE_STD, message);
+            imageView.getMessageDrawer().setLevelToShow(IMessageDrawer.LevelArea.LEVEL_HORIZONTAL, roll);
+            imageView.getMessageDrawer().setLevelToShow(IMessageDrawer.LevelArea.LEVEL_VERTICAL, pitch);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+*/
+/*
+    @Override
+    public void showFavoriteSettingDialog()
+    {
+        LoadSaveMyCameraPropertyDialog dialog = new LoadSaveMyCameraPropertyDialog();
+        dialog.setTargetFragment(this, COMMAND_MY_PROPERTY);
+        dialog.setPropertyOperationsHolder(new CameraPropertyLoadSaveOperations(getActivity(), camera.getLoadSaveCameraProperties(), this));
+        dialog.show(getChildFragmentManager(), "my_dialog");
+    }
+*/
+/*
+    @Override
+    public void toggleTimerStatus()
+    {
+        boolean isBracketing = !isBracketing();
+        SharedPreferences preferences = android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(getContext());
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putBoolean(IPreferencePropertyAccessor.USE_BRACKETING, isBracketing);
+        editor.apply();
+        if (bracketing != null)
+        {
+            bracketing.setSelected(isBracketing);
+        }
+    }
+
+    private boolean isBracketing()
+    {
+        SharedPreferences preferences = android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(getContext());
+        boolean isBracketing = false;
+        if (preferences != null)
+        {
+            isBracketing = preferences.getBoolean(IPreferencePropertyAccessor.USE_BRACKETING, false);
+        }
+        return (isBracketing);
+    }
+*/
+    /**
+     *
+     *
+     */
+/*
+    private void updateCameraPropertyStatus()
+    {
+        try
+        {
+            final boolean isManualFocus = camera.isManualFocus();
+            final boolean isAfLock = camera.isAFLock();
+            final boolean isAeLock = camera.isAELock();
+            final boolean isTimerOn = isBracketing();
+            boolean checkFocusAssist = false;
+            boolean checkShowGrid = false;
+            if (imageView != null)
+            {
+                checkFocusAssist = imageView.isFocusAssist();
+                checkShowGrid = imageView.isShowGrid();
+            }
+            final boolean isFocusAssist = checkFocusAssist;
+            final boolean isShowGrid = checkShowGrid;
+
+            runOnUiThread(new Runnable()
+            {
+                //カメラの状態(インジケータ)を更新する
+                @Override
+                public void run() {
+                    if (camera == null) {
+                        return;
+                    }
+                    Log.v(TAG, "--- UPDATE CAMERA PROPERTY (START) ---");
+                    if (manualFocus != null) {
+                        manualFocus.setSelected(isManualFocus);
+                    }
+                    if (afLock != null) {
+                        afLock.setSelected(isAfLock);
+                    }
+                    if (aeLock != null) {
+                        aeLock.setSelected(isAeLock);
+                    }
+                    if ((focusAssist != null) && (imageView != null)) {
+                        focusAssist.setSelected(isFocusAssist);
+                    }
+                    if ((showGrid != null) && (imageView != null)) {
+                        showGrid.setSelected(isShowGrid);
+                    }
+                    if (bracketing != null)
+                    {
+                        bracketing.setSelected(isTimerOn);
+                    }
+                    Log.v(TAG, "--- UPDATE CAMERA PROPERTY (END) ---");
+                }
+            });
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+*/
+
+    /**
+     *
+     *
+     */
+/*
+    @Override
+    public IMessageDrawer getMessageDrawer()
+    {
+        return (imageView.getMessageDrawer());
+    }
+*/
+    /**
+     *   表示エリアに文字を表示する
+     *
+     */
+    public void updateStatusView(String message)
+    {
+        messageValue = message;
+        runOnUiThread(new Runnable()
+        {
+            /**
+             * カメラの状態(ステータステキスト)を更新する
+             * (ステータステキストは、プライベート変数で保持して、書き換える)
+             */
+            @Override
+            public void run()
+            {
+                if (statusArea != null)
+                {
+                    statusArea.setText(messageValue);
+                }
+            }
+        });
+    }
+/*
+    @Override
+    public void toggleGpsTracking()
+    {
+        if (locationPicker == null)
+        {
+            return;
+        }
+        locationPicker.controlGps(!locationPicker.isTracking());
+        updateGpsTrackingStatus();
+    }
+
+    @Override
+    public void updateGpsTrackingStatus()
+    {
+        Log.v(TAG, "updateGpsTrackingStatus()");
+        if ((myView == null)||(locationPicker == null))
+        {
+            Log.v(TAG, "updateGpsTrackingStatus() : null");
+            return;
+        }
+
+        ImageButton gps = (ImageButton) myView.findViewById(R.id.gpsLocationButton);
+        int id = R.drawable.btn_location_off;
+        if (locationPicker.isTracking())
+        {
+            if (locationPicker.isFixedLocation())
+            {
+                // 位置が確定している
+                id = R.drawable.btn_location_on;
+            }
+            else
+            {
+                // 位置検索中だが未確定...
+                id = R.drawable.btn_gps_not_fixed;
+            }
+        }
+        else
+        {
+            // 位置情報をクリアする
+            camera.clearGeolocation();
+        }
+        try
+        {
+            // ボタンの表示を変える
+            gps.setImageResource(id);
+            //gps.setImageDrawable(getContext().getResources().getDrawable(id));
+            gps.invalidate();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+*/
+
+
+    private void runOnUiThread(Runnable action)
+    {
+        Activity activity = getActivity();
+        if (activity == null)
+        {
+            return;
+        }
+        activity.runOnUiThread(action);
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/ScalableImageViewPanel.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/ScalableImageViewPanel.java
new file mode 100644 (file)
index 0000000..5fc1ec5
--- /dev/null
@@ -0,0 +1,411 @@
+package net.osdn.gokigen.a01d.liveview;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.support.v7.widget.AppCompatImageView;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+
+/**
+ *  イメージを表示する ... ImageViewerSampleから持ってくる
+ *
+ */
+public class ScalableImageViewPanel extends AppCompatImageView
+{
+
+    private static enum GestureMode {
+        None,
+        Move,
+        Zoom,
+    }
+
+    private ICameraPanelDrawer cameraPanelDrawer;
+    private boolean overrideDrawer;
+    private Context mContext;
+    private GestureDetector mDoubleTapDetector;
+    private GestureMode mGestureMode;
+
+    /** The affine transformation matrix. */
+    private Matrix mMatrix;
+
+    /** The horizontal moving factor after scaling. */
+    private float mMoveX;
+    /** The vertical moving factor after scaling. */
+    private float mMoveY;
+    /** The X-coordinate origin for calculating the amount of movement. */
+    private float mMovingBaseX;
+    /** The Y-coordinate origin for calculating the amount of movement. */
+    private float mMovingBaseY;
+
+    /** The scaling factor. */
+    private float mScale;
+    /** The minimum value of scaling factor. */
+    private float mScaleMin;
+    /** The maximum value of scaling factor. */
+    private float mScaleMax;
+    /** The distance from the center for determining the amount of scaling. */
+    private float mScalingBaseDistance;
+    /** The center X-coordinate to determine the amount of scaling. */
+    private float mScalingCenterX;
+    /** The center Y-coordinate to determine the amount of scaling. */
+    private float mScalingCenterY;
+
+    /** The width of the view. */
+    private int mViewWidth;
+    /** The height of the view. */
+    private int mViewHeight;
+    /** The width of the image. */
+    private int mImageWidth;
+    /** The height of the image. */
+    private int mImageHeight;
+
+
+    @Override
+    public void setImageDrawable(Drawable drawable) {
+        super.setImageDrawable(drawable);
+        reset();
+    };
+
+    @Override
+    public void setImageBitmap(Bitmap bm) {
+        super.setImageBitmap(bm);
+        reset();
+    };
+
+    @Override
+    public void setImageURI(Uri uri) {
+        super.setImageURI(uri);
+        reset();
+    }
+
+    /**
+     *
+     *
+     */
+    public void setCameraPanelDrawer(boolean isOverrideDrawer, ICameraPanelDrawer drawer)
+    {
+        this.overrideDrawer = isOverrideDrawer;
+        this.cameraPanelDrawer = drawer;
+    }
+
+    /**
+     * Constructs a new CapturedImageView.
+     *
+     * @param context
+     */
+    public ScalableImageViewPanel(Context context) {
+        super(context);
+        mContext = context;
+        init();
+    }
+
+    /**
+     * Constructs a new CapturedImageView.
+     *
+     * @param context
+     * @param attrs
+     */
+    public ScalableImageViewPanel(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+        init();
+    }
+
+    /**
+     * Constructs a new CapturedImageView.
+     *
+     * @param context
+     * @param attrs
+     * @param defStyle
+     */
+    public ScalableImageViewPanel(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mContext = context;
+        init();
+    }
+
+    /**
+     * Initializes this instance.
+     */
+    private void init() {
+        this.cameraPanelDrawer = null;
+        this.overrideDrawer = false;
+        this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        this.setScaleType(ScaleType.MATRIX);
+        mMatrix = new Matrix();
+        mViewWidth = 0;
+        mViewHeight = 0;
+        mImageWidth = 0;
+        mImageHeight = 0;
+        mGestureMode = GestureMode.None;
+        mMoveX = 0;
+        mMoveY = 0;
+        mScale = 1.f;
+        mScaleMin = 1.f;
+        mScaleMax = 4.f;
+
+        // Setups touch gesture.
+        mDoubleTapDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
+            @Override
+            public boolean onDoubleTap(MotionEvent e) {
+                if (mScale != 1.0f) {
+                    // Zooms at tapped point.
+                    updateScaleWithBasePoint(1.0f, e.getX(), e.getY());
+                } else {
+                    // Zooms out.
+                    fitScreen();
+                }
+                updateMatrix();
+                return true;
+            }
+        });
+    }
+
+    /**
+     * Resets current scaling.
+     */
+    private void reset() {
+        Drawable drawable = this.getDrawable();
+        if (drawable != null) {
+            mImageWidth = drawable.getIntrinsicWidth();
+            mImageHeight = drawable.getIntrinsicHeight();
+            fitScreen();
+            updateMatrix();
+        }
+    }
+
+    @Override
+    protected boolean setFrame(int l, int t, int r, int b) {
+        mViewWidth = r - l;
+        mViewHeight = b - t;
+        if (this.getDrawable() != null) {
+            fitScreen();
+        }
+        updateMatrix();
+        return super.setFrame(l, t, r, b);
+    }
+
+    /**
+     * Returns a scaled X offset.
+     *
+     * @param scale A scaling factor.
+     * @param moveX A horizontal moving factor.
+     * @return A scaled X offset.
+     */
+    private float computeOffsetX(float scale, float moveX) {
+        // Offsets in order to center the image.
+        float scaledWidth = scale * mImageWidth;
+        float offsetX = (mViewWidth - scaledWidth) / 2;
+        // Moves specified offset.
+        offsetX += moveX;
+        return offsetX;
+    }
+
+    /**
+     * Returns a scaled Y offset.
+     *
+     * @param scale A scaling factor.
+     * @param moveY A vertical moving factor.
+     * @return A scaled Y offset.
+     */
+    private float computeOffsetY(float scale, float moveY) {
+        // Offsets in order to center the image.
+        float scaledHeight = scale * mImageHeight;
+        float offsetY = (mViewHeight - scaledHeight) / 2;
+        // Moves specified offset.
+        offsetY += moveY;
+        return offsetY;
+    }
+
+    /**
+     * Updates affine transformation matrix to display the image.
+     */
+    private void updateMatrix() {
+        // Creates new matrix.
+        mMatrix.reset();
+        mMatrix.postScale(mScale, mScale);
+        mMatrix.postTranslate(computeOffsetX(mScale, mMoveX), computeOffsetY(mScale, mMoveY));
+
+        // Updates the matrix.
+        this.setImageMatrix(mMatrix);
+        this.invalidate();
+    }
+
+    /**
+     * Calculates zoom scale. (for the image size to fit screen size).
+     */
+    private void fitScreen() {
+        if ((mImageWidth == 0) || (mImageHeight == 0) || (mViewWidth == 0) || (mViewHeight == 0)) {
+            return;
+        }
+
+        // Clears the moving factors.
+        updateMove(0, 0);
+
+        // Gets scaling ratio.
+        float scaleX = (float)mViewWidth / mImageWidth;
+        float scaleY = (float)mViewHeight / mImageHeight;
+
+        // Updates the scaling factor so that the image will not be larger than the screen size.
+        mScale = Math.min(scaleX, scaleY);
+        mScaleMin = mScale;
+        // 4 times of original image size or 4 times of the screen size.
+        mScaleMax = Math.max(4.f, mScale * 4);
+    }
+
+    /**
+     * Updates the moving factors.
+     *
+     * @param moveX A horizontal moving factor.
+     * @param moveY A vertical moving factor.
+     */
+    protected void updateMove(float moveX, float moveY) {
+        mMoveX = moveX;
+        mMoveY = moveY;
+
+        // Gets scaled size.
+        float scaledWidth = mImageWidth * mScale;
+        float scaledHeight = mImageHeight * mScale;
+
+        // Clips the moving factors.
+        if (scaledWidth <= mViewWidth) {
+            mMoveX = 0;
+        } else {
+            float minMoveX = -(scaledWidth - mViewWidth) / 2;
+            float maxMoveX = +(scaledWidth - mViewWidth) / 2;
+            mMoveX = Math.min(Math.max(mMoveX, minMoveX), maxMoveX);
+        }
+        if (scaledHeight <= mViewHeight) {
+            mMoveY = 0;
+        } else {
+            float minMoveY = -(scaledHeight - mViewHeight) / 2;
+            float maxMoveY = +(scaledHeight - mViewHeight) / 2;
+            mMoveY = Math.min(Math.max(mMoveY, minMoveY), maxMoveY);
+        }
+    }
+
+    /**
+     * Updates the scaling factor. The specified point doesn't change in appearance.
+     *
+     * @param newScale The new scaling factor.
+     * @param baseX The center position of scaling.
+     * @param baseY The center position of scaling.
+     */
+    protected void updateScaleWithBasePoint(float newScale, float baseX, float baseY) {
+        float lastScale = mScale;
+        float lastOffsetX = computeOffsetX(mScale, mMoveX);
+        float lastOffsetY = computeOffsetY(mScale, mMoveY);
+
+        // Updates the scale with clipping.
+        mScale = Math.min(Math.max(newScale, mScaleMin), mScaleMax);
+        mScalingCenterX = baseX;
+        mScalingCenterY = baseY;
+
+        // Gets scaling base point on the image world.
+        float scalingCenterXOnImage = (mScalingCenterX - lastOffsetX) / lastScale;
+        float scalingCenterYOnImage = (mScalingCenterY - lastOffsetY) / lastScale;
+        // Gets scaling base point on the scaled image world.
+        float scalingCenterXOnScaledImage = scalingCenterXOnImage * mScale;
+        float scalingCenterYOnScaledImage = scalingCenterYOnImage * mScale;
+        // Gets scaling base point on the view world.
+        float scalingCenterXOnView = computeOffsetX(mScale, 0) + scalingCenterXOnScaledImage;
+        float scalingCenterYOnView = computeOffsetY(mScale, 0) + scalingCenterYOnScaledImage;
+
+        // Updates moving.
+        updateMove(mScalingCenterX - scalingCenterXOnView, mScalingCenterY - scalingCenterYOnView);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (mDoubleTapDetector.onTouchEvent(event)) {
+            return true;
+        }
+
+        int action = event.getAction() & MotionEvent.ACTION_MASK;
+        int touchCount = event.getPointerCount();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                if (mScale > mScaleMin) {
+                    // Starts to move the image and takes in the start point.
+                    mGestureMode = GestureMode.Move;
+                    mMovingBaseX = event.getX();
+                    mMovingBaseY = event.getY();
+                }
+                break;
+            case MotionEvent.ACTION_POINTER_DOWN:
+                if (touchCount >= 2) {
+                    // Starts zooming and takes in the center point.
+                    mGestureMode = GestureMode.Zoom;
+                    float distance = (float)Math.hypot(event.getX(0) - event.getX(1), event.getY(0) - event.getY(1));
+                    mScalingBaseDistance = distance;
+                    mScalingCenterX = (event.getX(0) + event.getX(1)) / 2;
+                    mScalingCenterY = (event.getY(0) + event.getY(1)) / 2;
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mGestureMode == GestureMode.Move) {
+                    // Moves the image and updates the start point.
+                    float moveX = event.getX() - mMovingBaseX;
+                    float moveY = event.getY() - mMovingBaseY;
+                    mMovingBaseX = event.getX();
+                    mMovingBaseY = event.getY();
+                    updateMove(mMoveX + moveX, mMoveY + moveY);
+                    updateMatrix();
+                } else if ((mGestureMode == GestureMode.Zoom) && (touchCount >= 2)) {
+                    // Zooms the image and updates the distance from the center point.
+                    float distance = (float)Math.hypot(event.getX(0) - event.getX(1), event.getY(0) - event.getY(1));
+                    float scale = distance / mScalingBaseDistance;
+                    mScalingBaseDistance = distance;
+                    updateScaleWithBasePoint(mScale * scale, mScalingCenterX, mScalingCenterY);
+                    updateMatrix();
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_POINTER_UP:
+                // Finishes all gestures.
+                mGestureMode = GestureMode.None;
+                break;
+        }
+        return true;
+    }
+
+    // The content in view can scroll to horizontal.
+    public boolean canHorizontalScroll()
+    {
+        if (mScale == mScaleMin) {
+            return false;
+        }
+        if (mGestureMode == GestureMode.None)
+        {
+            return false;
+        }
+
+        // TODO: Please improve UX.
+        // If the view rectangle is touching to the edge of the image, the view cannot be scrolled.
+
+        return true;
+    }
+
+    /**
+     *   Draw on Canvas
+     *
+     */
+    @Override
+    public void onDraw(Canvas canvas)
+    {
+        if (!overrideDrawer)
+        {
+            super.onDraw(canvas);
+        }
+        if (cameraPanelDrawer != null)
+        {
+            cameraPanelDrawer.drawCameraPanel(canvas);
+        }
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/ConvertNothing.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/ConvertNothing.java
new file mode 100644 (file)
index 0000000..1c97724
--- /dev/null
@@ -0,0 +1,21 @@
+package net.osdn.gokigen.a01d.liveview.bitmapconvert;
+
+import android.graphics.Bitmap;
+
+/**
+ *
+ *
+ */
+class ConvertNothing implements IPreviewImageConverter
+{
+    /**
+     *   変換後のビットマップを応答する
+     *
+     * @return 変換後のビットマップ
+     */
+    @Override
+    public Bitmap getModifiedBitmap(Bitmap src)
+    {
+        return (src);
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/IPreviewImageConverter.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/IPreviewImageConverter.java
new file mode 100644 (file)
index 0000000..d500652
--- /dev/null
@@ -0,0 +1,11 @@
+package net.osdn.gokigen.a01d.liveview.bitmapconvert;
+
+import android.graphics.Bitmap;
+
+/**
+ *   ビットマップ変換
+ */
+public interface IPreviewImageConverter
+{
+    Bitmap getModifiedBitmap(Bitmap src);
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/ImageConvertFactory.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/bitmapconvert/ImageConvertFactory.java
new file mode 100644 (file)
index 0000000..0a5d9dd
--- /dev/null
@@ -0,0 +1,22 @@
+package net.osdn.gokigen.a01d.liveview.bitmapconvert;
+
+/**
+ *
+ *
+ */
+public class ImageConvertFactory
+{
+    private static final int CONVERT_TYPE_0 = 0;
+    private static final int CONVERT_TYPE_1 = 1;
+    private static final int CONVERT_TYPE_2 = 2;
+    private static final int CONVERT_TYPE_3 = 3;
+    private static final int CONVERT_TYPE_4 = 4;
+    private static final int CONVERT_TYPE_5 = 5;
+    private static final int CONVERT_TYPE_6 = 6;
+
+    public static IPreviewImageConverter getImageConverter(int id)
+    {
+        IPreviewImageConverter drawer = new ConvertNothing();
+        return (drawer);
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/GridFrameDrawerDefault.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/GridFrameDrawerDefault.java
new file mode 100644 (file)
index 0000000..ea4e0e8
--- /dev/null
@@ -0,0 +1,35 @@
+package net.osdn.gokigen.a01d.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ *   対角線のグリッド表示
+ */
+public class GridFrameDrawerDefault implements IGridFrameDrawer
+{
+    /**
+     *
+     *
+     */
+    @Override
+    public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+    {
+        float w = (rect.right - rect.left) / 3.0f;
+        float h = (rect.bottom - rect.top) / 3.0f;
+
+        canvas.drawLine(rect.left + w, rect.top, rect.left + w, rect.bottom, paint);
+        canvas.drawLine(rect.left + 2.0f * w, rect.top, rect.left + 2.0f * w, rect.bottom, paint);
+        canvas.drawLine(rect.left, rect.top + h, rect.right, rect.top + h, paint);
+        canvas.drawLine(rect.left, rect.top + 2.0f * h, rect.right, rect.top + 2.0f * h, paint);
+        canvas.drawRect(rect, paint);
+    }
+
+    @Override
+    public int getDrawColor()
+    {
+        return (Color.argb(130,235,235,235));
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/GridFrameFactory.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/GridFrameFactory.java
new file mode 100644 (file)
index 0000000..21207b5
--- /dev/null
@@ -0,0 +1,21 @@
+package net.osdn.gokigen.a01d.liveview.gridframe;
+
+/**
+ *
+ *
+ */
+public class GridFrameFactory
+{
+    private static final int GRID_FRAME_0 = 0;
+    private static final int GRID_FRAME_1 = 1;
+    private static final int GRID_FRAME_2 = 2;
+    private static final int GRID_FRAME_3 = 3;
+    private static final int GRID_FRAME_4 = 4;
+    private static final int GRID_FRAME_5 = 5;
+    private static final int GRID_FRAME_6 = 6;
+
+    public static IGridFrameDrawer getGridFrameDrawer(int id)
+    {
+        return (new GridFrameDrawerDefault());
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/IGridFrameDrawer.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/gridframe/IGridFrameDrawer.java
new file mode 100644 (file)
index 0000000..7350dcb
--- /dev/null
@@ -0,0 +1,15 @@
+package net.osdn.gokigen.a01d.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ *   撮影補助線の描画クラス
+ *
+ */
+public interface IGridFrameDrawer
+{
+    void drawFramingGrid(Canvas canvas, RectF rect, Paint paint);
+    int getDrawColor();
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/message/IMessageDrawer.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/message/IMessageDrawer.java
new file mode 100644 (file)
index 0000000..c7df0f8
--- /dev/null
@@ -0,0 +1,32 @@
+package net.osdn.gokigen.a01d.liveview.message;
+
+public interface IMessageDrawer
+{
+    // メッセージを表示する位置
+    enum MessageArea
+    {
+        UPLEFT,
+        UPRIGHT,
+        CENTER,
+        LOWLEFT,
+        LOWRIGHT,
+        UPCENTER,
+        LOWCENTER,
+        LEFTCENTER,
+        RIGHTCENTER,
+    }
+
+    enum LevelArea
+    {
+        LEVEL_HORIZONTAL,
+        LEVEL_VERTICAL,
+    }
+
+    int SIZE_STD = 16;
+    int SIZE_LARGE = 24;
+    int SIZE_BIG = 32;
+
+    void setMessageToShow(MessageArea area, int color, int size, String message);
+    void setLevelToShow(LevelArea area, float value);
+
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/message/IMessageHolder.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/message/IMessageHolder.java
new file mode 100644 (file)
index 0000000..0cbfa6e
--- /dev/null
@@ -0,0 +1,13 @@
+package net.osdn.gokigen.a01d.liveview.message;
+
+public interface IMessageHolder
+{
+    int getSize(IMessageDrawer.MessageArea area);
+    int getColor(IMessageDrawer.MessageArea area);
+    String getMessage(IMessageDrawer.MessageArea area);
+
+    boolean isLevel();
+    float getLevel(IMessageDrawer.LevelArea area);
+    int getLevelColor(float value);
+    IMessageDrawer getMessageDrawer();
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/liveview/message/ShowMessageHolder.java b/app/src/main/java/net/osdn/gokigen/a01d/liveview/message/ShowMessageHolder.java
new file mode 100644 (file)
index 0000000..bd9c7c2
--- /dev/null
@@ -0,0 +1,265 @@
+package net.osdn.gokigen.a01d.liveview.message;
+
+import android.graphics.Color;
+import android.view.ViewDebug;
+
+/**
+ *
+ *
+ * Created by MRSa on 2017/03/01.
+ */
+public class ShowMessageHolder implements IMessageDrawer, IMessageHolder
+{
+    /**
+     *
+     */
+    private class messageHolder
+    {
+        private String message = "";
+        private int color = Color.BLUE;
+        private int textSize = 16;
+
+        String getMessage()
+        {
+            return message;
+        }
+
+        void setMessage(String message)
+        {
+            this.message = message;
+        }
+
+        int getColor()
+        {
+            return color;
+        }
+
+        void setColor(int color)
+        {
+            this.color = color;
+        }
+
+        int getTextSize()
+        {
+            return textSize;
+        }
+
+        void setTextSize(int textSize)
+        {
+            this.textSize = textSize;
+        }
+    }
+
+    private messageHolder upperLeft = new messageHolder();
+    private messageHolder upperRight = new messageHolder();
+    private messageHolder center = new messageHolder();
+    private messageHolder lowerLeft = new messageHolder();
+    private messageHolder lowerRight = new messageHolder();
+    private messageHolder upperCenter = new messageHolder();
+    private messageHolder lowerCenter = new messageHolder();
+    private messageHolder leftCenter = new messageHolder();
+    private messageHolder rightCenter = new messageHolder();
+    private float level_horizontal = Float.NaN;
+    private float level_vertical = Float.NaN;
+
+    private float LEVELGAUGE_THRESHOLD_MIDDLE = 2.0f;
+    private float LEVELGAUGE_THRESHOLD_OVER = 15.0f;
+
+    /**
+     *   コンストラクタ
+     *
+     */
+    public ShowMessageHolder()
+    {
+        center.setTextSize(24);
+    }
+
+    /**
+     *
+     *
+     */
+    private messageHolder decideHolder(MessageArea area)
+    {
+        messageHolder target;
+        switch (area)
+        {
+            case CENTER:
+                target = center;
+                break;
+
+            case UPLEFT:
+                target = upperLeft;
+                break;
+
+            case UPRIGHT:
+                target = upperRight;
+                break;
+
+            case LOWLEFT:
+                target = lowerLeft;
+                break;
+
+            case LOWRIGHT:
+                target = lowerRight;
+                break;
+
+            case UPCENTER:
+                target = upperCenter;
+                break;
+
+            case LOWCENTER:
+                target = lowerCenter;
+                break;
+
+            case LEFTCENTER:
+                target = leftCenter;
+                break;
+
+            case RIGHTCENTER:
+                target = rightCenter;
+                break;
+
+            default:
+                target = null;
+                break;
+        }
+        return (target);
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void setMessageToShow(MessageArea area, int color, int size, String message)
+    {
+        messageHolder target = decideHolder(area);
+        if (target != null)
+        {
+            target.setColor(color);
+            target.setTextSize(size);
+            target.setMessage(message);
+        }
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void setLevelToShow(LevelArea area, float value)
+    {
+        if (area == LevelArea.LEVEL_HORIZONTAL)
+        {
+            level_horizontal = value;
+        }
+        else if (area == LevelArea.LEVEL_VERTICAL)
+        {
+           level_vertical = value;
+        }
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public int getSize(MessageArea area)
+    {
+        messageHolder target = decideHolder(area);
+        if (target != null)
+        {
+            return (target.getTextSize());
+        }
+        return (0);
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public int getColor(MessageArea area)
+    {
+        messageHolder target = decideHolder(area);
+        if (target != null)
+        {
+            return (target.getColor());
+        }
+        return (0);
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public String getMessage(MessageArea area)
+    {
+        messageHolder target = decideHolder(area);
+        if (target != null)
+        {
+            return (target.getMessage());
+        }
+        return ("");
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public boolean isLevel()
+    {
+        return (!((Float.isNaN(level_horizontal))||(Float.isNaN(level_vertical))));
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public float getLevel(LevelArea area)
+    {
+        float value;
+        if (area == LevelArea.LEVEL_HORIZONTAL)
+        {
+            value = level_horizontal;
+        }
+        else //  if (area == LevelArea.LEVEL_VERTICAL)
+        {
+            value = level_vertical;
+        }
+        return (value);
+    }
+
+    /**
+     *   傾きの色を取得する
+     *
+     */
+    @Override
+    public int getLevelColor(float value)
+    {
+        value = Math.abs(value);
+
+        if (value < LEVELGAUGE_THRESHOLD_MIDDLE)
+        {
+            return (Color.GREEN);
+        }
+        if (value > LEVELGAUGE_THRESHOLD_OVER)
+        {
+            return (Color.RED);
+        }
+        return (Color.YELLOW);
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public IMessageDrawer getMessageDrawer()
+    {
+        return (this);
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/preference/IPreferencePropertyAccessor.java b/app/src/main/java/net/osdn/gokigen/a01d/preference/IPreferencePropertyAccessor.java
new file mode 100644 (file)
index 0000000..6285842
--- /dev/null
@@ -0,0 +1,45 @@
+package net.osdn.gokigen.a01d.preference;
+
+/**
+ *
+ *
+ *
+ */
+public interface IPreferencePropertyAccessor
+{
+    String EXIT_APPLICATION = "exit_application";
+
+    String AUTO_CONNECT_TO_CAMERA = "auto_connect_to_camera";
+
+    String TAKE_MODE =  "take_mode";
+    String TAKE_MODE_DEFAULT_VALUE =  "P";
+
+    String SOUND_VOLUME_LEVEL = "sound_volume_level";
+    String SOUND_VOLUME_LEVEL_DEFAULT_VALUE = "OFF";
+
+    String RAW = "raw";
+
+    String LIVE_VIEW_QUALITY = "live_view_quality";
+    String LIVE_VIEW_QUALITY_DEFAULT_VALUE = "QVGA";
+
+    String CAMERAKIT_VERSION = "camerakit_version";
+
+    String SHOW_GRID_STATUS = "show_grid";
+/*****
+    int CHOICE_SPLASH_SCREEN = 10;
+
+    int SELECT_SAMPLE_IMAGE_CODE = 110;
+    int SELECT_SPLASH_IMAGE_CODE = 120;
+
+    String getLiveViewSize();
+    void restoreCameraSettings(Callback callback);
+    void storeCameraSettings(Callback callback);
+
+    interface Callback
+    {
+        void stored(boolean result);
+        void restored(boolean result);
+    }
+*****/
+
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/preference/PreferenceFragment.java b/app/src/main/java/net/osdn/gokigen/a01d/preference/PreferenceFragment.java
new file mode 100644 (file)
index 0000000..5e16308
--- /dev/null
@@ -0,0 +1,404 @@
+package net.osdn.gokigen.a01d.preference;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceFragmentCompat;
+import android.support.v7.preference.PreferenceManager;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.IChangeScene;
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.ICameraHardwareStatus;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.ICameraRunMode;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraProperty;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
+import net.osdn.gokigen.a01d.camera.olympus.operation.CameraPowerOff;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+
+/**
+ *   SettingFragment
+ *
+ */
+public class PreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener, PreferenceSynchronizer.IPropertySynchronizeCallback
+{
+    private final String TAG = toString();
+    private IOlyCameraPropertyProvider propertyInterface = null;
+    private ICameraHardwareStatus hardwareStatusInterface = null;
+    private ICameraRunMode changeRunModeExecutor = null;
+    private CameraPowerOff powerOffController = null;
+    private SharedPreferences preferences = null;
+    private ProgressDialog busyDialog = null;
+    private PreferenceSynchronizer preferenceSynchronizer = null;
+
+    public void setInterface(Context context, IOlympusInterfaceProvider factory, IChangeScene changeScene)
+    {
+        Log.v(TAG, "setInterface()");
+        this.propertyInterface = factory.getCameraPropertyProvider();
+        this.changeRunModeExecutor = factory.getCameraRunMode();
+        hardwareStatusInterface = factory.getHardwareStatus();
+        powerOffController = new CameraPowerOff(context, changeScene);
+        powerOffController.prepare();
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void onAttach(Context activity)
+    {
+        super.onAttach(activity);
+        Log.v(TAG, "onAttach()");
+
+        // Preference をつかまえる
+        preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+        if (preferenceSynchronizer == null)
+        {
+            preferenceSynchronizer = new PreferenceSynchronizer(this.propertyInterface, preferences, this);
+        }
+
+        // Preference を初期設定する
+        initializePreferences();
+
+        preferences.registerOnSharedPreferenceChangeListener(this);
+    }
+
+    /**
+     * Preferenceの初期化...
+     */
+    private void initializePreferences()
+    {
+        Map<String, ?> items = preferences.getAll();
+        SharedPreferences.Editor editor = preferences.edit();
+
+        if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE))
+        {
+            editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE_DEFAULT_VALUE);
+        }
+        if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.LIVE_VIEW_QUALITY))
+        {
+            editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.LIVE_VIEW_QUALITY, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.LIVE_VIEW_QUALITY_DEFAULT_VALUE);
+        }
+        if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL))
+        {
+            editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL_DEFAULT_VALUE);
+        }
+        if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.RAW))
+        {
+            editor.putBoolean(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.RAW, true);
+        }
+        if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL))
+        {
+            editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL_DEFAULT_VALUE);
+        }
+        editor.apply();
+    }
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey)
+    {
+        Log.v(TAG, "onCreatePreferences()");
+
+        //super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.preferences);
+
+        {
+            final HashMap<String, String> sizeTable = new HashMap<>();
+            sizeTable.put("QVGA", "(320x240)");
+            sizeTable.put("VGA", "(640x480)");
+            sizeTable.put("SVGA", "(800x600)");
+            sizeTable.put("XGA", "(1024x768)");
+            sizeTable.put("QUAD_VGA", "(1280x960)");
+
+            ListPreference liveViewQuality = (ListPreference) findPreference(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY);
+            liveViewQuality.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+                @Override
+                public boolean onPreferenceChange(Preference preference, Object newValue) {
+                    String key = (String) newValue;
+                    preference.setSummary(newValue + " " + sizeTable.get(key));
+                    return (true);
+                }
+            });
+            liveViewQuality.setSummary(liveViewQuality.getValue() + " " + sizeTable.get(liveViewQuality.getValue()));
+        }
+
+        findPreference("exit_application").setOnPreferenceClickListener(powerOffController);
+    }
+
+    /**
+     * ハードウェアのサマリ情報を取得し設定する
+     */
+    private void setHardwareSummary()
+    {
+        // レンズ状態
+        findPreference("lens_status").setSummary(hardwareStatusInterface.getLensMountStatus());
+
+        // メディア状態
+        findPreference("media_status").setSummary(hardwareStatusInterface.getMediaMountStatus());
+
+        // 焦点距離
+        String focalLength;
+        float minLength = hardwareStatusInterface.getMinimumFocalLength();
+        float maxLength = hardwareStatusInterface.getMaximumFocalLength();
+        float actualLength = hardwareStatusInterface.getActualFocalLength();
+        if (minLength == maxLength)
+        {
+            focalLength = String.format(Locale.ENGLISH, "%3.0fmm", actualLength);
+        }
+        else
+            {
+            focalLength = String.format(Locale.ENGLISH, "%3.0fmm - %3.0fmm (%3.0fmm)", minLength, maxLength, actualLength);
+        }
+        findPreference("focal_length").setSummary(focalLength);
+
+        // カメラのバージョン
+        try
+        {
+            Map<String, Object> hardwareInformation = hardwareStatusInterface.inquireHardwareInformation();
+            findPreference("camera_version").setSummary((String) hardwareInformation.get(OLYCamera.HARDWARE_INFORMATION_CAMERA_FIRMWARE_VERSION_KEY));
+
+            // 取得した一覧はログに出力する。)
+            Log.v(TAG, "- - - - - - - - - -");
+            for (Map.Entry<String, Object> entry : hardwareInformation.entrySet())
+            {
+                String value = (String) entry.getValue();
+                Log.v(TAG, entry.getKey() + " : " + value);
+            }
+            Log.v(TAG, "- - - - - - - - - -");
+        }
+        catch (Exception e)
+        {
+            findPreference("camera_version").setSummary("Unknown");
+        }
+    }
+
+    private void setCameraProperty(String name, String value)
+    {
+        try
+        {
+            String propertyValue = "<" + name + "/" + value + ">";
+            Log.v(TAG, "setCameraProperty() : " + propertyValue);
+            propertyInterface.setCameraPropertyValue(name, propertyValue);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void onResume()
+    {
+        super.onResume();
+        Log.v(TAG, "onResume() Start");
+
+        // 撮影モードかどうかを確認して、撮影モードではなかったら撮影モードに切り替える
+        if ((changeRunModeExecutor != null) && (!changeRunModeExecutor.isRecordingMode()))
+        {
+            // Runモードを切り替える。(でも切り替えると、設定がクリアされてしまう...。
+            changeRunModeExecutor.changeRunMode(true);
+        }
+        synchronizeCameraProperties(true);
+        Log.v(TAG, "onResume() End");
+
+    }
+
+    @Override
+    public void onPause()
+    {
+        super.onPause();
+        Log.v(TAG, "onPause() Start");
+
+        // Preference変更のリスナを解除
+        preferences.unregisterOnSharedPreferenceChangeListener(this);
+
+        Log.v(TAG, "onPause() End");
+    }
+
+    /**
+     * カメラプロパティとPreferenceとの同期処理を実行
+     */
+    private void synchronizeCameraProperties(boolean isPropertyLoad)
+    {
+        // 実行中ダイアログを取得する
+        busyDialog = new ProgressDialog(getActivity());
+        busyDialog.setTitle(getString(R.string.dialog_title_loading_properties));
+        busyDialog.setMessage(getString(R.string.dialog_message_loading_properties));
+        busyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+        busyDialog.setCancelable(false);
+        busyDialog.show();
+
+        // データ読み込み処理(別スレッドで実行)
+        if (isPropertyLoad)
+        {
+            new Thread(preferenceSynchronizer).start();
+        }
+    }
+
+    /**
+     * Preferenceが更新された時に呼び出される処理
+     *
+     * @param sharedPreferences sharedPreferences
+     * @param key               変更されたキー
+     */
+    @Override
+    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
+    {
+        Log.v(TAG, "onSharedPreferenceChanged() : " + key);
+        String propertyValue;
+        boolean value;
+        if (key != null)
+        {
+            switch (key)
+            {
+                case IPreferencePropertyAccessor.RAW:
+                    value = preferences.getBoolean(key, true);
+                    setBooleanPreference(key, key, value);
+                    propertyValue = (value) ? "ON" : "OFF";
+                    setCameraProperty(IOlyCameraProperty.RAW, propertyValue);
+                    break;
+
+                case IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA:
+                    value = preferences.getBoolean(key, true);
+                    Log.v(TAG, " " + key + " , " + value);
+                    break;
+
+                default:
+                    String strValue = preferences.getString(key, "");
+                    setListPreference(key, key, strValue);
+                    String propertyKey = convertKeyFromPreferenceToCameraPropertyKey(key);
+                    if (propertyKey != null)
+                    {
+                        setCameraProperty(propertyKey, strValue);
+                    }
+                    break;
+            }
+        }
+    }
+
+    /**
+     * ListPreference の表示データを設定
+     *
+     * @param pref_key     Preference(表示)のキー
+     * @param key          Preference(データ)のキー
+     * @param defaultValue Preferenceのデフォルト値
+     */
+    private void setListPreference(String pref_key, String key, String defaultValue)
+    {
+        ListPreference pref;
+        pref = (ListPreference) findPreference(pref_key);
+        String value = preferences.getString(key, defaultValue);
+        if (pref != null)
+        {
+            pref.setValue(value);
+            pref.setSummary(value);
+        }
+    }
+
+    /**
+     * BooleanPreference の表示データを設定
+     *
+     * @param pref_key     Preference(表示)のキー
+     * @param key          Preference(データ)のキー
+     * @param defaultValue Preferenceのデフォルト値
+     */
+    private void setBooleanPreference(String pref_key, String key, boolean defaultValue)
+    {
+        CheckBoxPreference pref = (CheckBoxPreference) findPreference(pref_key);
+        if (pref != null)
+        {
+            boolean value = preferences.getBoolean(key, defaultValue);
+            pref.setChecked(value);
+        }
+    }
+
+    /**
+     *
+     *
+     */
+    private String convertKeyFromPreferenceToCameraPropertyKey(String key)
+    {
+        String target = null;
+        if (key == null)
+        {
+            return (null);
+        }
+        switch (key)
+        {
+            case IPreferencePropertyAccessor.TAKE_MODE:
+                target = IOlyCameraProperty.TAKE_MODE;
+                break;
+
+            case IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL:
+                target = IOlyCameraProperty.SOUND_VOLUME_LEVEL;
+                break;
+
+            default:
+                // target == null
+                break;
+        }
+        return (target);
+    }
+
+    /**
+     * カメラプロパティの同期処理終了通知
+     */
+    @Override
+    public void synchronizedProperty()
+    {
+        Activity activity = getActivity();
+        if (activity == null)
+        {
+            try
+            {
+                busyDialog.dismiss();
+                busyDialog = null;
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+            return;
+        }
+        activity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    // Preferenceの画面に反映させる
+                    setListPreference(IPreferencePropertyAccessor.TAKE_MODE, IPreferencePropertyAccessor.TAKE_MODE, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE_DEFAULT_VALUE);
+                    setListPreference(IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL_DEFAULT_VALUE);
+                    setBooleanPreference(IPreferencePropertyAccessor.RAW, IPreferencePropertyAccessor.RAW, true);
+
+                    // カメラキットのバージョン
+                    findPreference(IPreferencePropertyAccessor.CAMERAKIT_VERSION).setSummary(OLYCamera.getVersion());
+                    if (hardwareStatusInterface != null)
+                    {
+                        // その他のハードウェア情報の情報設定
+                        setHardwareSummary();
+                    }
+
+                    // 実行中ダイアログを消す
+                    busyDialog.dismiss();
+                    busyDialog = null;
+                } catch (Exception e)
+                {
+                    e.printStackTrace();
+                }
+            }
+        });
+    }
+
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/preference/PreferenceSynchronizer.java b/app/src/main/java/net/osdn/gokigen/a01d/preference/PreferenceSynchronizer.java
new file mode 100644 (file)
index 0000000..1832877
--- /dev/null
@@ -0,0 +1,62 @@
+package net.osdn.gokigen.a01d.preference;
+
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraProperty;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.CameraPropertyUtilities;
+
+class PreferenceSynchronizer implements Runnable
+{
+    private final String TAG = toString();
+    private final IOlyCameraPropertyProvider propertyInterface;
+    private final SharedPreferences preference;
+    private final IPropertySynchronizeCallback callback;
+
+    PreferenceSynchronizer(IOlyCameraPropertyProvider propertyInterface, SharedPreferences preference, IPropertySynchronizeCallback callback)
+    {
+        this.propertyInterface = propertyInterface;
+        this.preference = preference;
+        this.callback = callback;
+    }
+
+    private String getPropertyValue(String key)
+    {
+        String propertyValue;
+        try
+        {
+            String value = propertyInterface.getCameraPropertyValue(key);
+            propertyValue = CameraPropertyUtilities.getPropertyValue(value);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            propertyValue = "";
+        }
+        Log.v(TAG, "getPropertyValue(" + key + ") : " + propertyValue);
+        return (propertyValue);
+    }
+
+    @Override
+    public void run()
+    {
+        Log.v(TAG, "run()");
+        SharedPreferences.Editor editor = preference.edit();
+        editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE, getPropertyValue(IOlyCameraProperty.TAKE_MODE));
+        editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, getPropertyValue(IOlyCameraProperty.SOUND_VOLUME_LEVEL));
+
+        boolean value = getPropertyValue(IOlyCameraProperty.RAW).equals("ON");
+        editor.putBoolean(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.RAW, value);
+        editor.apply();
+        if (callback != null)
+        {
+            callback.synchronizedProperty();
+        }
+    }
+
+    interface IPropertySynchronizeCallback
+    {
+        void synchronizedProperty();
+    }
+}
diff --git a/app/src/main/res/color/setting_text_color.xml b/app/src/main/res/color/setting_text_color.xml
new file mode 100644 (file)
index 0000000..76fcb3a
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item
+        android:state_enabled="false"
+        android:color="@android:color/darker_gray" />
+    <item
+        android:state_selected="true"
+        android:color="@android:color/holo_blue_light" />
+    <item
+        android:state_pressed="true"
+        android:color="@android:color/holo_blue_light" />
+    <item
+        android:color="@android:color/black" />
+        
+</selector>
diff --git a/app/src/main/res/drawable/a01d_default.jpg b/app/src/main/res/drawable/a01d_default.jpg
new file mode 100644 (file)
index 0000000..bac1435
Binary files /dev/null and b/app/src/main/res/drawable/a01d_default.jpg differ
diff --git a/app/src/main/res/drawable/a01d_ini.jpg b/app/src/main/res/drawable/a01d_ini.jpg
new file mode 100644 (file)
index 0000000..fa5c365
Binary files /dev/null and b/app/src/main/res/drawable/a01d_ini.jpg differ
diff --git a/app/src/main/res/drawable/ic_block_black_24dp.xml b/app/src/main/res/drawable/ic_block_black_24dp.xml
new file mode 100644 (file)
index 0000000..00770b6
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_build_black_24dp.xml b/app/src/main/res/drawable/ic_build_black_24dp.xml
new file mode 100644 (file)
index 0000000..061392d
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_camera_roll_black_24dp.xml b/app/src/main/res/drawable/ic_camera_roll_black_24dp.xml
new file mode 100644 (file)
index 0000000..f2292f5
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M14,5c0,-1.1 -0.9,-2 -2,-2h-1L11,2c0,-0.55 -0.45,-1 -1,-1L6,1c-0.55,0 -1,0.45 -1,1v1L4,3c-1.1,0 -2,0.9 -2,2v15c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2h8L22,5h-8zM12,18h-2v-2h2v2zM12,9h-2L10,7h2v2zM16,18h-2v-2h2v2zM16,9h-2L14,7h2v2zM20,18h-2v-2h2v2zM20,9h-2L18,7h2v2z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_check_box_black_24dp.xml b/app/src/main/res/drawable/ic_check_box_black_24dp.xml
new file mode 100644 (file)
index 0000000..df2108a
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_check_box_outline_blank_black_24dp.xml b/app/src/main/res/drawable/ic_check_box_outline_blank_black_24dp.xml
new file mode 100644 (file)
index 0000000..7efd89a
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_cloud_done_black_24dp.xml b/app/src/main/res/drawable/ic_cloud_done_black_24dp.xml
new file mode 100644 (file)
index 0000000..f270e33
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM10,17l-3.5,-3.5 1.41,-1.41L10,14.17 15.18,9l1.41,1.41L10,17z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_cloud_off_black_24dp.xml b/app/src/main/res/drawable/ic_cloud_off_black_24dp.xml
new file mode 100644 (file)
index 0000000..f33a569
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4c-1.48,0 -2.85,0.43 -4.01,1.17l1.46,1.46C10.21,6.23 11.08,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3 0,1.13 -0.64,2.11 -1.56,2.62l1.45,1.45C23.16,18.16 24,16.68 24,15c0,-2.64 -2.05,-4.78 -4.65,-4.96zM3,5.27l2.75,2.74C2.56,8.15 0,10.77 0,14c0,3.31 2.69,6 6,6h11.73l2,2L21,20.73 4.27,4 3,5.27zM7.73,10l8,8H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h1.73z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_cloud_queue_black_24dp.xml b/app/src/main/res/drawable/ic_cloud_queue_black_24dp.xml
new file mode 100644 (file)
index 0000000..f95403b
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h0.71C7.37,7.69 9.48,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3s-1.34,3 -3,3z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_grid_off_black_24dp.xml b/app/src/main/res/drawable/ic_grid_off_black_24dp.xml
new file mode 100644 (file)
index 0000000..c79d517
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M8,4v1.45l2,2L10,4h4v4h-3.45l2,2L14,10v1.45l2,2L16,10h4v4h-3.45l2,2L20,16v1.45l2,2L22,4c0,-1.1 -0.9,-2 -2,-2L4.55,2l2,2L8,4zM16,4h4v4h-4L16,4zM1.27,1.27L0,2.55l2,2L2,20c0,1.1 0.9,2 2,2h15.46l2,2 1.27,-1.27L1.27,1.27zM10,12.55L11.45,14L10,14v-1.45zM4,6.55L5.45,8L4,8L4,6.55zM8,20L4,20v-4h4v4zM8,14L4,14v-4h3.45l0.55,0.55L8,14zM14,20h-4v-4h3.45l0.55,0.54L14,20zM16,20v-1.46L17.46,20L16,20z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_grid_on_black_24dp.xml b/app/src/main/res/drawable/ic_grid_on_black_24dp.xml
new file mode 100644 (file)
index 0000000..3bae6d3
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M20,2L4,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM8,20L4,20v-4h4v4zM8,14L4,14v-4h4v4zM8,8L4,8L4,4h4v4zM14,20h-4v-4h4v4zM14,14h-4v-4h4v4zM14,8h-4L10,4h4v4zM20,20h-4v-4h4v4zM20,14h-4v-4h4v4zM20,8h-4L16,4h4v4z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_indeterminate_check_box_black_24dp.xml b/app/src/main/res/drawable/ic_indeterminate_check_box_black_24dp.xml
new file mode 100644 (file)
index 0000000..bddf2ab
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM17,13L7,13v-2h10v2z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_linked_camera_black_24dp.xml b/app/src/main/res/drawable/ic_linked_camera_black_24dp.xml
new file mode 100644 (file)
index 0000000..84ed351
--- /dev/null
@@ -0,0 +1,7 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M12,14m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
+    <path android:fillColor="#FF000000" android:pathData="M16,3.33c2.58,0 4.67,2.09 4.67,4.67H22c0,-3.31 -2.69,-6 -6,-6v1.33M16,6c1.11,0 2,0.89 2,2h1.33c0,-1.84 -1.49,-3.33 -3.33,-3.33V6"/>
+    <path android:fillColor="#FF000000" android:pathData="M17,9c0,-1.11 -0.89,-2 -2,-2L15,4L9,4L7.17,6L4,6c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,9h-5zM12,19c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_mode_edit_black_24dp.xml b/app/src/main/res/drawable/ic_mode_edit_black_24dp.xml
new file mode 100644 (file)
index 0000000..084e01e
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_photo_camera_black_24dp.xml b/app/src/main/res/drawable/ic_photo_camera_black_24dp.xml
new file mode 100644 (file)
index 0000000..bd02368
--- /dev/null
@@ -0,0 +1,6 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
+    <path android:fillColor="#FF000000" android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_refresh_black_24dp.xml b/app/src/main/res/drawable/ic_refresh_black_24dp.xml
new file mode 100644 (file)
index 0000000..1c1c80a
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_restore_page_black_24dp.xml b/app/src/main/res/drawable/ic_restore_page_black_24dp.xml
new file mode 100644 (file)
index 0000000..3163385
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M14,2L6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6zM12,18c-2.05,0 -3.81,-1.24 -4.58,-3h1.71c0.63,0.9 1.68,1.5 2.87,1.5 1.93,0 3.5,-1.57 3.5,-3.5S13.93,9.5 12,9.5c-1.35,0 -2.52,0.78 -3.1,1.9l1.6,1.6h-4L6.5,9l1.3,1.3C8.69,8.92 10.23,8 12,8c2.76,0 5,2.24 5,5s-2.24,5 -5,5z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_save_black_24dp.xml b/app/src/main/res/drawable/ic_save_black_24dp.xml
new file mode 100644 (file)
index 0000000..c5200f7
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_settings_black_24dp.xml b/app/src/main/res/drawable/ic_settings_black_24dp.xml
new file mode 100644 (file)
index 0000000..2cd9cde
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_web_asset_black_24dp.xml b/app/src/main/res/drawable/ic_web_asset_black_24dp.xml
new file mode 100644 (file)
index 0000000..b239036
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#010101" android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.89,-2 -2,-2zM19,18L5,18L5,8h14v10z"/>
+</vector>
diff --git a/app/src/main/res/layout-land/activity_a01d_main.xml b/app/src/main/res/layout-land/activity_a01d_main.xml
new file mode 100644 (file)
index 0000000..f922219
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+    tools:context="net.osdn.gokigen.a01d.A01dMain">
+
+    <FrameLayout
+        android:id="@+id/fragment1"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentTop="true"
+        />
+
+<!--
+        <FrameLayout
+            android:id="@+id/fragment2"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+
+        <FrameLayout
+            android:id="@+id/fragment1"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="3"
+            />
+
+        <FrameLayout
+            android:id="@+id/fragment3"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+    -->
+</RelativeLayout>
diff --git a/app/src/main/res/layout-land/fragmant_camera_property.xml b/app/src/main/res/layout-land/fragmant_camera_property.xml
new file mode 100644 (file)
index 0000000..57b3b01
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_alignParentTop="true"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true">
+
+    <LinearLayout
+        android:id="@+id/propertyInformationPanelLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="14dp"
+        android:background="@color/background_translucent_dark" >
+
+        <TextView
+            android:id="@+id/propertyInformationMessageTextView"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="start"
+            android:clickable="true"
+            android:text="@string/blank"
+            android:textColor="@color/background_dark"
+            android:textSize="14sp" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/propertyConfigPanelLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="24dp"
+        android:background="@color/background_translucent_dark" >
+
+        <ImageView
+            android:id="@+id/propertySettings_save"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:layout_gravity="end"
+            android:visibility="invisible"
+            android:clickable="true"
+            android:scaleType="center"
+            android:contentDescription="@string/configuration"
+            android:src="@drawable/ic_save_black_24dp" />
+
+        <ImageView
+            android:id="@+id/propertySettings_refresh"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:layout_gravity="end"
+            android:visibility="invisible"
+            android:clickable="true"
+            android:scaleType="center"
+            android:contentDescription="@string/configuration"
+            android:src="@drawable/ic_refresh_black_24dp" />
+
+        <ImageView
+            android:id="@+id/propertySettings_restore"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:layout_gravity="end"
+            android:visibility="visible"
+            android:clickable="true"
+            android:scaleType="center"
+            android:contentDescription="@string/restore"
+            android:src="@drawable/ic_restore_page_black_24dp" />
+
+    </LinearLayout>
+
+    <ListView android:id="@+id/CameraPropertyListView"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+    </ListView>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout-land/fragment_live_view.xml b/app/src/main/res/layout-land/fragment_live_view.xml
new file mode 100644 (file)
index 0000000..64871dd
--- /dev/null
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_alignParentTop="true"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true">
+
+    <LinearLayout
+        android:id="@+id/consolePanelLayout"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:background="@color/background_translucent_dark"
+        android:orientation="horizontal">
+
+        <view
+            android:id="@+id/consoleImageView1"
+            class="net.osdn.gokigen.a01d.liveview.ScalableImageViewPanel"
+            android:layout_width="0dip"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:clickable="true"
+            android:contentDescription="@string/favorite"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:visibility="visible" />
+
+        <view
+            class="net.osdn.gokigen.a01d.liveview.CameraLiveImageView"
+            android:id="@+id/cameraLiveImageView"
+            android:layout_width="0dip"
+            android:layout_height="fill_parent"
+            android:layout_weight="5"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:visibility="visible"/>
+
+        <view
+            android:id="@+id/consoleImageView2"
+            class="net.osdn.gokigen.a01d.liveview.ScalableImageViewPanel"
+            android:layout_width="0dip"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:clickable="true"
+            android:contentDescription="@string/favorite"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:visibility="visible" />
+    </LinearLayout>
+
+    <RelativeLayout
+        android:id="@+id/informationPanelLayout"
+        android:layout_width="fill_parent"
+        android:layout_height="14pt"
+        android:background="@color/background_translucent_dark"
+        android:orientation="horizontal">
+
+        <ImageButton
+            android:id="@+id/show_preference_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clickable="true"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
+            android:contentDescription="@string/preferences"
+            android:src="@drawable/ic_settings_black_24dp"
+            android:visibility="visible" />
+
+        <ImageButton
+            android:id="@+id/connect_disconnect_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clickable="true"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:contentDescription="@string/grid"
+            android:src="@drawable/ic_cloud_off_black_24dp"
+            android:visibility="visible" />
+
+        <TextView
+            android:id="@+id/informationMessageTextView"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_toRightOf="@id/connect_disconnect_button"
+            android:layout_toEndOf="@id/connect_disconnect_button"
+            android:clickable="true"
+            android:gravity="start"
+            android:text="@string/information"
+            android:textColor="@color/background_translucent_dark"
+            android:textSize="12pt" />
+
+        <ImageButton
+            android:id="@+id/camera_property_settings_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clickable="true"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:layout_alignTop="@id/show_preference_button"
+            android:layout_toLeftOf="@id/show_preference_button"
+            android:layout_toStartOf="@id/show_preference_button"
+            android:contentDescription="@string/blank"
+            android:src="@drawable/ic_build_black_24dp"
+            android:visibility="visible" />
+
+
+        <ImageButton
+            android:id="@+id/show_hide_grid_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clickable="true"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:layout_alignTop="@id/show_preference_button"
+            android:layout_toLeftOf="@id/camera_property_settings_button"
+            android:layout_toStartOf="@id/camera_property_settings_button"
+            android:contentDescription="@string/grid"
+            android:src="@drawable/ic_grid_on_black_24dp"
+            android:visibility="visible" />
+
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout-land/listarrayitems.xml b/app/src/main/res/layout-land/listarrayitems.xml
new file mode 100644 (file)
index 0000000..709965b
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    >
+    <ImageView
+        android:id="@+id/ObjectStyleIcons"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:scaleType="fitCenter"
+        android:tag="icon"
+        android:src="@drawable/ic_photo_camera_black_24dp"
+        android:contentDescription="@string/icon"
+        android:layout_gravity="center_vertical"
+        android:maxHeight="18dp"
+        android:minWidth="18dp">
+    </ImageView>
+    <TextView
+        android:textSize="9pt"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/ObjectDataTitle"
+        android:tag="title"
+        android:maxWidth="130dp"
+        android:minWidth="130dp"
+        android:layout_gravity="start">
+    </TextView>
+    <TextView
+        android:textSize="6pt"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/ObjectDataDetail"
+        android:tag="value"
+        android:linksClickable="true"
+        android:maxWidth="100dp"
+        android:minWidth="100dp"
+        android:layout_gravity="center_vertical">
+    </TextView>
+    <TextView
+        android:textSize="4pt"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/ObjectDataValue"
+        android:tag="name"
+        android:autoLink="all"
+        android:linksClickable="true"
+        android:layout_gravity="center_vertical">
+    </TextView>
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_a01d_main.xml b/app/src/main/res/layout/activity_a01d_main.xml
new file mode 100644 (file)
index 0000000..bc8ae2e
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    tools:context="net.osdn.gokigen.a01d.A01dMain">
+
+    <FrameLayout
+        android:id="@+id/fragment1"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentTop="true"
+        />
+
+<!--
+    <FrameLayout
+        android:id="@+id/fragment1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="3"
+        />
+
+    <FrameLayout
+        android:id="@+id/fragment2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1" />
+
+    <FrameLayout
+        android:id="@+id/fragment3"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        />
+-->
+</RelativeLayout>
diff --git a/app/src/main/res/layout/fragmant_camera_property.xml b/app/src/main/res/layout/fragmant_camera_property.xml
new file mode 100644 (file)
index 0000000..8a5ddc4
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_alignParentTop="true"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true">
+
+    <LinearLayout
+        android:id="@+id/propertyInformationPanelLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="14dp"
+        android:background="@color/background_translucent_dark" >
+
+        <TextView
+            android:id="@+id/propertyInformationMessageTextView"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="start"
+            android:clickable="true"
+            android:text="@string/blank"
+            android:textColor="@color/background_dark"
+            android:textSize="14sp" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/propertyConfigPanelLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="24dp"
+        android:background="@color/background_translucent_dark" >
+
+        <ImageView
+            android:id="@+id/propertySettings_save"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:layout_gravity="end"
+            android:visibility="invisible"
+            android:clickable="true"
+            android:scaleType="center"
+            android:contentDescription="@string/configuration"
+            android:src="@drawable/ic_save_black_24dp" />
+
+        <ImageView
+            android:id="@+id/propertySettings_refresh"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:layout_gravity="end"
+            android:visibility="invisible"
+            android:clickable="true"
+            android:scaleType="center"
+            android:contentDescription="@string/configuration"
+            android:src="@drawable/ic_refresh_black_24dp" />
+
+        <ImageView
+            android:id="@+id/propertySettings_restore"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:layout_gravity="end"
+            android:visibility="visible"
+            android:clickable="true"
+            android:scaleType="center"
+            android:contentDescription="@string/restore"
+            android:src="@drawable/ic_restore_page_black_24dp" />
+
+    </LinearLayout>
+
+    <ListView android:id="@+id/CameraPropertyListView"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+    </ListView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_live_view.xml b/app/src/main/res/layout/fragment_live_view.xml
new file mode 100644 (file)
index 0000000..f2d1db8
--- /dev/null
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_alignParentTop="true"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true">
+
+    <view
+        android:id="@+id/cameraLiveImageView"
+        class="net.osdn.gokigen.a01d.liveview.CameraLiveImageView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:gravity="center"
+        android:scaleType="fitCenter"
+        android:visibility="visible" />
+
+    <LinearLayout
+        android:id="@+id/consolePanelLayout"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:background="@color/background_translucent_dark"
+        android:orientation="horizontal">
+
+        <view
+            android:id="@+id/consoleImageView1"
+            class="net.osdn.gokigen.a01d.liveview.ScalableImageViewPanel"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:clickable="true"
+            android:contentDescription="@string/favorite"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:visibility="visible" />
+
+        <view
+            android:id="@+id/consoleImageView2"
+            class="net.osdn.gokigen.a01d.liveview.ScalableImageViewPanel"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:clickable="true"
+            android:contentDescription="@string/favorite"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:visibility="visible" />
+    </LinearLayout>
+
+    <RelativeLayout
+        android:id="@+id/informationPanelLayout"
+        android:layout_width="fill_parent"
+        android:layout_height="14pt"
+        android:background="@color/background_translucent_dark"
+        android:orientation="horizontal">
+
+        <ImageButton
+            android:id="@+id/show_preference_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clickable="true"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
+            android:contentDescription="@string/preferences"
+            android:src="@drawable/ic_settings_black_24dp"
+            android:visibility="visible" />
+
+
+
+        <ImageButton
+            android:id="@+id/connect_disconnect_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clickable="true"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:contentDescription="@string/grid"
+            android:src="@drawable/ic_cloud_off_black_24dp"
+            android:visibility="visible" />
+
+
+        <TextView
+            android:id="@+id/informationMessageTextView"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_toRightOf="@id/connect_disconnect_button"
+            android:layout_toEndOf="@id/connect_disconnect_button"
+            android:clickable="true"
+            android:gravity="start"
+            android:text="@string/information"
+            android:textColor="@color/background_translucent_dark"
+            android:textSize="12pt" />
+
+        <ImageButton
+            android:id="@+id/camera_property_settings_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clickable="true"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:layout_alignTop="@id/show_preference_button"
+            android:layout_toLeftOf="@id/show_preference_button"
+            android:layout_toStartOf="@id/show_preference_button"
+            android:contentDescription="@string/blank"
+            android:src="@drawable/ic_build_black_24dp"
+            android:visibility="visible" />
+
+        <ImageButton
+            android:id="@+id/show_hide_grid_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clickable="true"
+            android:gravity="center"
+            android:scaleType="fitCenter"
+            android:layout_alignTop="@id/show_preference_button"
+            android:layout_toLeftOf="@id/camera_property_settings_button"
+            android:layout_toStartOf="@id/camera_property_settings_button"
+            android:contentDescription="@string/grid"
+            android:src="@drawable/ic_grid_on_black_24dp"
+            android:visibility="visible" />
+    </RelativeLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/listarrayitems.xml b/app/src/main/res/layout/listarrayitems.xml
new file mode 100644 (file)
index 0000000..709965b
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    >
+    <ImageView
+        android:id="@+id/ObjectStyleIcons"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:scaleType="fitCenter"
+        android:tag="icon"
+        android:src="@drawable/ic_photo_camera_black_24dp"
+        android:contentDescription="@string/icon"
+        android:layout_gravity="center_vertical"
+        android:maxHeight="18dp"
+        android:minWidth="18dp">
+    </ImageView>
+    <TextView
+        android:textSize="9pt"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/ObjectDataTitle"
+        android:tag="title"
+        android:maxWidth="130dp"
+        android:minWidth="130dp"
+        android:layout_gravity="start">
+    </TextView>
+    <TextView
+        android:textSize="6pt"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/ObjectDataDetail"
+        android:tag="value"
+        android:linksClickable="true"
+        android:maxWidth="100dp"
+        android:minWidth="100dp"
+        android:layout_gravity="center_vertical">
+    </TextView>
+    <TextView
+        android:textSize="4pt"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/ObjectDataValue"
+        android:tag="name"
+        android:autoLink="all"
+        android:linksClickable="true"
+        android:layout_gravity="center_vertical">
+    </TextView>
+</LinearLayout>
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..cde69bc
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..9a078e3
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..c133a0c
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..efc028a
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..bfa42f0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..3af2608
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..324e72c
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..9bec2e6
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..aee44e1
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..34947cd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values-ja/arrays.xml b/app/src/main/res/values-ja/arrays.xml
new file mode 100644 (file)
index 0000000..8733cbe
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string-array name="take_mode">
+        <item >P</item>
+        <item >iAuto</item>
+        <item >A</item>
+        <item >S</item>
+        <item >M</item>
+        <item>Movie</item>
+    </string-array>
+    <string-array name="take_mode_value">
+        <item >P</item>
+        <item >iAuto</item>
+        <item >A</item>
+        <item >S</item>
+        <item >M</item>
+        <item >movie</item>
+    </string-array>
+
+    <string-array name="sound_volume_level">
+        <item >OFF</item>
+        <item >1</item>
+        <item >2</item>
+        <item >3</item>
+        <item >4</item>
+        <item >5</item>
+    </string-array>
+
+    <string-array name="sound_volume_level_value">
+        <item >OFF</item>
+        <item >1</item>
+        <item >2</item>
+        <item >3</item>
+        <item >4</item>
+        <item >5</item>
+    </string-array>
+
+    <string-array name="live_view_quality">
+        <item >QVGA (320x240)</item>
+        <item >VGA (640x480)</item>
+        <item >SVGA (800x600)</item>
+        <item >XGA (1024x768)</item>
+        <item >QUAD VGA (1280x960)</item>
+    </string-array>
+    <string-array name="live_view_quality_value">
+        <item >QVGA</item>
+        <item >VGA</item>
+        <item >SVGA</item>
+        <item >XGA</item>
+        <item >QUAD_VGA</item>
+    </string-array>
+</resources>
diff --git a/app/src/main/res/values-ja/colors.xml b/app/src/main/res/values-ja/colors.xml
new file mode 100644 (file)
index 0000000..03c8f28
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+    <color name="background_dark">#555555</color>
+    <color name="background_translucent_dark">#AA555555</color>
+    <color name="background_translucent_white">#AAFFFFFF</color>
+</resources>
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
new file mode 100644 (file)
index 0000000..4f4123d
--- /dev/null
@@ -0,0 +1,48 @@
+<resources>
+    <string name="app_name">A01d</string>
+    <string name="blank"> </string>
+
+    <string name="configuration">Settings</string>
+    <string name="restore">Restore</string>
+    <string name="icon">icon</string>
+
+    <string name="dialog_positive_execute">OK</string>
+    <string name="dialog_negative_cancel">Cancel</string>
+
+    <string name="dialog_title_confirmation">確認</string>
+    <string name="dialog_message_restore_camera_property">カメラプロパティを画面オープン時の状態に戻します。</string>
+    <string name="dialog_title_loading_properties">カメラプロパティ読出中</string>
+    <string name="dialog_message_loading_properties">しばらくお待ち下さい…</string>
+
+    <string name="pref_cat_camera">カメラ設定</string>
+    <string name="pref_take_mode">撮影モード</string>
+    <string name="pref_camera_sound_volume">シャッター音</string>
+    <string name="pref_take_raw">RAW撮影</string>
+
+    <string name="pref_cat_application_control">アプリ制御</string>
+    <string name="pref_exit_power_off">アプリ終了(とカメラOFF)</string>
+
+    <string name="pref_cat_initialize">起動時設定</string>
+    <string name="pref_auto_connect_camera">カメラに自動接続</string>
+    <string name="dialog_message_power_off">カメラの電源を切り、アプリケーションを終了します。</string>
+
+
+    <string name="pref_cat_live_view">ライブビュー設定</string>
+    <string name="pref_live_view_quality">ライブビュー品質</string>
+
+    <string name="pref_cat_info">カメラ情報</string>
+    <string name="pref_focal_length">焦点距離</string>
+    <string name="pref_lens_status">レンズ状態</string>
+    <string name="pref_media_status">SDカード状態</string>
+    <string name="pref_camera_version">Camera Version</string>
+    <string name="pref_camerakit_version">Camera kit Version</string>
+
+    <string name="pref_cat_gokigen">GOKIGEN Project(現在、直接開けません)</string>
+    <string name="pref_instruction_manual">操作説明</string>
+    <string name="pref_privacy_policy">プライバシーポリシー</string>
+
+    <string name="information">ハロー!</string>
+    <string name="favorite">お気に入り</string>
+    <string name="preferences">Preferences</string>
+    <string name="grid">Grid</string>
+</resources>
diff --git a/app/src/main/res/values-ja/styles.xml b/app/src/main/res/values-ja/styles.xml
new file mode 100644 (file)
index 0000000..676cfe7
--- /dev/null
@@ -0,0 +1,12 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+        <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
+    </style>
+
+</resources>
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
new file mode 100644 (file)
index 0000000..8733cbe
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string-array name="take_mode">
+        <item >P</item>
+        <item >iAuto</item>
+        <item >A</item>
+        <item >S</item>
+        <item >M</item>
+        <item>Movie</item>
+    </string-array>
+    <string-array name="take_mode_value">
+        <item >P</item>
+        <item >iAuto</item>
+        <item >A</item>
+        <item >S</item>
+        <item >M</item>
+        <item >movie</item>
+    </string-array>
+
+    <string-array name="sound_volume_level">
+        <item >OFF</item>
+        <item >1</item>
+        <item >2</item>
+        <item >3</item>
+        <item >4</item>
+        <item >5</item>
+    </string-array>
+
+    <string-array name="sound_volume_level_value">
+        <item >OFF</item>
+        <item >1</item>
+        <item >2</item>
+        <item >3</item>
+        <item >4</item>
+        <item >5</item>
+    </string-array>
+
+    <string-array name="live_view_quality">
+        <item >QVGA (320x240)</item>
+        <item >VGA (640x480)</item>
+        <item >SVGA (800x600)</item>
+        <item >XGA (1024x768)</item>
+        <item >QUAD VGA (1280x960)</item>
+    </string-array>
+    <string-array name="live_view_quality_value">
+        <item >QVGA</item>
+        <item >VGA</item>
+        <item >SVGA</item>
+        <item >XGA</item>
+        <item >QUAD_VGA</item>
+    </string-array>
+</resources>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644 (file)
index 0000000..03c8f28
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+    <color name="background_dark">#555555</color>
+    <color name="background_translucent_dark">#AA555555</color>
+    <color name="background_translucent_white">#AAFFFFFF</color>
+</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644 (file)
index 0000000..7d569f7
--- /dev/null
@@ -0,0 +1,65 @@
+<resources>
+    <string name="app_name">A01d</string>
+    <string name="blank"> </string>
+
+    <string name="configuration">Settings</string>
+    <string name="restore">Restore</string>
+    <string name="icon">icon</string>
+
+    <string name="dialog_positive_execute">OK</string>
+    <string name="dialog_negative_cancel">Cancel</string>
+
+    <string name="dialog_title_confirmation">Confirmation</string>
+    <string name="dialog_message_restore_camera_property">Restore Camera Property</string>
+    <string name="dialog_title_loading_properties">Loading Camera Properties</string>
+    <string name="dialog_message_loading_properties">Please wait&#8230;</string>
+
+    <string name="pref_cat_camera">Camera</string>
+    <string name="pref_take_mode">Take Mode</string>
+    <string name="pref_camera_sound_volume">Shutter Sound</string>
+    <string name="pref_take_raw">Take Raw</string>
+
+    <string name="pref_cat_application_control">App. Control</string>
+    <string name="pref_exit_power_off">Exit Application(and Camera OFF)</string>
+
+
+    <string name="pref_cat_initialize">App. Startup</string>
+    <string name="pref_auto_connect_camera">Auto Connect To Camera</string>
+    <string name="dialog_message_power_off">Power Off</string>
+
+    <string name="pref_cat_live_view">Live View Settings</string>
+    <string name="pref_live_view_quality">Live View Quality</string>
+
+    <string name="pref_cat_info">Information</string>
+    <string name="pref_focal_length">Focal Length</string>
+    <string name="pref_lens_status">Lens Status</string>
+    <string name="pref_media_status">SD Card Status</string>
+    <string name="pref_camera_version">Camera Version</string>
+    <string name="pref_camerakit_version">Camera kit Version</string>
+
+    <string name="pref_cat_gokigen">GOKIGEN(Currently not open directly)</string>
+    <string name="pref_instruction_manual">A01d Instructions</string>
+    <string name="pref_privacy_policy">Privacy Policy</string>
+
+    <string name="information">Hello!</string>
+    <string name="favorite">Favorite</string>
+    <string name="preferences">Preferences</string>
+    <string name="grid">Grid</string>
+
+    <string name="network_connection_timeout">Connection time out</string>
+    <string name="dialog_title_connect_failed">Connect failed</string>
+    <string name="dialog_title_button_retry">Retry</string>
+    <string name="dialog_title_button_network_settings">WiFi Settings</string>
+
+
+    <string name="connect_start">start</string>
+    <string name="connect_check_wifi">check WIFI</string>
+    <string name="connect_connect">connecting</string>
+    <string name="connect_connected">connected</string>
+    <string name="connect_change_run_mode">changeRunMode</string>
+    <string name="connect_restore_camera_settings">restoreCameraSettings</string>
+
+    <string name="fatal_cannot_use_camera">The CameraKit SDK can not work because the running mode of camera is UNKNOWN.   So please long press the power button of camera more than 8 seconds. (This is the camera reset operation.) After that turn on the camera power again.</string>
+    <string name="camera_reset_required">The camera reset operation is required.</string>
+    <string name="camera_disconnected">Disconnected</string>
+</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644 (file)
index 0000000..676cfe7
--- /dev/null
@@ -0,0 +1,12 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+        <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
+    </style>
+
+</resources>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
new file mode 100644 (file)
index 0000000..d83f940
--- /dev/null
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+    <PreferenceCategory
+        android:title="@string/pref_cat_application_control">
+
+        <PreferenceScreen
+            android:key="exit_application"
+            android:title="@string/pref_exit_power_off" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_cat_initialize">
+
+        <CheckBoxPreference
+            android:key="auto_connect_to_camera"
+            android:title="@string/pref_auto_connect_camera" />
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_cat_camera">
+
+        <ListPreference
+            android:title="@string/pref_take_mode"
+            android:entryValues="@array/take_mode_value"
+            android:entries="@array/take_mode"
+            android:key="take_mode"
+            android:defaultValue="P"/>
+
+        <ListPreference
+            android:title="@string/pref_camera_sound_volume"
+            android:entryValues="@array/sound_volume_level_value"
+            android:entries="@array/sound_volume_level"
+            android:key="sound_volume_level"
+            android:defaultValue="OFF"/>
+
+        <CheckBoxPreference
+            android:key="raw"
+            android:title="@string/pref_take_raw" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_cat_live_view">
+        <ListPreference
+            android:title="@string/pref_live_view_quality"
+            android:entryValues="@array/live_view_quality_value"
+            android:entries="@array/live_view_quality"
+            android:key="live_view_quality"
+            android:defaultValue="QVGA"/>
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_cat_info">
+
+        <PreferenceScreen
+            android:key="focal_length"
+            android:title="@string/pref_focal_length"
+            android:selectable="false" />
+
+        <PreferenceScreen
+            android:key="lens_status"
+            android:title="@string/pref_lens_status"
+            android:selectable="false" />
+
+        <PreferenceScreen
+            android:key="media_status"
+            android:title="@string/pref_media_status"
+            android:selectable="false" />
+
+        <PreferenceScreen
+            android:key="camera_version"
+            android:title="@string/pref_camera_version"
+            android:selectable="false" />
+
+        <PreferenceScreen
+        android:key="camerakit_version"
+        android:title="@string/pref_camerakit_version"
+        android:selectable="false" />
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_cat_gokigen">
+        <Preference
+            android:key="instruction_link"
+            android:title="@string/pref_instruction_manual"
+            android:summary="https://osdn.net/projects/gokigen/wiki/A01d"
+            android:selectable="true">
+            <intent android:action="android.intent.action.VIEW"
+                android:data="https://osdn.net/projects/gokigen/wiki/A01d" />
+        </Preference>
+        <Preference
+            android:key="privacy_policy"
+            android:title="@string/pref_privacy_policy"
+            android:summary="https://osdn.net/projects/gokigen/wiki/PrivacyPolicy"
+            android:selectable="true">
+            <intent android:action="android.intent.action.VIEW"
+                android:data="https://osdn.net/projects/gokigen/wiki/PrivacyPolicy" />
+        </Preference>
+    </PreferenceCategory>
+</PreferenceScreen>
diff --git a/build.gradle b/build.gradle
new file mode 100644 (file)
index 0000000..c2eea8e
--- /dev/null
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:2.3.3'
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        jcenter()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644 (file)
index 0000000..aac7c9b
--- /dev/null
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644 (file)
index 0000000..13372ae
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644 (file)
index 0000000..727166e
--- /dev/null
@@ -0,0 +1,6 @@
+#Mon Jun 19 23:15:24 JST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644 (file)
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644 (file)
index 0000000..8a0b282
--- /dev/null
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644 (file)
index 0000000..e7b4def
--- /dev/null
@@ -0,0 +1 @@
+include ':app'