OSDN Git Service

https://osdn.net/cvs/view/gokigen/MeMoMa/ から コピーしてくる。(+API27でビルドできるよう、少し調整。)
authorMRSa <mrsa@myad.jp>
Mon, 25 Jun 2018 13:40:51 +0000 (22:40 +0900)
committerMRSa <mrsa@myad.jp>
Mon, 25 Jun 2018 13:40:51 +0000 (22:40 +0900)
130 files changed:
.gitignore [new file with mode: 0644]
app/build.gradle [new file with mode: 0644]
app/src/main/AndroidManifest.xml [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ConfirmationDialog.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/CreditDialog.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ExtensionActivity.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ExtensionActivityListener.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ExternalStorageFileUtility.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/FileSelectionDialog.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/GokigenSurfaceView.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ICanvasDrawer.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/IObjectSelectionReceiver.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ImageLoader.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ItemSelectionDialog.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/LineStyleHolder.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/Main.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaCanvasDrawer.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaConnectLineHolder.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaDataFileHolder.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaDataInOutManager.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileExportCsvProcess.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileImportCsvProcess.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileLoadingProcess.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileSavingEngine.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileSavingProcess.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaListener.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaObjectHolder.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectAligner.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectDataInputDialog.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectLayoutCaptureExporter.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectOperationCommandHolder.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectShapeDrawer.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/OperationModeHolder.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/Preference.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/SelectFeatureListener.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/SelectLineShapeDialog.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/SharedIntentInvoker.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/SymbolListArrayAdapter.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/SymbolListArrayItem.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/TextEditDialog.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/TextEditReceiver.java [new file with mode: 0644]
app/src/main/java/jp/sourceforge/gokigen/memoma/ViewCaptureExporter.java [new file with mode: 0644]
app/src/main/res/drawable-hdpi/icon.png [new file with mode: 0644]
app/src/main/res/drawable-hdpi/icon0.png [new file with mode: 0644]
app/src/main/res/drawable-ldpi/icon0.png [new file with mode: 0644]
app/src/main/res/drawable-mdpi/icon0.png [new file with mode: 0644]
app/src/main/res/drawable/btn_arrow_down.png [new file with mode: 0644]
app/src/main/res/drawable/btn_arrow_left.png [new file with mode: 0644]
app/src/main/res/drawable/btn_arrow_right.png [new file with mode: 0644]
app/src/main/res/drawable/btn_arrow_up.png [new file with mode: 0644]
app/src/main/res/drawable/btn_checked.png [new file with mode: 0644]
app/src/main/res/drawable/btn_circle.png [new file with mode: 0644]
app/src/main/res/drawable/btn_circle_normal.png [new file with mode: 0644]
app/src/main/res/drawable/btn_circle_pressed.png [new file with mode: 0644]
app/src/main/res/drawable/btn_circle_selected.png [new file with mode: 0644]
app/src/main/res/drawable/btn_create.png [new file with mode: 0644]
app/src/main/res/drawable/btn_curve.png [new file with mode: 0644]
app/src/main/res/drawable/btn_curve_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_curve_larrow.png [new file with mode: 0644]
app/src/main/res/drawable/btn_curve_larrow_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_curve_rarrow.png [new file with mode: 0644]
app/src/main/res/drawable/btn_curve_rarrow_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_delete.png [new file with mode: 0644]
app/src/main/res/drawable/btn_diamond.png [new file with mode: 0644]
app/src/main/res/drawable/btn_double.png [new file with mode: 0644]
app/src/main/res/drawable/btn_double_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_drum.png [new file with mode: 0644]
app/src/main/res/drawable/btn_expand.png [new file with mode: 0644]
app/src/main/res/drawable/btn_explode.png [new file with mode: 0644]
app/src/main/res/drawable/btn_filter.png [new file with mode: 0644]
app/src/main/res/drawable/btn_hexagonal.png [new file with mode: 0644]
app/src/main/res/drawable/btn_keyboard.png [new file with mode: 0644]
app/src/main/res/drawable/btn_line_dash_heavy.png [new file with mode: 0644]
app/src/main/res/drawable/btn_line_dash_middle.png [new file with mode: 0644]
app/src/main/res/drawable/btn_line_dash_thin.png [new file with mode: 0644]
app/src/main/res/drawable/btn_line_heavy.png [new file with mode: 0644]
app/src/main/res/drawable/btn_line_middle.png [new file with mode: 0644]
app/src/main/res/drawable/btn_line_thin.png [new file with mode: 0644]
app/src/main/res/drawable/btn_move.png [new file with mode: 0644]
app/src/main/res/drawable/btn_noregion.png [new file with mode: 0644]
app/src/main/res/drawable/btn_notchecked.png [new file with mode: 0644]
app/src/main/res/drawable/btn_oval.png [new file with mode: 0644]
app/src/main/res/drawable/btn_paper.png [new file with mode: 0644]
app/src/main/res/drawable/btn_parallelogram.png [new file with mode: 0644]
app/src/main/res/drawable/btn_rectangle.png [new file with mode: 0644]
app/src/main/res/drawable/btn_roundrect.png [new file with mode: 0644]
app/src/main/res/drawable/btn_save_normal.png [new file with mode: 0644]
app/src/main/res/drawable/btn_save_pressed.png [new file with mode: 0644]
app/src/main/res/drawable/btn_save_selected.png [new file with mode: 0644]
app/src/main/res/drawable/btn_sheet.png [new file with mode: 0644]
app/src/main/res/drawable/btn_straight.png [new file with mode: 0644]
app/src/main/res/drawable/btn_straight_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_straight_larrow.png [new file with mode: 0644]
app/src/main/res/drawable/btn_straight_larrow_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_straight_rarrow.png [new file with mode: 0644]
app/src/main/res/drawable/btn_straight_rarrow_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_trapezoidy_down.png [new file with mode: 0644]
app/src/main/res/drawable/btn_trapezoidy_up.png [new file with mode: 0644]
app/src/main/res/drawable/btn_tree.png [new file with mode: 0644]
app/src/main/res/drawable/btn_tree_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_tree_larrow.png [new file with mode: 0644]
app/src/main/res/drawable/btn_tree_larrow_dash.png [new file with mode: 0644]
app/src/main/res/drawable/btn_tree_rarrow.png [new file with mode: 0644]
app/src/main/res/drawable/btn_tree_rarrow_dash.png [new file with mode: 0644]
app/src/main/res/drawable/circle_go.png [new file with mode: 0644]
app/src/main/res/drawable/home.png [new file with mode: 0644]
app/src/main/res/drawable/icon.png [new file with mode: 0644]
app/src/main/res/drawable/icon1.png [new file with mode: 0644]
app/src/main/res/drawable/icon2.png [new file with mode: 0644]
app/src/main/res/layout/confirmationdialog.xml [new file with mode: 0644]
app/src/main/res/layout/creditdialog.xml [new file with mode: 0644]
app/src/main/res/layout/extensionview.xml [new file with mode: 0644]
app/src/main/res/layout/lineselection.xml [new file with mode: 0644]
app/src/main/res/layout/listarrayitems.xml [new file with mode: 0644]
app/src/main/res/layout/listdialog.xml [new file with mode: 0644]
app/src/main/res/layout/main.xml [new file with mode: 0644]
app/src/main/res/layout/messagedialog.xml [new file with mode: 0644]
app/src/main/res/layout/objectinput.xml [new file with mode: 0644]
app/src/main/res/layout/preference.xml [new file with mode: 0644]
app/src/main/res/values-ja/arrays.xml [new file with mode: 0644]
app/src/main/res/values-ja/strings.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/bordershape.xml [new file with mode: 0644]
app/src/main/res/xml/circlebuttonstyle.xml [new file with mode: 0644]
app/src/main/res/xml/savebuttonstyle.xml [new file with mode: 0644]
build.gradle [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..4160cc5
--- /dev/null
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+.idea
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+/app/build
+.externalNativeBuild
+/gradle
+import-summary.txt
+gradlew
+gradlew.bat
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644 (file)
index 0000000..3f4072b
--- /dev/null
@@ -0,0 +1,29 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 27
+    buildToolsVersion "28.0.0"
+
+    defaultConfig {
+        applicationId "jp.sourceforge.gokigen.memoma"
+        minSdkVersion 14
+        targetSdkVersion 27
+        versionCode 15
+        versionName "1.3.0"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
+        }
+    }
+}
+
+dependencies {
+    api fileTree(dir: 'libs', include: ['*.jar'])
+    api 'com.android.support:appcompat-v7:27.1.1'
+    api 'com.android.support.constraint:constraint-layout:1.1.2'
+    api 'com.android.support:preference-v14:27.1.1'
+    api 'com.android.support:preference-v7:27.1.1'
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..5ac969d
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="jp.sourceforge.gokigen.memoma">
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+    <application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/Theme.AppCompat">
+
+        <activity android:name=".Main"
+            android:label="@string/app_name"
+            android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".Preference" android:label="@string/preference_name">
+        </activity>
+        <activity android:name=".ExtensionActivity"
+            android:label="@string/extent_name"
+            android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="jp.sfjp.gokigen.memoma.extension.activity" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+        <meta-data android:name="android.max_aspect" android:value="ratio_float"/>
+    </application>
+</manifest>
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ConfirmationDialog.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ConfirmationDialog.java
new file mode 100644 (file)
index 0000000..60dec13
--- /dev/null
@@ -0,0 +1,121 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ *   はい か いいえ を入力するダイアログを準備する
+ * 
+ * @author MRSa
+ *
+ */
+public class ConfirmationDialog
+{
+       private Context context = null;
+       private IResultReceiver resultReceiver = null;
+    private String  message = "";
+       private String  title = "";
+       private int    icon = 0;
+
+       public ConfirmationDialog(Context arg)
+       {
+               context = arg;
+       }
+
+       /**
+        *  クラスの準備
+        * @param receiver
+        * @param initialMessage
+        */
+       public void prepare(IResultReceiver receiver, int titleIcon, String titleMessage, String confirmMessage)
+       {
+               if (receiver != null)
+               {
+                       resultReceiver = receiver;
+               }
+               icon = titleIcon;
+               title = titleMessage;
+        message = confirmMessage;              
+       }
+
+    /**
+     *   確認ダイアログを応答する
+     * @return
+     */
+    public Dialog getDialog()
+    {
+       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final View layout = inflater.inflate(R.layout.confirmationdialog, null);
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        final TextView  textView = (TextView)  layout.findViewById(R.id.confirm_message);
+
+        // 表示するデータ(アイコン、ダイアログタイトル、メッセージ)を準備する
+        if (icon != 0)
+        {
+            builder.setIcon(icon);
+        }
+        if (title != null)
+        {
+            builder.setTitle(title);
+        }
+        if (message != null)
+        {
+               textView.setText(message);
+        }
+        builder.setView(layout);
+        builder.setCancelable(false);
+        builder.setPositiveButton(context.getString(R.string.confirmYes), new DialogInterface.OnClickListener()
+              {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.acceptConfirmation();
+                          }
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+               });
+        builder.setNegativeButton(context.getString(R.string.confirmNo), new DialogInterface.OnClickListener()
+               {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.rejectConfirmation();
+                          }
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+               });
+        return (builder.create());     
+    }
+
+    public interface IResultReceiver
+    {
+        public abstract void acceptConfirmation();
+        public abstract void rejectConfirmation();
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/CreditDialog.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/CreditDialog.java
new file mode 100644 (file)
index 0000000..9aef65e
--- /dev/null
@@ -0,0 +1,53 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ *  クレジットを表示する
+ * 
+ * @author MRSa
+ *
+ */
+public class CreditDialog
+{
+       private Activity context = null;
+
+       /**
+        *   コンストラクタ
+        * @param arg
+        */
+       public CreditDialog(Activity arg)
+       {
+               context = arg;
+       }
+
+    /**
+     *   ダイアログを応答する
+     * @return
+     */
+    public Dialog getDialog()
+    {
+       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+       View layout = inflater.inflate(R.layout.creditdialog, (ViewGroup) null);  //  ?? http://www.mail-archive.com/android-developers@googlegroups.com/msg162003.html より
+       //View layout = inflater.inflate(R.layout.creditdialog, (ViewGroup) context.findViewById(R.id.layout_root));
+
+       TextView text = (TextView) layout.findViewById(R.id.creditmessage);
+       text.setText(context.getString(R.string.app_credit));
+ //    ImageView image = (ImageView) layout.findViewById(R.id.crediticon);
+ //    image.setImageResource(R.drawable.icon);
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setTitle(context.getString(R.string.app_name));
+        builder.setIcon(R.drawable.icon);
+        builder.setView(layout);
+        builder.setCancelable(true);
+        return (builder.create());
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ExtensionActivity.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ExtensionActivity.java
new file mode 100644 (file)
index 0000000..f16fbe1
--- /dev/null
@@ -0,0 +1,192 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+/**
+ * 
+ * @author MRSa
+ *
+ */
+public class ExtensionActivity extends  Activity
+{
+       /** 起動コード **/
+    public static final String MEMOMA_EXTENSION_LAUNCH_ACTIVITY = "jp.sfjp.gokigen.memoma.extension.activity";
+
+    /** データ識別子(表示中データの保存ファイルへのフルパス) **/
+    public static final String MEMOMA_EXTENSION_DATA_FULLPATH = "jp.sfjp.gokigen.memoma.extension.data.fullpath";
+    public static final String MEMOMA_EXTENSION_DATA_TITLE = "jp.sfjp.gokigen.memoma.extension.data.title";
+
+    private ExtensionActivityListener listener = null;
+    
+       /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) 
+    {
+          super.onCreate(savedInstanceState);
+
+          /** リスナクラスを生成する **/
+          listener = new ExtensionActivityListener((Activity) this);
+
+          /** レイアウトを設定する **/
+          setContentView(R.layout.extensionview);
+
+          /** リスナクラスの準備 **/
+          listener.prepareExtraDatas(getIntent());
+          listener.prepareListener(); 
+     }
+
+    /**
+     *  メニューの生成
+     */
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu)
+    {
+       menu = listener.onCreateOptionsMenu(menu);
+       return (super.onCreateOptionsMenu(menu));
+    }
+    
+    /**
+     *  メニューアイテムの選択
+     */
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item)
+    {
+        return (listener.onOptionsItemSelected(item));
+    }
+    
+    /**
+     *  メニュー表示前の処理
+     */
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu)
+    {
+       listener.onPrepareOptionsMenu(menu);
+       return (super.onPrepareOptionsMenu(menu));
+    }
+
+    /**
+     *  画面が裏に回ったときの処理
+     */
+    @Override
+    public void onPause()
+    {
+        super.onPause();
+        try
+        {
+            // 動作を止めるようイベント処理クラスに指示する
+               listener.shutdown();            
+        }
+        catch (Exception ex)
+        {
+               // 何もしない
+        }
+    }
+    
+    /**
+     *  画面が表に出てきたときの処理
+     */
+    @Override
+    public void onResume()
+    {
+        super.onResume();
+        try
+        {
+               // 動作準備するようイベント処理クラスに指示する
+               listener.prepareToStart();
+        }
+        catch (Exception ex)
+        {
+            // なにもしない
+        }
+    }
+
+    /**
+     *   終了時の処理
+     * 
+     */
+    @Override
+    protected void onDestroy()
+    {
+        listener.finishListener();
+        super.onDestroy();
+    }
+
+    /**
+     * 
+     */
+    @Override
+    protected void onStart()
+    {
+        super.onStart();
+    }
+
+    /**
+     * 
+     */
+    @Override
+    protected void onStop()
+    {
+        super.onStop();
+    }
+
+    /**
+     * 
+     */
+    @Override
+    protected void onSaveInstanceState(Bundle outState)
+    {
+            super.onSaveInstanceState(outState);
+    }
+
+    /**
+     * 
+     */
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState)
+    {
+        super.onRestoreInstanceState(savedInstanceState);
+    }
+
+    /**
+     *  ダイアログ表示の準備
+     * 
+     */
+    @Override
+    protected Dialog onCreateDialog(int id)
+    {
+       return (listener.onCreateDialog(id));
+    }
+
+    /**
+     *  ダイアログ表示の準備
+     * 
+     */
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog)
+    {
+       listener.onPrepareDialog(id, dialog);
+       return;
+    }
+    
+    /**
+     *  子画面から応答をもらったときの処理
+     */
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data)
+    {
+        try
+        {
+            // 子画面からもらった情報の応答処理をイベント処理クラスに依頼する
+               listener.onActivityResult(requestCode, resultCode, data);
+        }
+        catch (Exception ex)
+        {
+            // 例外が発生したときには、何もしない。
+        }
+    }    
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ExtensionActivityListener.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ExtensionActivityListener.java
new file mode 100644 (file)
index 0000000..a8a3db9
--- /dev/null
@@ -0,0 +1,475 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Enumeration;
+import java.util.List;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Intent;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.ImageButton;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.Toast;
+
+/**
+ *    リスト形式で表示・エクスポート
+ * 
+ * @author MRSa
+ *
+ */
+public class ExtensionActivityListener  implements OnClickListener, MeMoMaFileLoadingProcess.IResultReceiver, MeMoMaFileExportCsvProcess.IResultReceiver, FileSelectionDialog.IResultReceiver, MeMoMaFileImportCsvProcess.IResultReceiver
+{
+    public final int MENU_ID_EXPORT= (Menu.FIRST + 1);
+    public final int MENU_ID_SHARE = (Menu.FIRST + 2);
+    public final int MENU_ID_IMPORT = (Menu.FIRST + 3);
+
+    private final String EXTENSION_DIRECTORY = "/exported";
+    
+    private ExternalStorageFileUtility fileUtility = null;
+       private MeMoMaObjectHolder objectHolder = null;
+       private FileSelectionDialog fileSelectionDialog = null;
+       
+       private boolean isShareExportedData = false;
+
+       private List<SymbolListArrayItem> listItems = null;
+    
+    private Activity parent = null;  // 親分
+       
+       /**
+     *  コンストラクタ
+     * @param argument
+     */
+    public ExtensionActivityListener(Activity argument)
+    {
+        parent = argument;
+        fileUtility = new ExternalStorageFileUtility(Main.APP_BASEDIR);
+        objectHolder = new MeMoMaObjectHolder(parent, new MeMoMaConnectLineHolder());
+    }
+    /**
+     *  起動時にデータを準備する
+     * 
+     * @param myIntent
+     */
+    public void prepareExtraDatas(Intent myIntent)
+    {
+        try
+        {
+            // Intentで拾ったデータを読み出す (初期化データ)
+               //fullPath = myIntent.getStringExtra(ExtensionActivity.MEMOMA_EXTENSION_DATA_FULLPATH);
+               objectHolder.setDataTitle(myIntent.getStringExtra(ExtensionActivity.MEMOMA_EXTENSION_DATA_TITLE));
+
+            // Preferenceに記憶されたデータがあればそれを取得する
+            // SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+         }
+        catch (Exception ex)
+        {
+            Log.v(Main.APP_IDENTIFIER, "Exception :" + ex.toString());
+        }        
+    }
+
+    /**
+     *  がっつりこのクラスにイベントリスナを接続する
+     * 
+     */
+    public void prepareListener()
+    {
+        // フィルタ設定ボタン
+        final ImageButton filterButton = (ImageButton) parent.findViewById(R.id.SetFilterButton);
+        filterButton.setOnClickListener(this);
+
+    }
+
+    /**
+     *  終了準備
+     */
+    public void finishListener()
+    {
+
+    }
+
+    /**
+     *  スタート準備
+     */
+    public void prepareToStart()
+    {
+               Log.v(Main.APP_IDENTIFIER, "ExtensionActivityListener::prepareToStart() : "  + objectHolder.getDataTitle());
+
+               // ファイルをロードする!
+               // (AsyncTaskを使ってデータを読み込む)
+               MeMoMaFileLoadingProcess asyncTask = new MeMoMaFileLoadingProcess(parent, fileUtility, this);
+        asyncTask.execute(objectHolder);
+    }
+
+    /**
+     *    詳細データを表示する。
+     * 
+     * @param title
+     * @param url
+     */
+    private void showDetailData(String first, String second, String third)
+    {
+        Log.v(Main.APP_IDENTIFIER, "SELECTED: " + first + " " + second + " " + third);
+    }
+
+    /**
+     *  終了準備
+     */
+    public void shutdown()
+    {
+       
+    }
+    
+    /**
+     *  他画面から戻ってきたとき...
+     * @param requestCode
+     * @param resultCode
+     * @param data
+     */
+    public void onActivityResult(int requestCode, int resultCode, Intent data)
+    {
+        // なにもしない...
+    }
+
+    /**
+     *   クリックされたときの処理
+     */
+    public void onClick(View v)
+    {
+        int id = v.getId();
+        if (id == R.id.SetFilterButton)
+        {
+                // フィルタ設定ボタンが押された!
+        }
+    }
+    
+    /**
+     *   触られたときの処理
+     * 
+     */
+    public boolean onTouch(View v, MotionEvent event)
+    {
+        // int id = v.getId();
+        // int action = event.getAction();
+
+        return (false);
+    }
+
+    /**
+     *   メニューへのアイテム追加
+     * @param menu
+     * @return
+     */
+    public Menu onCreateOptionsMenu(Menu menu)
+    {
+       MenuItem menuItem = menu.add(Menu.NONE, MENU_ID_SHARE, Menu.NONE, parent.getString(R.string.export_csv));
+       menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);   /*  for Android 3.1  */
+       menuItem.setIcon(android.R.drawable.ic_menu_share);
+
+       menuItem = menu.add(Menu.NONE, MENU_ID_EXPORT, Menu.NONE, parent.getString(R.string.shareContent));
+       menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);   /*  for Android 3.1  */
+       menuItem.setIcon(android.R.drawable.ic_menu_save);
+
+       menuItem = menu.add(Menu.NONE, MENU_ID_IMPORT, Menu.NONE, parent.getString(R.string.import_csv));
+       menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);   /*  for Android 3.1  */
+       menuItem.setIcon(android.R.drawable.ic_menu_edit);
+
+       return (menu);
+    }
+    
+    /**
+     *   メニュー表示前の処理
+     * @param menu
+     * @return
+     */
+    public void onPrepareOptionsMenu(Menu menu)
+    {
+       menu.findItem(MENU_ID_SHARE).setVisible(true);
+       menu.findItem(MENU_ID_EXPORT).setVisible(true);
+       menu.findItem(MENU_ID_IMPORT).setVisible(true);
+
+       return;
+    }
+
+    /**
+     *   メニューのアイテムが選択されたときの処理
+     * @param item
+     * @return
+     */
+    public boolean onOptionsItemSelected(MenuItem item)
+    {
+       boolean result = false;
+       switch (item.getItemId())
+       {
+          case MENU_ID_EXPORT:
+            // 表示中データのエクスポート
+                   export_as_csv(false);
+               result = true;
+               break;
+
+          case MENU_ID_SHARE:
+               export_as_csv(true);
+               result = true;
+               break;
+
+          case MENU_ID_IMPORT:
+               // データのインポート
+               importObjectFromCsv();
+               result = true;
+               break;
+
+         default:
+               result = false;
+               break;
+       }
+       return (result);
+    }
+
+    /**
+     *   CSV形式でデータをインポートする
+     * 
+     */
+    private void importObjectFromCsv()
+    {
+       // データのインポート
+       parent.showDialog(R.id.listdialog);     
+    }
+
+    /**
+     *   データをCSV形式で出力する
+     * 
+     */
+    private void export_as_csv(boolean isShare)
+    {
+       isShareExportedData = isShare;
+
+       // AsyncTaskを使ってデータをエクスポートする
+       MeMoMaFileExportCsvProcess asyncTask = new MeMoMaFileExportCsvProcess(parent, fileUtility, this);
+        asyncTask.execute(objectHolder);
+    }
+    
+    /**
+     *  ダイアログの生成
+     * 
+     */
+    public Dialog onCreateDialog(int id)
+    {
+       if (id == R.id.listdialog)
+       {
+               fileSelectionDialog = new FileSelectionDialog(parent, parent.getString(R.string.dialogtitle_selectcsv), fileUtility, ".csv",  this);
+               return (fileSelectionDialog.getDialog());
+       }
+
+/**
+       if (id == R.id.info_about_gokigen)
+       {
+               CreditDialog dialog = new CreditDialog(parent);
+               return (dialog.getDialog());
+       }
+**/
+           return (null);
+    }
+
+    /**
+     *    ファイル選択ダイアログの表示を準備する
+     * 
+     */
+    private void prepareFileSelectionDialog(Dialog dialog)
+    {
+       fileSelectionDialog.prepare("", EXTENSION_DIRECTORY);
+    }
+
+    /**
+     *  ダイアログ表示の準備
+     * 
+     */
+    public void onPrepareDialog(int id, Dialog dialog)
+    {
+        if (id == R.id.listdialog)
+        {
+               // CSVインポートダイアログを準備する
+               prepareFileSelectionDialog(dialog);
+               return;
+        }
+    }
+
+    /**
+     *    ファイルをロードする途中のバックグラウンド処理...
+     * 
+     */
+       public void onLoadingProcess()
+       {
+               try
+               {
+               // リストに表示するアイテムを生成する
+               listItems = null;
+               listItems = new ArrayList<SymbolListArrayItem>();
+
+               // TODO: 何らかの法則に従って並べ替えをする。
+
+               Enumeration<Integer> keys = objectHolder.getObjectKeys();
+               while (keys.hasMoreElements())
+               {
+                   Integer key = keys.nextElement();
+                   MeMoMaObjectHolder.PositionObject pos = objectHolder.getPosition(key);
+
+                   // アイコンの決定
+                   int objectStyleIcon = MeMoMaObjectHolder .getObjectDrawStyleIcon(pos.drawStyle);
+                   
+                   // ユーザチェックの有無表示
+                   int userCheckedIcon = (pos.userChecked == true) ? R.drawable.btn_checked : R.drawable.btn_notchecked;
+
+                   // TODO: アイテム選択時の情報エリアは(ArrayItem側には)用意しているが未使用。
+                   SymbolListArrayItem listItem = new SymbolListArrayItem(userCheckedIcon, pos.label, pos.detail, "", objectStyleIcon);
+
+                   listItems.add(listItem);
+               }
+           } catch (Exception ex)
+           {
+               // 例外発生...ログを吐く
+               Log.v(Main.APP_IDENTIFIER, "ExtensionActivityListener::onLoadingProcess() : " + ex.toString());
+           }   
+       }
+
+    /**
+     *    ファイルのロード結果を受け取る
+     * 
+     */
+    public void onLoadedResult(String detail)
+    {
+               Log.v(Main.APP_IDENTIFIER, "ExtensionActivityListener::onLoadedResult() '"  + objectHolder.getDataTitle() +"' : " + detail);
+
+               // 読み込んだファイル名をタイトルに設定する
+               parent.setTitle(objectHolder.getDataTitle());
+               
+               // オブジェクト一覧を表示する
+               updateObjectList();
+               
+               // 読み込みしたことを伝達する
+               //String outputMessage = parent.getString(R.string.load_data) + " " + objectHolder.getDataTitle() + " " + detail;
+        //Toast.makeText(parent, outputMessage, Toast.LENGTH_SHORT).show();            
+    }
+
+    /**
+     *    ファイルのエクスポート結果を受け取る
+     * 
+     */
+    public void onExportedResult(String exportedFileName, String detail)
+    {
+               Log.v(Main.APP_IDENTIFIER, "ExtensionActivityListener::onExportedResult() '"  + objectHolder.getDataTitle() +"' : " + detail);
+
+               // エクスポートしたことを伝達する
+               String outputMessage = parent.getString(R.string.export_csv) + " " + objectHolder.getDataTitle() + " " + detail;
+        Toast.makeText(parent, outputMessage, Toast.LENGTH_SHORT).show();
+        
+        if (isShareExportedData == true)
+        {
+               // エクスポートしたファイルを共有する
+            shareContent(exportedFileName);
+        }
+       isShareExportedData = false;
+    }
+    
+    /**
+     *    オブジェクト一覧を更新する
+     */
+    private void updateObjectList()
+    {
+       try
+       {
+               // リストアダプターを生成し、設定する
+            ListView listView = (ListView) parent.findViewById(R.id.ExtensionView);
+            ListAdapter adapter = new SymbolListArrayAdapter(parent,  R.layout.listarrayitems, listItems);
+            listView.setAdapter(adapter);
+
+            // アイテムを選択したときの処理
+            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+                //@Override
+                public void onItemClick(AdapterView<?> parentView, View view, int position, long id)
+                {
+                    ListView listView = (ListView) parentView;
+                    SymbolListArrayItem item = (SymbolListArrayItem) listView.getItemAtPosition(position);
+
+                    /// リストが選択されたときの処理...データを開く
+                    showDetailData(item.getTextResource1st(), item.getTextResource2nd(), item.getTextResource3rd());
+                }
+            });
+            System.gc();   // いらない(参照が切れた)クラスを消したい
+       }
+       catch (Exception ex)
+       {
+               // 何もしない。
+       }
+    }
+    
+    /**
+     *    エクスポートしたファイルを共有する
+     * 
+     * @param fileName
+     */
+    private void shareContent(String fileName)
+    {
+       String message = "";
+        try
+        {
+               // 現在の時刻を取得する
+            Calendar calendar = Calendar.getInstance();
+               SimpleDateFormat outFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+            String date =  outFormat.format(calendar.getTime());
+
+            // メールタイトル
+            String title = parent.getString(R.string.app_name) + " | "+ objectHolder.getDataTitle() + " | " + date;
+
+            // メールの本文を構築する
+            message = message + "Name : " + objectHolder.getDataTitle() + "\n";
+            message = message + "exported : " + date + "\n";
+            message = message + "number of objects : " + objectHolder.getCount() + "\n";
+
+            // Share Intentを発行する。
+            SharedIntentInvoker.shareContent(parent, MENU_ID_SHARE, title, message,  fileName, "text/plain");
+        }
+        catch (Exception ex)
+        {
+               
+        }
+    }
+    
+    /**
+     *   ファイルが選択された!
+     * 
+     */
+    public void selectedFileName(String fileName)
+    {
+       // CSVファイルからオブジェクトをロードするクラスを呼び出す。
+        Log.v(Main.APP_IDENTIFIER, "ExtensionActivityListener::selectedFileName() : " + fileName);
+        MeMoMaFileImportCsvProcess asyncTask = new MeMoMaFileImportCsvProcess(parent, fileUtility, this, fileName);
+        asyncTask.execute(objectHolder);
+    }
+
+    /**
+     *    インポート結果の受信
+     * 
+     * @param detail
+     */
+    public void onImportedResult(String detail)
+    {
+               Log.v(Main.APP_IDENTIFIER, "ExtensionActivityListener::onImportedResult() '"  + objectHolder.getDataTitle() +"' : " + detail);
+
+               // インポートしたことを伝達する
+               String outputMessage = parent.getString(R.string.import_csv) + " " + objectHolder.getDataTitle() + " " + detail;
+        Toast.makeText(parent, outputMessage, Toast.LENGTH_SHORT).show();
+
+        // 一覧のリストを作りなおす
+        onLoadingProcess();
+        updateObjectList();
+    }    
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ExternalStorageFileUtility.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ExternalStorageFileUtility.java
new file mode 100644 (file)
index 0000000..72a7c98
--- /dev/null
@@ -0,0 +1,331 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.os.Environment;
+import android.util.Log;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+/**
+ *  外部ストレージにデータを記録するために使うユーティリティ
+ *  
+ * @author MRSa
+ */
+public class ExternalStorageFileUtility 
+{
+       private final int COPY_BUFFER_SIZE = 32768;
+       private final int BUFFER_MARGIN    = 4;
+
+       private String baseDirectory = "/";
+
+    /**
+     *   コンストラクタ
+     * 
+     */
+    public ExternalStorageFileUtility(String offsetDir)
+    {
+        /** ベースディレクトリの作成 (あれば何もしない) **/
+        prepareBaseDirectory(offsetDir);
+    }
+    
+    /**
+     *   ベースディレクトリの決定を行う
+     * 
+     */
+    private boolean prepareBaseDirectory(String offsetDir)
+    {
+        String gokigenDirectory = Environment.getExternalStorageDirectory().getPath() + "/Gokigen";
+        try
+        {
+            File baseDir = new File(gokigenDirectory);
+            if (baseDir.exists() == false)
+            {
+                if (baseDir.mkdirs() == false)
+                {
+                    // ベースディレクトリ作成失敗...終了する
+                    baseDirectory = Environment.getExternalStorageDirectory().getPath();
+                    baseDir = null;
+                    return (false);
+                }
+            }
+            gokigenDirectory = gokigenDirectory + offsetDir;
+            baseDir = null;
+            baseDir = new File(gokigenDirectory);
+            if (baseDir.exists() == false)
+            {
+                if (baseDir.mkdirs() == false)
+                {
+                    // ベースディレクトリ作成失敗...終了する
+                    baseDirectory = Environment.getExternalStorageDirectory().getPath() + "/Gokigen";
+                    baseDir = null;
+                    return (false);                    
+                }
+            }
+            baseDirectory = gokigenDirectory;
+            return (true);
+        }
+        catch (Exception ex)
+        {
+            Log.v(Main.APP_IDENTIFIER, "prepareBaseDirectory() : " + ex.getMessage());
+        }
+        baseDirectory = Environment.getExternalStorageDirectory().getPath();
+        return (false);
+    }
+
+    /**
+     *  ベースディレクトリを取得する
+     * @return  書き込みを行うアプリ用ベースディレクトリ
+     */
+    public String getGokigenDirectory()
+    {
+        return (baseDirectory);
+    }    
+    
+    /**
+     *  ディレクトリを作成する
+     * 
+     * @param dirName
+     * @return
+     */
+    public boolean makeDirectory(String dirName)
+    {
+        String makeDir = baseDirectory + "/" + dirName;
+        try
+        {
+            File dir = new File(makeDir);
+            if (dir.exists() == false)
+            {
+                return (dir.mkdirs());
+            }
+            return (true);
+        }
+        catch (Exception ex)
+        {
+            Log.v(Main.APP_IDENTIFIER, "makeDirectory() : " + ex.getMessage());
+        }
+        return (false);
+    }
+
+    /**
+     *  記録ファイルをオープンする    
+     * @param fileName  ファイル名
+     * @param isAppend  追記モードでオープンするか?
+     * @return  ファイルストリーム
+     */
+    public FileOutputStream openFileStream(String fileName, boolean isAppend)
+    {
+        try
+        {
+            String targetName = baseDirectory + "/" + fileName;
+            FileOutputStream fileStream = new FileOutputStream(targetName, isAppend);
+            return (fileStream);
+        }
+        catch (Exception e)
+        {
+            Log.v(Main.APP_IDENTIFIER, "openFileStream() : " + e.getMessage());
+        }
+        return (null);
+    }    
+
+    /**
+     *   日単位でディレクトリを作成し、そこに書き込むためのファイル名を決定する
+     * @return ファイル名称
+     */
+    private String decideFileNameWithSpecifiedDate(String fileName, String year, String month, String date)
+    {
+        String directory = year;
+        
+        // 年のディレクトリを掘る
+        makeDirectory(year);
+
+        directory = directory + "/" + year + month;
+
+        // 年月のディレクトリを掘る
+        makeDirectory(directory);
+
+        directory = directory + "/" + year + month + date;
+
+        // 年月日のディレクトリを掘る
+        makeDirectory(directory);
+        
+        return (directory + "/" + year + month + date + "-" + fileName);
+    }
+
+    /**
+     *   日単位でディレクトリを作成し、そこに書き込むためのファイル名を決定する
+     * @return ファイル名称
+     */
+    public String decideFileNameWithDate(String fileName)
+    {
+        Calendar calendar = Calendar.getInstance();
+
+        SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
+        SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
+        SimpleDateFormat dateFormat = new SimpleDateFormat("dd");
+
+        String year  = yearFormat.format(calendar.getTime());
+        String month = monthFormat.format(calendar.getTime());
+        String date  = dateFormat.format(calendar.getTime());
+
+        return (decideFileNameWithSpecifiedDate(fileName, year, month, date));
+    }
+
+    /**
+     *   日単位でディレクトリを作成し、そこに書き込むためのファイル名を決定する
+     * @return ファイル名称
+     */
+    public String decideFileNameWithSpecifiedDate(String fileName, int year, int month, int day)
+    {
+        String yearStr = year + "";
+        String monthStr = "";
+        if (month < 10)
+        {
+            monthStr = "0" + month;    
+        }
+        else
+        {
+               monthStr = month + "";
+        }
+        String dayStr = "";
+        if (day < 10)
+        {
+            dayStr = "0" + day;
+        }
+        else
+        {
+               dayStr = day + "";
+        }
+        return (decideFileNameWithSpecifiedDate(fileName, yearStr, monthStr, dayStr));
+    }
+
+    /**
+     *  日付ディレクトリ名を取得する
+     * @param year
+     * @param month
+     * @param date
+     * @return
+     */
+    public String decideDateDirectory(int year, int month, int date)
+    {
+        String addMonth = "";
+        String addDate  = "";
+        String directory = baseDirectory + "/" + year + "/";
+        if (month < 10)
+        {
+            addMonth =  "0";
+        }
+        if (date < 10)
+        {
+            addDate = "0";
+        }
+        directory = directory + year + addMonth + month + "/" + year + addMonth + month + addDate + date + "/";        
+        return (directory);
+    }
+
+    /**
+     * ファイルのコピー (kaniFilerから持ってきた...)
+     * 
+     * @param destFileName コピー先ファイル (full path)
+     * @param srcFileName  コピー元ファイル (full path)
+     */
+       public boolean copyFile(String destFileName, String srcFileName)
+       {
+               File srcFile = null;
+               File dstFile = null;
+               
+               boolean     ret = false;
+               InputStream   is = null;
+               OutputStream  os = null;
+
+               if (destFileName == srcFileName)
+               {
+                       // ファイル名が同じだった場合にはコピーを実行しない
+                       return (false);
+               }
+               
+               try
+               {
+                       srcFile = new File(srcFileName);
+                       if (srcFile.exists() != true)
+                       {
+                               // ファイルが存在しなかった、、、終了する
+                               return (false);
+                       }
+                       is = new FileInputStream(srcFile);
+
+                       long dataFileSize = srcFile.length();
+                       byte[] buffer = new byte[COPY_BUFFER_SIZE + BUFFER_MARGIN];
+
+                       dstFile = new File(destFileName);
+                       if (dstFile.exists() == true)
+                       {
+                               // ファイルが存在した、、、削除して作り直す
+                               dstFile.delete();
+                       }
+
+                       os = new FileOutputStream(dstFile);
+                       if ((is != null)&&(os != null))
+                       {
+                               while (dataFileSize > 0)
+                               {
+                               int size = is.read(buffer, 0, COPY_BUFFER_SIZE);
+                               if (size <= 0)
+                               {
+                                       break;
+                               }
+                               os.write(buffer, 0, size);
+                               }
+                       }
+                       os.flush();
+                       os.close();
+                       is.close();
+                       
+                       dstFile = null;
+                       srcFile = null;
+                       buffer = null;
+                       is = null;
+                       os = null;
+                       ret = true;
+                       System.gc();
+               }
+               catch (Exception e)
+               {
+                       // 例外発生!!!
+                       try
+                       {
+                               if (is != null)
+                               {
+                                       is.close();
+                               }
+                       }
+                       catch (Exception e2)
+                       {
+                               //
+                       }
+                               
+                       try
+                       {
+                               if (os != null)
+                               {
+                                       os.close();
+                               }
+                       }
+                       catch (Exception e2)
+                       {
+                               //
+                       }
+                       is = null;
+                       os = null;
+                       srcFile = null;
+                       dstFile = null;
+                       System.gc();
+
+                       return (false);
+               }
+               return (ret);
+       }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/FileSelectionDialog.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/FileSelectionDialog.java
new file mode 100644 (file)
index 0000000..1c10cb8
--- /dev/null
@@ -0,0 +1,124 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+/**
+ *    ファイル選択ダイアログ
+ * 
+ * @author MRSa
+ *
+ */
+public class FileSelectionDialog
+{
+       private Context context = null;
+       private IResultReceiver resultReceiver = null;
+       private ExternalStorageFileUtility fileUtility = null;
+    private MeMoMaDataFileHolder dataFileHolder = null;
+    private String title = null;
+    private String fileExtension = null;
+    private Dialog dialogRef = null;
+    
+       /**
+        *    コンストラクタ
+        * 
+        * @param arg
+        */
+       public FileSelectionDialog(Context arg, String titleMessage, ExternalStorageFileUtility utility, String extension, IResultReceiver receiver)
+       {
+           context = arg;      
+           resultReceiver = receiver;
+               title = titleMessage;
+        fileUtility = utility;
+        fileExtension = extension;
+        dataFileHolder = new MeMoMaDataFileHolder(context, android.R.layout.simple_list_item_1, fileUtility, extension);
+       }
+
+       /**
+        *   ファイル一覧データをつくる!
+        * 
+        * @param currentFileName
+        * @param extendDirectory
+        */
+       public void prepare(String currentFileName, String extendDirectory)
+       {
+               dataFileHolder.updateFileList(currentFileName, extendDirectory);
+       }
+
+    /**
+     *   ファイル選択ダイアログを応答する
+     *   
+     * @return
+     */
+    public Dialog getDialog()
+    {
+       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final View layout = inflater.inflate(R.layout.listdialog, null);
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        
+        final ListView  listView = (ListView)  layout.findViewById(R.id.ListDataFileName);
+        listView.setAdapter(dataFileHolder);
+
+        // 表示するデータ(ダイアログタイトル)を準備する
+        if (title != null)
+        {
+            builder.setTitle(title);
+        }
+        builder.setView(layout);
+
+        // アイテムを選択したときの処理
+        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            //@Override
+            public void onItemClick(AdapterView<?> parentView, View view, int position, long id)
+            {
+                ListView listView = (ListView) parentView;
+                String fileName = (String) listView.getItemAtPosition(position);
+
+                /// リストが選択されたときの処理...データを開く
+                  if (resultReceiver != null)
+                  {
+                      resultReceiver.selectedFileName(fileName + fileExtension);
+                  }
+                  if (dialogRef != null)
+                  {
+                          dialogRef.dismiss();
+                   dialogRef = null;
+                  }
+               System.gc();
+            }
+        });
+        builder.setCancelable(true);
+        builder.setNegativeButton(context.getString(R.string.confirmNo), new DialogInterface.OnClickListener()
+               {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                       dialog.cancel();
+                       System.gc();
+                   }
+               });
+        dialogRef = builder.create();
+        return (dialogRef);            
+    }
+
+    /**
+     *   ファイルダイアログのインタフェース
+     *   
+     * @author MRSa
+     *
+     */
+    public interface IResultReceiver
+    {
+       /**
+        *    ファイルが選択された!
+        *    
+        */
+        public abstract void selectedFileName(String fileName);
+    }  
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/GokigenSurfaceView.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/GokigenSurfaceView.java
new file mode 100644 (file)
index 0000000..c765eed
--- /dev/null
@@ -0,0 +1,174 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ *  描画するくらす
+ * 
+ * @author MRSa
+ *
+ */
+public class GokigenSurfaceView extends SurfaceView implements SurfaceHolder.Callback
+{
+       ICanvasDrawer canvasDrawer = null;
+       
+       /**
+     *  コンストラクタ
+     * @param context
+     */
+       public GokigenSurfaceView(Context context)
+    {
+       super(context);
+       initializeSelf(context, null);
+    }
+
+       /**
+        *  コンストラクタ
+        * @param context
+        * @param attrs
+        */
+       public GokigenSurfaceView(Context context, AttributeSet attrs)
+       {
+               super(context, attrs);
+               initializeSelf(context, attrs);
+       }
+
+    /**
+     *   クラスの初期化処理
+     * @param context
+     * @param attrs
+     */
+    private void initializeSelf(Context context, AttributeSet attrs)
+    {
+       SurfaceHolder holder = getHolder();
+        holder.addCallback(this);
+    }
+
+    /**
+     *  データ書き込みクラスの設定
+     * 
+     * @param drawer
+     */
+    public void setCanvasDrawer(ICanvasDrawer drawer)
+    {
+        canvasDrawer = drawer;
+    }
+
+    /**
+     *   サーフェイス生成イベントの処理
+     * 
+     */
+    public void surfaceCreated(SurfaceHolder aHolder)
+    {
+        try
+        {
+               if (canvasDrawer != null)
+               {
+                   canvasDrawer.prepareToStart(getWidth(), getHeight());
+               }
+               doDraw();
+        }
+        catch (Exception ex)
+        {
+            //
+        }
+    }
+    
+
+    /**
+     *   タッチイベント
+     */
+    @Override
+    public boolean onTouchEvent(MotionEvent event)
+    {
+        boolean ret = false;
+       if (canvasDrawer != null)
+       {
+           ret = canvasDrawer.onTouchEvent(event);
+           if (ret == true)
+           {
+               doDraw();
+           }
+       }
+        return (ret);
+    }
+
+    
+    /**
+     *  サーフェイス変更イベントの処理
+     * 
+     */
+    public void surfaceChanged(SurfaceHolder aHolder, int format, int width, int height)
+    {
+        try
+        {
+               if (canvasDrawer != null)
+               {
+                   canvasDrawer.changedScreenProperty(format, width, height);
+               }
+               doDraw();
+        }
+        catch (Exception ex)
+        {
+            //
+            //
+            //
+        }
+    }
+
+    /**
+     *  サーフェイス開放イベントの処理
+     * 
+     */
+    public void surfaceDestroyed(SurfaceHolder aHolder)
+    {
+        try
+        {
+            //            
+        }
+        catch (Exception ex)
+        {
+            //            
+        }        
+    }
+
+    /**
+     *  グラフィックを描画する
+     */
+    public void doDraw()
+    {
+               //Log.v(Main.APP_IDENTIFIER, "GokigenSurfaceView::doDraw()");
+
+               SurfaceHolder drawHolder = getHolder();
+       try
+       {
+            Canvas canvas = drawHolder.lockCanvas();
+               if (canvas == null)
+               {
+                       // 描画領域が取れないから抜けてしまう
+                       Log.v(Main.APP_IDENTIFIER, "GokigenSurfaceView::doDraw()  canvas is null." );
+                       return;
+               }
+            canvas.save();
+            //////////////////////////////////////////////
+            if (canvasDrawer != null)
+            {
+               canvasDrawer.drawOnCanvas(canvas);
+            }
+            /////////////////////////////////////////////
+            canvas.restore();
+            drawHolder.unlockCanvasAndPost(canvas);
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "ex.(doDraw())>" +  ex.toString() + " " + ex.getMessage());
+       }
+    }
+
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ICanvasDrawer.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ICanvasDrawer.java
new file mode 100644 (file)
index 0000000..4397641
--- /dev/null
@@ -0,0 +1,15 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.graphics.Canvas;
+import android.view.MotionEvent;
+
+public interface ICanvasDrawer
+{      
+    public abstract void prepareToStart(int width, int height);
+    public abstract void changedScreenProperty(int format, int width, int height);
+
+    public abstract void drawOnCanvas(Canvas canvas);
+    
+    public abstract boolean onTouchEvent(MotionEvent event);
+
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/IObjectSelectionReceiver.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/IObjectSelectionReceiver.java
new file mode 100644 (file)
index 0000000..9ab1994
--- /dev/null
@@ -0,0 +1,18 @@
+package jp.sourceforge.gokigen.memoma;
+
+
+/**
+ *   オブジェクトが選択されたことを通知する
+ * 
+ * @author MRSa
+ *
+ */
+public interface IObjectSelectionReceiver
+{
+       public abstract int touchedVacantArea();
+       public abstract int touchUppedVacantArea();
+       public abstract void objectCreated();
+    public abstract boolean objectSelected(Integer key);
+    public abstract void objectSelectedContext(Integer key);
+       
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ImageLoader.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ImageLoader.java
new file mode 100644 (file)
index 0000000..8a71e95
--- /dev/null
@@ -0,0 +1,316 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.io.File;
+import java.io.InputStream;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.widget.ImageView;
+
+/**
+ *  画像イメージを読み込む
+ * 
+ * @author MRSa
+ *
+ */
+public class ImageLoader
+{
+    ProgressDialog loadingDialog = null;
+    Context  parent = null;
+
+    // 画像を表示する
+    String imageFile = null;
+       Bitmap imageBitmap = null;
+       int imageWidth     = 1;
+       int imageHeight    = 1;
+       ImageView imageView = null;
+    
+    public ImageLoader(Context context)
+    {
+        loadingDialog = new ProgressDialog(context);
+        parent = context;
+    }
+    
+    /**
+     *  イメージファイルの一覧を取得する
+     *  (一度も動かしたことのないコードなので注意!)
+     * @param activity
+     * @return イメージファイル名の一覧
+     */
+    /*
+    public static String[] getImageFileList(Activity activity)
+    {
+        try
+        {
+               HashSet<String> list = new HashSet<String>();
+               
+               Cursor c = activity.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
+               while(c.moveToNext())
+               {
+                String imagefile = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
+                File file = new File(imagefile);
+                list.add(file.getParent());
+               }
+            return (String[]) list.toArray(new String[list.size()]);
+        }
+        catch (Exception ex)
+        {
+            //
+        }
+        return (null);
+    }
+    */
+
+    /**
+        *  URIから変換
+        * 
+        * @param imageFile
+        * @return
+        */
+       public static Uri parseUri(String imageFile)
+       {
+           if (imageFile.startsWith("content://") == true)
+           {
+               return (Uri.parse(imageFile));
+           }
+
+       File picFile = new File(imageFile);
+       return (Uri.fromFile(picFile)); 
+       }
+
+       /**
+        *   画面にイメージを表示する 
+        *
+        */
+       public static void setImage(Context context, ImageView view, String imageFile)
+    {
+       // 画像を表示する
+               Bitmap bitmap = null;
+               int width = view.getWidth();
+               int height = view.getHeight();
+        if (imageFile.startsWith("content://") == true)
+        {
+               // URIから画像を設定する...OutOfMemory対策付き
+               bitmap = getBitmapFromUri(context, Uri.parse(imageFile), width, height);
+        }
+        else
+        {
+               // OutOfMemory対策付き...ビットマップのサイズを圧縮して表示
+               bitmap = getBitmap(imageFile, view.getWidth(), view.getHeight());
+        }
+       view.setScaleType(ImageView.ScaleType.FIT_XY);
+        view.setImageBitmap(bitmap);
+    }
+
+       /**
+        *   画面にイメージを表示する (ロード中ダイアログ表示つき)
+        * 
+        */
+       public void setImage(ImageView view, String targetFile)
+    {
+
+        //  プログレスダイアログ(「ロード中...」)を表示する。
+        loadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+        loadingDialog.setMessage(parent.getString(R.string.dataLoading));
+        loadingDialog.setIndeterminate(true);
+        loadingDialog.setCancelable(false);
+        loadingDialog.show();
+
+        imageFile = targetFile;
+        imageView = view;
+        imageBitmap = null;
+        imageWidth = view.getWidth();
+        imageHeight = view.getHeight();        
+        
+        /**
+         *  ダイアログ表示中の処理
+         * 
+         */
+        Thread thread = new Thread(new Runnable()
+        {  
+            public void run()
+            {
+               try
+               {                       
+                       if (imageFile.startsWith("content://") == true)
+                    {
+                       // URIから画像を設定する...OutOfMemory対策付き
+                       imageBitmap = getBitmapFromUri(parent, Uri.parse(imageFile), imageWidth, imageHeight);
+                    }
+                    else
+                    {
+                       // OutOfMemory対策付き...ビットマップのサイズを圧縮して表示
+                       imageBitmap = getBitmap(imageFile, imageWidth, imageHeight);
+                    }
+                       handler.sendEmptyMessage(0);
+               }
+                catch (Exception ex)
+               {
+                       handler.sendEmptyMessage(0);
+               }
+            }
+
+            /**
+             *   画面の更新
+             */
+            private final Handler handler = new Handler()
+            {
+                @Override
+                public void handleMessage(Message msg)
+                {
+                       if ((imageBitmap != null)&&(imageView != null))
+                       {
+                        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
+                        imageView.setImageBitmap(imageBitmap);
+                       }
+                    imageFile = null;
+                    imageView = null;
+                    imageBitmap = null;
+                    imageWidth = 1;
+                    imageHeight = 1;
+
+                       loadingDialog.dismiss();
+                
+                }
+            };   
+        });
+        try
+        {
+            thread.start();
+        }
+        catch (Exception ex)
+        {
+
+        }
+    }
+       
+       /**
+        *   URI経由でビットマップデータを取得する
+        * 
+        * @param context
+        * @param uri
+        * @param width
+        * @param height
+        * @return
+        */
+    public static Bitmap getBitmapFromUri(Context context, Uri uri, int width, int height)
+    {
+        // ファイルの表示方法を若干変更する ⇒ Uri.Parse() から BitmapFactoryを利用する方法へ。
+        BitmapFactory.Options opt = new BitmapFactory.Options();
+
+        // OutOfMemoryエラー対策...一度読み込んで画像サイズを取得
+        opt.inJustDecodeBounds = true;
+        opt.inDither = true;
+        opt.inPurgeable = true;
+        opt.inPreferredConfig = Bitmap.Config.RGB_565;
+
+        InputStream input = null; 
+        try
+        { 
+            input = context.getContentResolver().openInputStream(uri); 
+            BitmapFactory.decodeStream(input, null, opt); 
+            input.close();
+        }
+        catch (Exception ex)
+        {
+               Log.v(Main.APP_IDENTIFIER, "Ex(1): " + ex.toString());
+               if (input != null)
+               {
+                       try
+                       {
+                       input.close();
+                       }
+                       catch (Exception e)
+                       {
+                               //
+                       }
+               }
+        }
+        // 表示サイズに合わせて縮小...表示サイズが取得できなかった場合には、QVGAサイズと仮定する
+        if (width < 10)
+        {
+            width = 320;
+        }
+        if (height < 10)
+        {
+               height = 240;
+        }
+
+        // 画像の縮小サイズを決定する (縦幅、横幅の小さいほうにあわせる)
+        int widthBounds = opt.outWidth / width;
+        int heightBounds = opt.outHeight / height;
+        opt.inSampleSize=Math.min(widthBounds, heightBounds);
+        opt.inJustDecodeBounds = false;
+        opt.inPreferredConfig = Bitmap.Config.RGB_565;
+        
+        // 画像ファイルを応答する
+        input = null; 
+        Bitmap retBitmap = null;
+        try
+        { 
+            input = context.getContentResolver().openInputStream(uri); 
+            retBitmap = BitmapFactory.decodeStream(input, null, opt); 
+            input.close();
+        }
+        catch (Exception ex)
+        {
+               Log.v(Main.APP_IDENTIFIER, "Ex(2): " + ex.toString());
+               if (input != null)
+               {
+                       try
+                       {
+                       input.close();
+                       }
+                       catch (Exception e)
+                       {
+                               //
+                       }
+               }
+        }
+        return (retBitmap);
+    }        
+    
+    /**
+     *   ビットマップデータを取得する
+     * 
+     * @param pictureString
+     * @param width
+     * @param height
+     * @return ビットマップデータ
+     */
+    public static Bitmap getBitmap(String pictureString, int width, int height)
+    {
+
+        // ファイルの表示方法を若干変更する ⇒ Uri.Parse() から BitmapFactoryを利用する方法へ。
+        BitmapFactory.Options opt = new BitmapFactory.Options();
+
+        // OutOfMemoryエラー対策...一度読み込んで画像サイズを取得
+        opt.inJustDecodeBounds = true;
+        opt.inDither = true;
+        BitmapFactory.decodeFile(pictureString, opt);
+
+        // 表示サイズに合わせて縮小...表示サイズが取得できなかった場合には、QVGAサイズと仮定する
+        if (width < 10)
+        {
+            width = 320;
+        }
+        if (height < 10)
+        {
+               height = 240;
+        }
+
+        // 画像の縮小サイズを決定する (縦幅、横幅の小さいほうにあわせる)
+        int widthBounds = opt.outWidth / width;
+        int heightBounds = opt.outHeight / height;
+        opt.inSampleSize=Math.min(widthBounds, heightBounds);
+        opt.inJustDecodeBounds = false;
+        
+        // 画像ファイルを応答する
+       return (BitmapFactory.decodeFile(pictureString, opt));
+    }    
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ItemSelectionDialog.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ItemSelectionDialog.java
new file mode 100644 (file)
index 0000000..a6e1d1b
--- /dev/null
@@ -0,0 +1,161 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+
+
+/**
+ *   アイテムを選択するダイアログを準備する
+ * 
+ * @author MRSa
+ *
+ */
+public class ItemSelectionDialog
+{
+       private Context context = null;
+       private ISelectionItemReceiver resultReceiver = null;
+       private ISelectionItemHolder dataHolder = null;
+       private String  title = "";
+
+       public ItemSelectionDialog(Context arg)
+       {
+               context = arg;
+       }
+
+       /**
+        *  クラスの準備
+        * @param receiver
+        * @param initialMessage
+        */
+       public void prepare(ISelectionItemReceiver receiver, ISelectionItemHolder holder,  String titleMessage)
+       {
+               title = titleMessage;
+               resultReceiver = receiver;
+               dataHolder = holder;
+       }
+       
+       /**
+     *   確認ダイアログを応答する
+     * @return
+     */
+    public Dialog getDialog()
+    {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        
+        // 表示するデータ(ダイアログタイトル、メッセージ)を準備する
+        if (title != null)
+        {
+            builder.setTitle(title);
+        }
+        builder.setCancelable(false);
+        if (dataHolder != null)
+        {
+               if (dataHolder.isMultipleSelection() == false)
+               {
+                builder.setItems(dataHolder.getItems(), new DialogInterface.OnClickListener()
+                {
+                       public void onClick(DialogInterface dialog, int id)
+                       {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.itemSelected(id, dataHolder.getItem(id));
+                          }
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                               
+                       }
+                }); 
+               }
+            else
+            {
+               /**  複数選択の選択肢を準備する **/
+                builder.setMultiChoiceItems(dataHolder.getItems(), dataHolder.getSelectionStatus(), new DialogInterface.OnMultiChoiceClickListener()
+                {
+                       public void onClick(DialogInterface dialog, int which, boolean isChecked)
+                       {
+                           if (resultReceiver != null)
+                           {
+                               resultReceiver.itemSelected(which, dataHolder.getItem(which));
+                           }                           
+                       }
+                });
+
+                /**  複数選択時には、OKボタンを押したときに選択を確定させる。 **/
+                builder.setPositiveButton(context.getString(R.string.confirmYes), new DialogInterface.OnClickListener()
+                {
+                     public void onClick(DialogInterface dialog, int id)
+                     {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.itemSelectedMulti(dataHolder.getItems(), dataHolder.getSelectionStatus());
+                          }
+                         if (ret == true)
+                         {
+                          dialog.dismiss();
+                         }
+                         else
+                         {
+                             dialog.cancel();
+                         }
+                         System.gc();
+                     }
+                 });
+            }
+        }
+
+//        builder.setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, OnMultiChoiceClickListener listener)
+/**
+**/
+        builder.setNegativeButton(context.getString(R.string.confirmNo), new DialogInterface.OnClickListener()
+        {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.canceledSelection();
+                          }
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+        });
+        return (builder.create());     
+    }
+
+    public interface ISelectionItemHolder
+    {
+       public abstract boolean isMultipleSelection();
+
+       public abstract String[] getItems();
+        public abstract String  getItem(int index);
+
+        /** 複数選択時に使用する **/
+        public abstract boolean[] getSelectionStatus();
+        public abstract void setSelectionStatus(int index, boolean isSelected);
+    };
+    
+    public interface ISelectionItemReceiver
+    {
+        public abstract void itemSelected(int index, String itemValue);
+        public abstract void itemSelectedMulti(String[] items, boolean[] status);
+        public abstract void canceledSelection();
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/LineStyleHolder.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/LineStyleHolder.java
new file mode 100644 (file)
index 0000000..7edd7ec
--- /dev/null
@@ -0,0 +1,326 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+/**
+ *    線の形状を保持するクラス
+ * 
+ * @author MRSa
+ *
+ */
+public class LineStyleHolder
+{
+       private Activity activity = null;
+
+       public static final int LINESTYLE_STRAIGHT_NO_ARROW = 0;
+    public static final int LINESTYLE_TREESTYLE_NO_ARROW = 1;
+    public static final int LINESTYLE_CURVESTYLE_NO_ARROW = 2;
+       public static final int LINESTYLE_STRAIGHT_R_ARROW = 3;
+       public static final int LINESTYLE_STRAIGHT_L_ARROW = 4;
+    public static final int LINESTYLE_TREESTYLE_R_ARROW = 5;
+    public static final int LINESTYLE_TREESTYLE_L_ARROW = 6;
+    public static final int LINESTYLE_CURVESTYLE_R_ARROW = 7;
+    public static final int LINESTYLE_CURVESTYLE_L_ARROW = 8;
+
+    public static final int LINESHAPE_NORMAL = 1000;       // 普通の直線
+    public static final int LINESHAPE_DASH =  1001;      // 点線(破線)
+
+    public static final int LINETHICKNESS_THIN = 0;      // 細い線
+       public static final int LINETHICKNESS_MIDDLE = 3;  // 中太線
+       public static final int LINETHICKNESS_HEAVY = 6;    //  太線
+    
+       private int currentLineThickness = LINETHICKNESS_THIN;
+       private int currentLineShape = LINESHAPE_NORMAL;
+       private int currentLineStyle = LINESTYLE_STRAIGHT_NO_ARROW;
+       
+       /**
+        *    コンストラクタ
+        * 
+        * @param arg
+        */
+       public LineStyleHolder(Activity arg)
+       {
+               activity = arg;
+       }
+
+       /**
+        *    ライン形状を読み出す
+        * 
+        */
+       public void prepare()
+       {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+        currentLineStyle = Integer.parseInt(preferences.getString("lineStyle", "0"));
+        currentLineShape = Integer.parseInt(preferences.getString("lineShape", "1000"));
+        currentLineThickness = Integer.parseInt(preferences.getString("lineThickness", "1"));
+               
+       }
+       
+       public int changeLineStyle()
+       {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+        int value = Integer.parseInt(preferences.getString("lineStyle", "0"));
+        switch (value)
+        {
+          case LINESTYLE_STRAIGHT_NO_ARROW:
+              value = LINESTYLE_STRAIGHT_R_ARROW;
+            break;
+          case LINESTYLE_STRAIGHT_R_ARROW:
+              value = LINESTYLE_TREESTYLE_NO_ARROW;
+            break;
+          case LINESTYLE_TREESTYLE_NO_ARROW:
+              value = LINESTYLE_TREESTYLE_R_ARROW;
+              break;
+          case LINESTYLE_TREESTYLE_R_ARROW:
+              value = LINESTYLE_CURVESTYLE_NO_ARROW;
+            break;
+          case LINESTYLE_CURVESTYLE_NO_ARROW:
+              value = LINESTYLE_CURVESTYLE_R_ARROW;
+              break;
+          case LINESTYLE_CURVESTYLE_R_ARROW:
+                 // value = LINESTYLE_STRAIGHT_L_ARROW;  // 左側矢印を作成する場合
+                 value = LINESTYLE_STRAIGHT_NO_ARROW;   // 左側矢印を作成しない場合
+                 break;
+          case LINESTYLE_STRAIGHT_L_ARROW:
+              value = LINESTYLE_TREESTYLE_L_ARROW;
+              break;
+          case LINESTYLE_TREESTYLE_L_ARROW:
+              value = LINESTYLE_CURVESTYLE_L_ARROW;
+              break;
+          case LINESTYLE_CURVESTYLE_L_ARROW:
+          default:
+              value = LINESTYLE_STRAIGHT_NO_ARROW;
+              break;
+        }
+
+        // 文字列としてデータを記録
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putString("lineStyle", "" + value);
+        editor.commit();
+
+        return (value);
+       }
+
+         /**
+          *   接続する線の形状を指定する
+          *   
+          * @param style
+          */
+         public void setLineStyle(int style)
+         {
+                 currentLineStyle = LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW;
+                 switch (style)
+                 {
+                   case LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW:
+                   case LineStyleHolder.LINESTYLE_TREESTYLE_NO_ARROW:
+                   case LineStyleHolder.LINESTYLE_CURVESTYLE_NO_ARROW:
+                   case LineStyleHolder.LINESTYLE_STRAIGHT_R_ARROW:
+                   case LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW:
+                   case LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW:
+                   case LineStyleHolder.LINESTYLE_STRAIGHT_L_ARROW:
+                   case LineStyleHolder.LINESTYLE_TREESTYLE_L_ARROW:
+                   case LineStyleHolder.LINESTYLE_CURVESTYLE_L_ARROW:
+                       currentLineStyle = style;
+                           break;
+
+                   default:
+                       currentLineStyle = LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW;
+                           break;
+                 }     
+
+                 // 文字列としてデータを記録
+             SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+             SharedPreferences.Editor editor = preferences.edit();
+             editor.putString("lineStyle", "" + currentLineStyle);
+             editor.commit();
+         }
+         /**
+          *    接続する線の種類(点線 or 実線) を設定する
+          * 
+          * @param shape
+          */
+         public void setLineShape(int shape)
+         {
+                 currentLineShape = LineStyleHolder.LINESHAPE_NORMAL;
+                 switch (shape)
+                 {
+                   case LineStyleHolder.LINESHAPE_DASH:
+                   case LineStyleHolder.LINESHAPE_NORMAL:
+                       currentLineShape = shape;
+                           break;
+
+                   default:
+                       currentLineShape = LineStyleHolder.LINESHAPE_NORMAL;
+                           break;
+                 }
+
+                 // 文字列としてデータを記録
+             SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+             SharedPreferences.Editor editor = preferences.edit();
+             editor.putString("lineShape", "" + currentLineShape);
+             editor.commit();
+         }     
+
+         /**
+          *    接続する線の太さ を設定する
+          * 
+          * @param shape
+          */
+         public void setLineThickness(int thickness)
+         {
+                 currentLineThickness = LineStyleHolder.LINETHICKNESS_THIN;
+                 switch (thickness)
+                 {
+                   case LineStyleHolder.LINETHICKNESS_HEAVY:
+                   case LineStyleHolder.LINETHICKNESS_MIDDLE:
+                   case LineStyleHolder.LINETHICKNESS_THIN:
+                       currentLineThickness = thickness;
+                           break;
+
+                   default:
+                       currentLineThickness = LineStyleHolder.LINETHICKNESS_THIN;
+                           break;
+                 }
+
+                 // 文字列としてデータを記録
+             SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+             SharedPreferences.Editor editor = preferences.edit();
+             editor.putString("lineThickness", "" + currentLineThickness);
+             editor.commit();
+         }     
+
+         /**
+          *    接続する線の形状を応答する
+          * 
+          * @return 接続する線の形状
+          */
+         public int getLineStyle()
+         {
+                 return (currentLineStyle);
+         }
+         
+         /**
+          *   接続する線の種類(点線 or 実線) を応答する
+          * 
+          * @return 接続する線の種類
+          */
+         public int getLineShape()
+         {
+                 return (currentLineShape);
+         }
+
+         /**
+          *   接続する線の太さを応答する
+          * 
+          * @return 接続する線の太さ
+          */
+         public int getLineThickness()
+         {
+                 return (currentLineThickness);
+         }
+
+           /**
+            *    現在の太さのイメージのIDを応答する
+            * 
+            * @param thickness
+            * @return
+            */
+           public static int getLineThicknessImageId(int thickness)
+           {
+               int buttonId = R.drawable.btn_line_thin;
+               switch (thickness)
+               {
+                     case LineStyleHolder.LINETHICKNESS_HEAVY:
+                   buttonId = R.drawable.btn_line_heavy;
+                   break;
+
+                 case LineStyleHolder.LINETHICKNESS_MIDDLE:
+                     buttonId = R.drawable.btn_line_middle;
+                     break;
+
+                 case LineStyleHolder.LINETHICKNESS_THIN:
+                 default:
+                         buttonId = R.drawable.btn_line_thin;
+                         break;
+               }
+               return (buttonId);
+           }    
+           
+           /**
+            * 
+            * 
+            * @param currentLineStyle
+            * @param currentLineShape
+            * @return
+            */
+           public static int getLineShapeImageId(int currentLineStyle, int currentLineShape)
+           {
+               int buttonId = R.drawable.btn_straight;
+               
+               if ((currentLineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_NO_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+               {
+                       buttonId = R.drawable.btn_tree;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_NO_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+               {
+                       buttonId = R.drawable.btn_curve;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+               {
+                       buttonId = R.drawable.btn_straight_dash;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_NO_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+               {
+                       buttonId = R.drawable.btn_tree_dash;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_NO_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+               {
+                       buttonId = R.drawable.btn_curve_dash;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_R_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+               {
+                       buttonId = R.drawable.btn_straight_rarrow;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+               {
+                       buttonId = R.drawable.btn_tree_rarrow;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+               {
+                       buttonId = R.drawable.btn_curve_rarrow;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_R_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+               {
+                       buttonId = R.drawable.btn_straight_rarrow_dash;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+               {
+                       buttonId = R.drawable.btn_tree_rarrow_dash;
+               }
+               else if ((currentLineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+               {
+                       buttonId = R.drawable.btn_curve_rarrow_dash;
+               }
+               /**
+               else  if ((currentLineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW)&&
+                               (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+               {
+                       buttonId = R.drawable.btn_straight;
+               }
+               **/
+               return (buttonId);
+           }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/Main.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/Main.java
new file mode 100644 (file)
index 0000000..6ff63ab
--- /dev/null
@@ -0,0 +1,290 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.Manifest;
+import android.app.Dialog;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.Window;
+
+/**
+ *   メイン画面の処理
+ * 
+ * @author MRSa
+ *
+ */
+public class Main extends  AppCompatActivity
+{
+    public static final String APP_IDENTIFIER = "Gokigen";
+    public static final String APP_BASEDIR = "/MeMoMa";
+       public static final String APP_NAMESPACE = "gokigen";
+
+    private MeMoMaListener listener = null;  // イベント処理クラス
+
+    
+       /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) 
+    {
+        final int REQUEST_NEED_PERMISSIONS = 1010;
+
+        super.onCreate(savedInstanceState);
+
+        // データ保存・展開クラス を生成する
+        // リスナクラスを生成する
+        listener = new MeMoMaListener(this, new MeMoMaDataInOutManager(this));
+
+        // タイトルにプログレスバーを出せるようにする
+        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+
+        // タイトルバーにアクションバーを出す
+//       requestWindowFeature(Window.FEATURE_ACTION_BAR);
+        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
+
+        // レイアウトを設定する **/
+        setContentView(R.layout.main);
+
+        // 外部メモリアクセス権のオプトイン
+        if ((ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
+            ActivityCompat.requestPermissions(this,
+                    new String[]{
+                            Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                    },
+                    REQUEST_NEED_PERMISSIONS);
+        }
+
+        try
+        {
+            // リスナクラスの準備
+            listener.prepareListener();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *  メニューの生成
+     */
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu)
+    {
+        try
+        {
+            menu = listener.onCreateOptionsMenu(menu);
+            return (super.onCreateOptionsMenu(menu));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (false);
+    }
+    
+    /**
+     *  メニューアイテムの選択
+     */
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item)
+    {
+        try
+        {
+            return (listener.onOptionsItemSelected(item));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (false);
+    }
+    
+    /**
+     *  メニュー表示前の処理
+     */
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu)
+    {
+        try
+        {
+            listener.onPrepareOptionsMenu(menu);
+            return (super.onPrepareOptionsMenu(menu));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (false);
+    }
+
+    /**
+     *  画面が裏に回ったときの処理
+     */
+    @Override
+    public void onPause()
+    {
+        super.onPause();
+        try
+        {
+            // 動作を止めるようイベント処理クラスに指示する
+               listener.shutdown();            
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+    
+    /**
+     *  画面が表に出てきたときの処理
+     */
+    @Override
+    public void onResume()
+    {
+        super.onResume();
+        try
+        {
+               // 動作準備するようイベント処理クラスに指示する
+               listener.prepareToStart();
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+
+    /**
+     *   終了時の処理
+     * 
+     */
+    @Override
+    protected void onDestroy()
+    {
+        try
+        {
+            listener.finishListener();
+            super.onDestroy();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 
+     */
+    @Override
+    protected void onStart()
+    {
+        super.onStart();
+    }
+
+    /**
+     * 
+     */
+    @Override
+    protected void onStop()
+    {
+        super.onStop();
+    }
+
+    /**
+     * 
+     */
+    @Override
+    protected void onSaveInstanceState(Bundle outState)
+    {
+        try
+        {
+            super.onSaveInstanceState(outState);
+            if (listener != null)
+            {
+                // ここでActivityの情報を覚える
+                listener.onSaveInstanceState(outState);
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 
+     */
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState)
+    {
+        super.onRestoreInstanceState(savedInstanceState);
+        try
+        {
+            if (listener != null)
+            {
+                // ここでActivityの情報を展開する
+                listener.onRestoreInstanceState(savedInstanceState);
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *  ダイアログ表示の準備
+     * 
+     */
+    @Override
+    protected Dialog onCreateDialog(int id)
+    {
+        try
+        {
+            return (listener.onCreateDialog(id));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (null);
+    }
+
+    /**
+     *  ダイアログ表示の準備
+     * 
+     */
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog)
+    {
+        try
+        {
+            listener.onPrepareDialog(id, dialog);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+    
+    /**
+     *  子画面から応答をもらったときの処理
+     */
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data)
+    {
+        try
+        {
+            // 子画面からもらった情報の応答処理をイベント処理クラスに依頼する
+               listener.onActivityResult(requestCode, resultCode, data);
+        }
+        catch (Exception ex)
+        {
+           ex.printStackTrace();
+        }
+    }    
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaCanvasDrawer.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaCanvasDrawer.java
new file mode 100644 (file)
index 0000000..38ea001
--- /dev/null
@@ -0,0 +1,1285 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.util.Enumeration;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.DashPathEffect;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.MotionEvent;
+import         android.view.GestureDetector;
+import android.view.ScaleGestureDetector;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+/**
+ *    メモまの描画クラス
+ *    
+ * @author MRSa
+ *
+ */
+public class MeMoMaCanvasDrawer implements  ICanvasDrawer,  GestureDetector.OnGestureListener, ScaleGestureDetector.OnScaleGestureListener, SeekBar.OnSeekBarChangeListener
+{
+       public static final float OBJECTLABEL_MARGIN = 8.0f;
+       public static final float OBJECTLABEL_MARGIN_WIDTH = 24.0f;
+
+       public static final int BACKGROUND_COLOR_DEFAULT = 0xff004000;
+       private int backgroundColor = BACKGROUND_COLOR_DEFAULT;
+       
+       private MeMoMaObjectHolder.PositionObject selectedPosition = null;
+       private float tempPosX = Float.MIN_VALUE;
+       private float tempPosY = Float.MIN_VALUE;
+       private float downPosX = Float.MIN_VALUE;
+       private float downPosY = Float.MIN_VALUE;
+       
+       // 以下の値は、MeMoMaListenerで初期値を設定する
+       private int objectStyle = MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE;
+       
+       private LineStyleHolder lineStyleHolder = null;
+
+       private float drawScale = 1.0f;    // 表示の倍率
+       private float drawTransX  = 0.0f;   // 並行移動距離 (X)
+       private float drawTransY  = 0.0f;   // 並行移動距離 (Y)
+       private boolean onScaling = false;  // ピンチイン・ピンチアウト操作しているかどうかを示す
+       private int currentScaleBar= 50;  // 現在のピンチイン・ピンチアウト倍率
+       
+       private boolean onGestureProcessed = false;   // 長押し時の処理を行なっているかどうかを示す。
+       
+       private float screenWidth = 0.0f;  // 表示領域の幅
+       private float screenHeight = 0.0f; // 表示領域の高さ
+
+       private int displayObjectInformation = 1;  // オブジェクトラベルの表示
+       
+       private String backgroundBitmapUri = null;
+       private Bitmap backgroundBitmap = null;
+
+       private MeMoMaObjectHolder objectHolder = null;
+       private MeMoMaConnectLineHolder lineHolder = null;
+       private IObjectSelectionReceiver selectionReceiver = null;
+
+       private GestureDetector gestureDetector = null;
+       private ScaleGestureDetector scaleGestureDetector = null;
+
+       private Activity parent = null;
+       
+       /**
+      *   コンストラクタ
+      *   
+      */
+         public MeMoMaCanvasDrawer(Activity argument, MeMoMaObjectHolder object, LineStyleHolder styleHolder, IObjectSelectionReceiver receiver)
+         {
+                 objectHolder = object;
+                 lineHolder = objectHolder.getConnectLineHolder();
+                 selectionReceiver = receiver;
+                 lineStyleHolder = styleHolder;
+                 parent = argument;
+
+                 // ジェスチャを検出するクラスを生成する
+                 gestureDetector = new GestureDetector(argument, this);
+                 scaleGestureDetector = new ScaleGestureDetector(argument, this);
+
+                 // ズーム倍率を展開する
+                 restoreTranslateAndZoomScale();
+         }
+
+         /**
+          *   オブジェクトの形状を変更する
+          *   (ここで指定された形状のチェックを行っておく。)
+          * 
+          * @param style
+          */
+         public void setObjectStyle(int style)
+         {
+                 switch (style)
+                 {
+                   case MeMoMaObjectHolder.DRAWSTYLE_OVAL:
+                   case MeMoMaObjectHolder.DRAWSTYLE_ROUNDRECT:
+                   case MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE:
+                   case MeMoMaObjectHolder.DRAWSTYLE_DIAMOND:
+                   case MeMoMaObjectHolder.DRAWSTYLE_KEYBOARD:
+                   case MeMoMaObjectHolder.DRAWSTYLE_PAPER:
+                   case MeMoMaObjectHolder.DRAWSTYLE_DRUM:
+                   case MeMoMaObjectHolder.DRAWSTYLE_PARALLELOGRAM:
+                   case MeMoMaObjectHolder.DRAWSTYLE_HEXAGONAL:
+                   case MeMoMaObjectHolder.DRAWSTYLE_CIRCLE:
+                   case MeMoMaObjectHolder.DRAWSTYLE_NO_REGION:
+                   case MeMoMaObjectHolder.DRAWSTYLE_LOOP_START:
+                   case MeMoMaObjectHolder.DRAWSTYLE_LOOP_END:
+                   case MeMoMaObjectHolder.DRAWSTYLE_LEFT_ARROW:
+                   case MeMoMaObjectHolder.DRAWSTYLE_DOWN_ARROW:
+                   case MeMoMaObjectHolder.DRAWSTYLE_UP_ARROW:
+                   case MeMoMaObjectHolder.DRAWSTYLE_RIGHT_ARROW:
+                       objectStyle = style;
+                           break;
+
+                   default:
+                       objectStyle = MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE;
+                           break;
+                 }     
+         }
+
+         /**
+          * 
+          * @param uri
+          */
+         public void updateBackgroundBitmap(String uri, int width, int height)
+         {
+                 // 背景画像の文字列を記憶する
+                 backgroundBitmapUri = uri;
+
+                 // とりあえず、背景画像をクリアしてガベコレする。
+                 backgroundBitmap = null;
+                 System.gc();
+                 if (uri.isEmpty() == true)
+                 {
+                         // 背景画像の指定がなかったので、ここでリターンする。
+                         return;
+                 }
+                 try
+                 {
+                         // とりあえず設定する情報をログに残してみる
+                         Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::updateBackgroundBitmap() : w:" + width + " , h:"+ height + " " + uri);
+
+                         // 背景画像を取得して設定する。
+                         backgroundBitmap = ImageLoader.getBitmapFromUri(parent, ImageLoader.parseUri(uri), width, height);
+                 }
+                 catch (Exception ex)
+                 {
+                         Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::updateBackgroundBitmap() : " + uri + " , "+ ex.toString());
+                         ex.printStackTrace();
+                         backgroundBitmap = null;
+                         backgroundBitmapUri = "";
+                         System.gc();
+                 }     
+                 return;
+         }       
+         
+         /**
+          *   背景画像を設定する
+          *   
+          * @param uri
+          */
+         public void setBackgroundUri(String uri)
+         {
+                 backgroundBitmapUri = uri;
+         }
+         
+         /**
+          *   背景色を(文字列で)設定する
+          * 
+          * @param colorString
+          */
+         public void setBackgroundColor(String colorString)
+         {
+                 try
+                 {
+                         backgroundColor = Color.parseColor(colorString);
+                         return;
+                 }
+                 catch (Exception ex)
+                 {
+                         //
+              //Log.v(Main.APP_IDENTIFIER, "Ex:" + ex.toString() + " " + ex.getMessage());
+                 }
+                 backgroundColor = BACKGROUND_COLOR_DEFAULT;
+         }
+
+         /**
+          *    初期化ロジックを設定する
+          * 
+          */
+         public void prepareToStart(int width, int height)
+         {
+          Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::prepareToStart() " + "x:" + width + " , " + "y:" + height);
+
+          // 背景画像を更新する
+                 //updateBackgroundBitmap(backgroundBitmapUri, width, height);
+
+                 // Preferenceを読み出す
+                 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+                 displayObjectInformation = Integer.parseInt(preferences.getString("objectPrintData", "1"));
+         }     
+
+         /**
+          *    画面の大きさが変わってしまった場合...
+          * 
+          */
+         public  void changedScreenProperty(int format, int width, int height)
+         {
+                 // 背景画像を更新する
+                 updateBackgroundBitmap(backgroundBitmapUri, width, height);
+                 
+                 // 表示画面サイズを覚える
+                 screenWidth = width;
+                 screenHeight = height;
+
+          Log.v(Main.APP_IDENTIFIER, "changedScreenProperty() " + "x:" + width + " , " + "y:" + height);
+         }
+
+
+         /**
+          *    キャンバスにオブジェクト(と接続線)を表示する
+          * 
+          */
+         public void drawOnCanvas(Canvas canvas)
+         {
+               //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::drawOnCanvas()");
+               try
+               {
+                       // 画面全体をクリアする
+                       //canvas.drawColor(Color.argb(backgroundColorAlfa, backgroundColorRed, backgroundColorGreen, backgroundColorBlue), Mode.CLEAR);
+                       canvas.drawColor(backgroundColor);                              
+                       
+                       // 背景画像が設定されていた場合は、背景画像を描画する
+                       if (backgroundBitmap != null)
+                       {
+                           canvas.drawBitmap(backgroundBitmap, 0, 0, new Paint());
+                       }
+
+                       // 表示位置を移動させる
+                       canvas.translate(drawTransX, drawTransY);
+
+                       // 画面の表示領域を拡大・縮小する
+                       canvas.scale(drawScale, drawScale);
+
+                       // オブジェクト間の接続線をすべて表示する
+                       drawConnectionLines(canvas, 0.0f, 0.0f);
+                       
+                // オブジェクトをすべて表示
+                       drawObjects(canvas, 0.0f, 0.0f);
+
+                /**  移動中かどうかのチェックを行う。 **/
+                       if (isFlicking(canvas) == true)
+                       {
+                    // 移動中の場合、フリック時の軌跡と現在位置を表示する
+                           drawTrackAndPositions(canvas);
+                       }
+               }
+               catch (Exception ex)
+               {
+                       // 例外発生...でもそのときには何もしない
+                       Log.v(Main.APP_IDENTIFIER, "drawOnCanvas() ex: " + ex.getMessage());
+               }
+         }
+
+         /**
+          *    オブジェクトをBitmapCanvas上に描く
+          * 
+          */
+         public void drawOnBitmapCanvas(Canvas canvas, float offsetX, float offsetY)
+         {
+               try
+               {
+                       Paint paint = new Paint();
+
+                       // 画面全体をクリアする
+                       canvas.drawColor(backgroundColor);                              
+                       
+                       // 背景画像が設定されていた場合は、背景画像を描画する
+                       if (backgroundBitmap != null)
+                       {
+                           canvas.drawBitmap(backgroundBitmap, offsetX, offsetY, paint);
+                       }
+
+                       // オブジェクト間の接続線をすべて表示する
+                       drawConnectionLines(canvas, offsetX, offsetY);
+                       
+                // オブジェクトをすべて表示
+                       drawObjects(canvas, offsetX, offsetY);
+                       
+                       // タイトルとめもまのアイコンを表示する : 文字の色は黒でいいのかな...
+                       Bitmap bitmap = BitmapFactory.decodeResource(parent.getResources(), R.drawable.icon1);
+                       canvas.drawBitmap(bitmap, 2.0f, 2.0f, paint);
+                       canvas.drawText(objectHolder.getDataTitle(), (bitmap.getWidth() + 10.0f), 32.0f, paint);
+
+               }
+               catch (Exception ex)
+               {
+                       // 例外発生...でもそのときには何もしない
+                       Log.v(Main.APP_IDENTIFIER, "drawOnBitmapCanvas() ex: " + ex.toString() + " " + ex.getMessage());
+               }
+         }
+
+         /**
+          *    オブジェクト間の接続線を表示する
+          * 
+          * @param canvas
+          */
+         private void drawConnectionLines(Canvas canvas, float offsetX, float offsetY)
+         {
+               // オブジェクトの色と枠線を設定する (連続線用)
+               Paint paint = new Paint();
+               paint.setColor(Color.WHITE);
+               paint.setStyle(Paint.Style.STROKE);
+
+               // オブジェクトの色と枠線を設定する  (点線用)
+               Paint dashLinePaint = new Paint();
+               dashLinePaint.setColor(Color.WHITE);
+               dashLinePaint.setStyle(Paint.Style.STROKE);
+               dashLinePaint.setPathEffect(new DashPathEffect(new float[]{ 5.0f, 5.0f }, 0));          
+               
+               // オブジェクトの描画 (保持しているものはすべて表示する)
+               Enumeration<Integer> keys = lineHolder.getLineKeys();
+               while (keys.hasMoreElements())
+               {
+                   Integer key = keys.nextElement();
+                   MeMoMaConnectLineHolder.ObjectConnector line = lineHolder.getLine(key);
+                   if (line.key > 0)
+                   {
+                    // 実際にラインを引く
+                       drawLine(canvas, paint, dashLinePaint, line, offsetX, offsetY);
+                   }
+                   else
+                   {
+                       // ここは呼ばれないはず。。。消したはずのものが残っている
+                       Log.v(Main.APP_IDENTIFIER, "DETECTED DELETED LINE");
+                   }
+               }
+         }
+
+         /** 
+          *    接続する線を引く
+       *
+          * @param canvas
+          * @param paint
+          * @param line
+          */
+         public void drawLine(Canvas canvas, Paint paint, Paint dashPaint, MeMoMaConnectLineHolder.ObjectConnector line, float offsetX, float offsetY)
+         {
+                 try
+                 {
+                         if ((objectHolder == null)||(canvas == null))
+                         {
+                                 // なにもしない
+                                 return;
+                         }
+
+                         MeMoMaObjectHolder.PositionObject from = objectHolder.getPosition(line.fromObjectKey);
+                         MeMoMaObjectHolder.PositionObject to = objectHolder.getPosition(line.toObjectKey);
+                         if ((from == null)||(to == null))
+                         {
+                                 // なにもしない
+                                 return;
+                         }
+
+                         // ラインの太さを設定する。
+                         paint.setStrokeWidth((float) line.lineThickness);
+
+                         // ラインの太さを設定する。
+                         dashPaint.setStrokeWidth((float) line.lineThickness);
+
+                         // ラインのスタイル(連続線 or 点線)を設定する
+                         Paint linePaint = (line.lineShape == LineStyleHolder.LINESHAPE_DASH) ? dashPaint : paint;
+                         
+                         // 初期値として、各オブジェクトの中心座標を設定する
+                         float startX = from.rect.centerX() + offsetX;
+                         float endX = to.rect.centerX() + offsetX;
+                         float startY = from.rect.centerY() + offsetY;
+                         float endY = to.rect.centerY() + offsetY;
+                         
+                         // Y座標の線の位置を補正する
+                         if (from.rect.bottom < to.rect.top)
+                         {
+                  startY = from.rect.bottom + offsetY;
+                  endY = to.rect.top + offsetY;
+                         }
+                         else if (from.rect.top > to.rect.bottom)
+                         {
+                  startY = from.rect.top + offsetY;
+                  endY = to.rect.bottom + offsetY;
+                         }
+
+                         // X座標の線の位置を補正する (Y座標が補正されていないとき)
+              if ((startY != (from.rect.top + offsetY))&&(startY != (from.rect.bottom + offsetY)))
+                         {
+                         if (from.rect.right < to.rect.left)
+                         {
+                      startX = from.rect.right + offsetX;
+                      endX = to.rect.left + offsetX;
+                         }
+                         else if (from.rect.left > to.rect.right)
+                         {
+                      startX = from.rect.left + offsetX;
+                      endX = to.rect.right + offsetX; 
+                         }
+                         }
+
+                         if ((line.lineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_NO_ARROW)||
+                                         (line.lineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_L_ARROW)||
+                                         (line.lineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW))
+                         {
+                                 // ツリー形式のように接続する ... 
+                                 if (startX == (from.rect.centerX() + offsetX))
+                                 {
+                                         float middleY = (startY + endY) / 2;
+                                     canvas.drawLine(startX, startY, startX, middleY, linePaint);
+                                     canvas.drawLine(startX, middleY, endX, middleY, linePaint);
+                                     canvas.drawLine(endX, middleY, endX, endY, linePaint);
+                                     
+                                     /**  やじるしをつける処理 **/
+                                     if (line.lineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_L_ARROW)
+                                     {
+                                         // 始点に矢印をつける
+                                         ObjectShapeDrawer.drawArrowTree(canvas, paint, startX,startY, middleY, false);
+                                     }
+                                     else if (line.lineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW)
+                                     {
+                                         // 終点に矢印をつける
+                                         ObjectShapeDrawer.drawArrowTree(canvas, paint, endX, endY, middleY, false);
+                                     }
+                                 }
+                                 else
+                                 {
+                                         float middleX = (startX + endX) / 2;
+                                     canvas.drawLine(startX, startY, middleX, startY, linePaint);
+                                     canvas.drawLine(middleX, startY, middleX, endY, linePaint);
+                                     canvas.drawLine(middleX, endY, endX, endY, linePaint);
+
+                                     /**  やじるし(三角形)をつける処理 **/
+                                     if (line.lineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_L_ARROW)
+                                     {
+                                         // 始点に矢印をつける
+                                         ObjectShapeDrawer.drawArrowTree(canvas, paint, startX, startY, middleX, true);
+                                     }
+                                     else if (line.lineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW)
+                                     {
+                                         // 終点に矢印をつける
+                                         ObjectShapeDrawer.drawArrowTree(canvas, paint, endX,endY, middleX, true);
+                                     }
+                                 }
+                         }
+                         else if ((line.lineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_NO_ARROW)||
+                                         (line.lineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_L_ARROW)||
+                                         (line.lineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW))
+                         {
+                  // 曲線で接続する
+                                 float middleX = (startX + endX) / 2;
+                                 float middleY = (startY + endY) / 2;
+                                 float x1 = (startX + middleX) / 2;
+                                 float y1 = middleY;
+                                 float x2 = (middleX + endX) / 2;
+                                 float y2 = middleY;
+                                 
+                             Path pathLine = new Path();
+                             pathLine.moveTo(startX, startY);
+                             pathLine.cubicTo(x1, y1, x2, y2, endX, endY);
+                             canvas.drawPath(pathLine, linePaint);
+
+                             /**  やじるしをつける処理 **/
+                             if (line.lineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_L_ARROW)
+                             {
+                                 // 始点に矢印をつける
+                                 ObjectShapeDrawer.drawArrow(canvas, paint, startX, startY, endX, endY);
+                             }
+                             else if (line.lineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW)
+                             {
+                                 // 終点に矢印をつける
+                                 ObjectShapeDrawer.drawArrow(canvas, paint, endX, endY, startX, startY);
+                             }
+                         }
+              else  // if (line.lineStyle == MeMoMaConnectLineHolder.LINESTYLE_STRAIGHT)
+                         {
+                             // 直線で接続する
+                             canvas.drawLine(startX, startY, endX, endY, linePaint);
+                             
+                             /**  やじるしをつける処理 **/
+                             if (line.lineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_L_ARROW)
+                             {
+                                 // 始点に矢印をつける
+                                 ObjectShapeDrawer.drawArrow(canvas, paint, startX, startY, endX, endY);
+                             }
+                             else if (line.lineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_R_ARROW)
+                             {
+                                 // 終点に矢印をつける
+                                 ObjectShapeDrawer.drawArrow(canvas, paint, endX, endY, startX, startY);
+                             }
+                         }
+                 }
+                 catch (Exception ex)
+                 {
+                         // なにもしない
+                         Log.v(Main.APP_IDENTIFIER, "EXCEPTION :" + ex.toString());
+                 }
+         }       
+         
+    /**
+     *   オブジェクトを動かしている最中かどうかの判定を行う。
+     * 
+     * @param canvas
+     * @return  trueなら、動かしている最中
+     */
+    private boolean isFlicking(Canvas canvas)
+    {
+        //int width = canvas.getWidth();
+        //int height = canvas.getHeight();
+        if ((tempPosX == Float.MIN_VALUE)||(tempPosY == Float.MIN_VALUE))
+        {
+            return (false);
+        }
+        return (true);
+    }
+
+    /**
+     *   フリック時の軌跡と現在地点を表示する
+     * 
+     * @param canvas
+     */
+    private void drawTrackAndPositions(Canvas canvas)
+    {
+        // フリック時の軌跡を表示する
+       float x = (tempPosX - drawTransX) / drawScale;
+       float y = (tempPosY - drawTransY) / drawScale;
+
+       Paint paint = new Paint();
+       paint.setStyle(Paint.Style.STROKE);
+        paint.setColor(Color.GRAY);
+        if (selectedPosition != null)
+        {
+               float objX = (selectedPosition.rect.right - selectedPosition.rect.left) / 2;
+               float objY = (selectedPosition.rect.bottom - selectedPosition.rect.top) / 2;
+           canvas.drawLine(selectedPosition.rect.centerX(), selectedPosition.rect.centerY(), x, y, paint);
+            canvas.drawRect((x - objX), (y - objY), (x + objX), (y + objY), paint);
+
+            // 現在地点の表示
+            drawObject(canvas, selectedPosition, true, 0.0f, 0.0f);
+        }
+        else   // オブジェクト非選択時の表示
+        {
+               int data = selectionReceiver.touchedVacantArea();
+               if (data ==OperationModeHolder.OPERATIONMODE_MOVE)
+               {
+                // 移動モードのとき... (表示領域を移動させる)
+                       drawTransX = (tempPosX - downPosX);
+                       drawTransY = (tempPosY - downPosY);
+
+                       //  表示領域の移動を記憶する
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+               SharedPreferences.Editor editor = preferences.edit();
+               editor.putFloat("drawTransX", drawTransX);
+               editor.putFloat("drawTransY", drawTransY);
+               editor.commit();                
+               }
+               else
+               {
+                       // 移動モード以外
+               paint.setColor(Color.YELLOW);
+                   canvas.drawLine(((downPosX) / drawScale), ((downPosY) / drawScale), x,  y, paint);
+               }
+        }
+    }
+
+    /**
+     *    オブジェクト(1個)を表示する
+     * 
+     * @param canvas
+     * @param paint
+     * @param pos
+     */
+    private void drawObject(Canvas canvas, MeMoMaObjectHolder.PositionObject object, boolean isMoving, float offsetX, float offsetY)
+    {
+       float label_offsetX = OBJECTLABEL_MARGIN;
+       float label_offsetY = 0.0f;
+
+        // オブジェクトの色と枠線を設定する
+       Paint paint = new Paint();
+       if (isMoving == true)
+       {
+            paint.setColor(Color.YELLOW);
+               paint.setStyle(Paint.Style.STROKE);
+            paint.setStrokeWidth(object.strokeWidth);
+       }
+       else
+       {
+            paint.setColor(object.objectColor);
+            paint.setStyle(Paint.Style.valueOf(object.paintStyle));
+            paint.setStrokeWidth(object.strokeWidth);
+       }
+       // 図形の形状に合わせて描画する
+       RectF objectShape = new RectF(object.rect);
+       objectShape.left = objectShape.left + offsetX;
+       objectShape.right = objectShape.right + offsetX;
+       objectShape.top = objectShape.top + offsetY;
+       objectShape.bottom = objectShape.bottom + offsetY;
+       
+       if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_OVAL)
+               {
+                       // 楕円形の描画
+               label_offsetY = ObjectShapeDrawer.drawObjectOval(canvas, objectShape, paint);
+               }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_ROUNDRECT)
+               {
+                       // 丸角四角形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectRoundRect(canvas, objectShape, paint);
+               }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DIAMOND)
+               {
+                       // 菱形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectDiamond(canvas, objectShape, paint);
+            label_offsetX = OBJECTLABEL_MARGIN;
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_KEYBOARD)
+               {
+                       // 台形(キーボード型)の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectKeyboard(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_PARALLELOGRAM)
+               {
+                       // 平行四辺形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectParallelogram(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_HEXAGONAL)
+               {
+                       // 六角形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectHexagonal(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_PAPER)
+               {
+                       // 書類の形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectPaper(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DRUM)
+               {
+                       // 円柱の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectDrum(canvas, objectShape, paint, Paint.Style.valueOf(object.paintStyle));
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_CIRCLE)
+               {
+                       // 円を描画する
+                       label_offsetY = ObjectShapeDrawer.drawObjectCircle(canvas, objectShape, paint);
+               }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_NO_REGION)
+               {
+                         // 枠なしを描画(?)する ... なにもしない
+                         if (object.label.length() == 0)
+                         {
+                                 // 何も表示しないとわからないので、ラベルが無いときには枠を表示する
+                                 ObjectShapeDrawer.drawObjectNoRegion(canvas, objectShape, paint);
+                         }
+               }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LOOP_START)
+               {
+                       // ループ開始図形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectLoopStart(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LOOP_END)
+               {
+                       // ループ終了図形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectLoopEnd(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LEFT_ARROW)
+               {
+                       // 左側矢印図形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectLeftArrow(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DOWN_ARROW)
+               {
+                       // 下側矢印図形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectDownArrow(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_UP_ARROW)
+               {
+                       // 上側矢印図形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectUpArrow(canvas, objectShape, paint);
+        }
+               else if (object.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_RIGHT_ARROW)
+               {
+                       // 右側矢印図形の描画
+                       label_offsetY = ObjectShapeDrawer.drawObjectRightArrow(canvas, objectShape, paint);
+        }
+               else // if (pos.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE)
+        {
+            // 四角形を描画する
+            label_offsetY = ObjectShapeDrawer.drawObjectRect(canvas, objectShape, paint);
+        }
+
+        // 文字サイズを設定する。
+        paint.setTextSize(object.fontSize);
+
+        // 文字ラベルを表示する
+               ObjectShapeDrawer.drawTextLabel(canvas, paint, object, objectShape, displayObjectInformation, label_offsetX, label_offsetY);
+    }
+
+    /**
+     *   オブジェクトをすべて表示する
+     *
+     * @param canvas
+     */
+    private void drawObjects(Canvas canvas , float offsetX, float offsetY)
+    {
+       // オブジェクトの描画 (保持しているものはすべて表示する)
+       Enumeration<Integer> keys = objectHolder.getObjectKeys();
+        while (keys.hasMoreElements())
+        {
+            Integer key = keys.nextElement();
+            MeMoMaObjectHolder.PositionObject pos = objectHolder.getPosition(key);
+            drawObject(canvas, pos, false, offsetX, offsetY);
+        }
+    }
+
+    /**
+     *   タッチされたタイミングでの処理
+     * @param event
+     * @return
+     */
+    private boolean onTouchDown(MotionEvent event)
+    {
+       // タッチ位置を記憶する
+       downPosX = event.getX() - drawTransX;
+       downPosY = event.getY() - drawTransY;
+
+       // タッチ位置をオブジェクト画像の座標に変換する
+       float x = downPosX / drawScale;
+       float y = downPosY / drawScale;
+
+       // タッチ位置にオブジェクトが存在するか確認する
+       selectedPosition = checkSelectedObject(x, y);
+       if (selectedPosition == null)
+       {
+               // 最初にタップしたときの位置を selectedPositionに設定する
+               int data = selectionReceiver.touchedVacantArea();
+               if (data == OperationModeHolder.OPERATIONMODE_CREATE)
+               {
+                       // オブジェクト作成モードのとき...オブジェクトを生成する
+                       selectedPosition = objectHolder.createPosition(x, y, objectStyle);
+                       
+                       // オブジェクトが生成されたことを通知する
+                       selectionReceiver.objectCreated();                      
+               }
+               else if (data ==OperationModeHolder.OPERATIONMODE_MOVE)
+               {
+                       // 移動モードのとき
+               }
+               else // if (data ==ChangeDrawMode.OPERATIONMODE_DELETE)
+               {
+                       // 削除モードのとき...何もしない
+               }
+       }
+        return (false);
+    }
+
+    /**
+     *   タッチが離されたタイミングでの処理
+     * @param event
+     * @return
+     */
+    private boolean onTouchUp(MotionEvent event)
+    {
+       boolean longPress = false;
+        if (onGestureProcessed == true)
+        {
+               // ロングタッチ中だった場合...フラグを落とす
+               onGestureProcessed = false;
+               longPress = true;
+        }
+
+        // タッチ位置をオブジェクト画像の座標に変換する
+       float x = (event.getX() - drawTransX) / drawScale;
+       float y = (event.getY() - drawTransY) / drawScale;
+
+       if (selectedPosition == null)
+        {
+               int data = selectionReceiver.touchUppedVacantArea();
+               if (data == OperationModeHolder.OPERATIONMODE_DELETE)
+               {
+                if ((tempPosX == Float.MIN_VALUE)||(tempPosY == Float.MIN_VALUE)||(downPosX == Float.MIN_VALUE)||(downPosY == Float.MIN_VALUE))
+                {
+                       // タッチが2つ揃っていないので、何もしない。
+                       Log.v(Main.APP_IDENTIFIER, "onTouchUp : (" + downPosX + "," + downPosY + ") [" + drawScale + "] (" + tempPosX + "," + tempPosY + ") [" + drawTransX + "," + drawTransY + "]");
+                    return (false);    
+                }
+
+                       // タッチが離された位置にオブジェクトがおらず、オブジェクトが非選択だった場合...オブジェクトが繋がっているラインを切断する
+                disconnectObjects((downPosX / drawScale) , (downPosY / drawScale), ((tempPosX - drawTransX) / drawScale), ((tempPosY - drawTransY) / drawScale));
+                
+                       // 移動位置をクリアする
+                       tempPosX = Float.MIN_VALUE;
+                       tempPosY = Float.MIN_VALUE;
+                       downPosX = Float.MIN_VALUE;
+                       downPosY = Float.MIN_VALUE;
+                return (true);
+               }
+
+               // 移動位置をクリアする
+                       tempPosX = Float.MIN_VALUE;
+               tempPosY = Float.MIN_VALUE;
+               downPosX = Float.MIN_VALUE;
+               downPosY = Float.MIN_VALUE;
+               return (true);
+        }
+
+        if (selectedPosition.rect.contains(x, y) == true)
+       {
+               //  タッチが離された位置がタッチしたオブジェクトと同じ位置だった場合......
+
+               // タッチが離された位置を認識する
+               float diffX = Math.abs(event.getX() - drawTransX - downPosX);
+               float diffY = Math.abs(event.getY() - drawTransY - downPosY);           
+
+               // タッチが離された位置が動いていた場合、オブジェクト位置の微調整と判定する。
+               if (((diffX > 2.0f)||(diffY > 2.0f))||(longPress == true))
+               {
+               // タッチが離された場所にはオブジェクトがなかった場合...オブジェクトをその位置に移動させる
+               Log.v(Main.APP_IDENTIFIER, "MOVE OBJECT : (" + diffX + "," + diffY + ")");
+                       moveObjectPosition(x, y);
+                       return (true);
+               }
+               
+            //  タッチが押された位置と離された位置が同じ位置だった場合......アイテムが選択された、と認識する。             
+               Log.v(Main.APP_IDENTIFIER, " ITEM SELECTED :" + x + "," + y);
+               if (selectionReceiver != null)
+               {
+                       // アイテムが選択されたよ!と教える
+                       boolean isDraw = selectionReceiver.objectSelected(selectedPosition.getKey());
+
+                       // 移動位置をクリアする
+                       tempPosX = Float.MIN_VALUE;
+                       tempPosY = Float.MIN_VALUE;
+                       return (isDraw);
+               }
+       }
+
+       // タッチが離された位置にオブジェクトがいるかどうかのチェック
+       MeMoMaObjectHolder.PositionObject position = checkSelectedObject(x, y);
+        if ((position != null)&&(longPress == false))
+        {
+               // 他のオブジェクトと重なるように操作した、この場合は、オブジェクト間を線をつなげる
+               // (ただし、ボタンを長押ししていなかったとき。)
+               lineHolder.setLines(selectedPosition.getKey(), position.getKey(), lineStyleHolder);
+               tempPosX = Float.MIN_VALUE;
+               tempPosY = Float.MIN_VALUE;
+               return (true);
+        }
+        
+        // タッチが離された場所にはオブジェクトがなかった場合...オブジェクトをその位置に移動させる
+        moveObjectPosition(x, y);
+/*
+        tempPosX = Float.MIN_VALUE;
+       tempPosY = Float.MIN_VALUE;
+       float positionX = alignPosition(x, (objectSizeX / 2) * (-1));
+       float positionY = alignPosition(y, (objectSizeY / 2) * (-1));
+       selectedPosition.rect = new  android.graphics.RectF(positionX, positionY, (positionX + objectSizeX), (positionY + objectSizeY));
+       // selectedPosition.drawStyle = objectStyle;   // 不要、最初に生成するときだけ必要
+*/
+       return (true);
+    }
+    
+    /**
+     *   オブジェクトの位置を移動させる
+     * 
+     * @param x
+     * @param y
+     */
+    private void moveObjectPosition(float x, float y)
+    {
+        tempPosX = Float.MIN_VALUE;
+       tempPosY = Float.MIN_VALUE;
+       float sizeX = selectedPosition.rect.right - selectedPosition.rect.left;
+       float sizeY = selectedPosition.rect.bottom - selectedPosition.rect.top;
+       
+       float positionX = alignPosition(x, (sizeX / 2) * (-1));
+       float positionY = alignPosition(y, (sizeY / 2) * (-1));
+       selectedPosition.rect = new  android.graphics.RectF(positionX, positionY, (positionX + sizeX), (positionY + sizeY));
+       
+       return;
+    }
+    
+         /**
+          *    onTouchEvent : 画面がタッチした時のイベント処理
+          *    (true なら、画面描画を実施する)
+          */
+         public boolean onTouchEvent(MotionEvent event)
+         {
+            boolean isDraw = false;
+
+            /** スケールジェスチャ(マルチタッチのジェスチャ)を拾う **/
+            isDraw = scaleGestureDetector.onTouchEvent(event);
+               if ((onScaling == true)||(scaleGestureDetector.isInProgress() == true))
+               {
+                       //  マルチタッチ操作中...
+                       return (true);
+               }
+               
+               /**  先にジェスチャーを拾ってみよう...   **/
+            isDraw = gestureDetector.onTouchEvent(event);
+            if (isDraw == true)
+            {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onTouchEvent() : isDraw == true");
+               return (isDraw);
+            }
+
+               int action = event.getAction();
+               
+               //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onTouchEvent() : " + action);
+               if (action == MotionEvent.ACTION_DOWN)
+               {
+                       // タッチされたとき
+                       isDraw = onTouchDown(event);
+               }
+               else if (action == MotionEvent.ACTION_MOVE)
+               {
+                       // タッチされたまま動かされたときの処理
+                       tempPosX = event.getX();
+                tempPosY = event.getY();
+                isDraw = true;
+               }
+               else if (action == MotionEvent.ACTION_UP)
+               {
+                       // タッチが離されたときの処理...
+                   isDraw = onTouchUp(event);
+               }
+
+               return (isDraw);
+         }
+
+         /**
+          *   タテヨコ位置を合わせられるよう、調整する。
+          * @param pos
+          * @return
+          */
+         private float alignPosition(float pos, float offset)
+         {
+                 // 位置を調整する。
+                 return (pos + offset);
+         }     
+
+         /**
+          *    位置から判定し、選択したオブジェクトを応答する
+          *    (オブジェクトが選択されていない場合には、nullを応答する)
+          * @param x
+          * @param y
+          * @return
+          */
+         private MeMoMaObjectHolder.PositionObject checkSelectedObject(float x, float y)
+         {
+          Enumeration<Integer> keys = objectHolder.getObjectKeys();
+             //Log.v(Main.APP_IDENTIFIER, "CHECK POS "  + x + "," + y);
+                 while (keys.hasMoreElements())
+                 {
+                         Integer key = keys.nextElement();
+                         MeMoMaObjectHolder.PositionObject pos = objectHolder.getPosition(key);
+                         if (pos.rect.contains(x, y) == true)
+                         {
+                                     Log.v(Main.APP_IDENTIFIER, "SELECTED :"  + pos.rect.centerX() + "," + pos.rect.centerY() +  " KEY :" + key);
+                                     return (pos);
+                         }
+                         //Log.v(Main.APP_IDENTIFIER, "NOT MATCH :"   + pos.rect.centerX() + "," + pos.rect.centerY());
+                 }
+                 //Log.v(Main.APP_IDENTIFIER, "RETURN NULL...");
+                 return (null);
+         }     
+
+         /**
+          *   線と交差するオブジェクト接続線をすべて削除する
+          * 
+          * @param startX
+          * @param startY
+          * @param endX
+          * @param endY
+          */
+      private void disconnectObjects(float startX, float startY, float endX, float endY)
+      {
+           Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::disconnectObjects() [" + startX + "," + startY +"]-[" + endX + "," + endY + "]");
+                   try
+                   {
+                       Enumeration<Integer> keys = lineHolder.getLineKeys();
+                       while (keys.hasMoreElements())
+                       {
+                           Integer key = keys.nextElement();
+                           MeMoMaConnectLineHolder.ObjectConnector line = lineHolder.getLine(key);
+                           if (line.key > 0)
+                           {
+                                   // 線の始点と終点を取り出す
+                                           MeMoMaObjectHolder.PositionObject from = objectHolder.getPosition(line.fromObjectKey);
+                                           MeMoMaObjectHolder.PositionObject to = objectHolder.getPosition(line.toObjectKey);
+
+                                           // 線が交差しているかチェックする
+                                           if (checkIntersection(startX, startY, endX, endY, from.rect.centerX(),  from.rect.centerY(),  to.rect.centerX(), to.rect.centerY()) == true)                                            
+                                           {
+                                // 線が交差していた! 線を切る!
+                                               //Log.v(Main.APP_IDENTIFIER, "CUT LINE [" +  from.rect.centerX() + "," +  from.rect.centerY() +"]-[" + to.rect.centerX() + "," + to.rect.centerY() + "]");
+                                                   lineHolder.disconnectLines(line.key);
+                                           }                                       
+                                }
+                       }
+                   }
+                   catch (Exception ex)
+                   {
+                       // 例外発生、でもなにもしない
+                   }
+      }
+      
+      /**
+       *    線が交差しているかチェックする
+       * 
+       * @param x1  線1の始点 (X座標)
+       * @param y1  線1の始点 (Y座標)
+       * @param x2  線1の終点 (X座標)
+       * @param y2  線1の終点 (Y座標)
+       * @param x3  線2の始点 (X座標)
+       * @param y3  線2の始点 (Y座標)
+       * @param x4  線2の終点 (X座標)
+       * @param y4  線2の終点 (Y座標)
+       * @return  true なら線が交差している
+       */
+      private boolean checkIntersection(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
+      {
+          // 線が平行かどうかのチェックを行う
+         float denominator = (x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3);
+         if (Math.abs(denominator) < 0.00001)
+         {
+                 // 線が平行と認識、交差しない
+                 return (false);
+         }
+
+          float tempX = x3 - x1;
+          float tempY = y3 - y1;
+          float dR = (((y4 - y3) * tempX) - ((x4 - x3) * tempY)) / denominator;
+          float dS = (((y2 - y1) * tempX) - ((x2 - x1) * tempY)) / denominator;
+         // 2直線の交点を求める
+         //float crossX, crossY;
+          //crossX = x1 + dR * (x2 - x1);
+          //crossY = y1 + dR * (y2 - y1);
+
+          // 交点が線分内にあるかどうかをチェックする
+          if ((dR >= 0)&&(dR <= 1)&&(dS >= 0)&&(dS <= 1))
+          {
+                 return (true);
+          }
+          return (false);
+      }
+
+      /**
+       *   並行移動・ズームのサイズをリセットする
+       * 
+       */
+      public void resetScaleAndLocation(SeekBar zoomBar)
+      {
+           // 並行移動をリセットする
+           drawTransX = 0.0f;
+           drawTransY = 0.0f;
+           
+            // プログレスバーの位置をリセットする
+           drawScale = 1.0f;
+           zoomBar.setProgress(50);
+
+           // preferenceに状態を記録する
+               recordTranslateAndZoomScale(50);
+      }
+
+      /**
+       *    スライドバーを変更された時の処理
+       */
+      public void zoomScaleChanged(int progress)
+      {
+         float val = ((float) progress - 50.0f) / 50.0f;
+
+         // 前の表示領域サイズを取得
+         float prevSizeWidth = screenWidth * drawScale;
+         float prevSizeHeight = screenHeight * drawScale;
+
+         //  表示倍率を変更し、倍率を画面に表示する
+         drawScale = (float) Math.round(Math.pow(10.0, val) * 10.0) / 10.0f;
+         TextView  textview = (TextView) parent.findViewById(R.id.ZoomRate);
+         textview.setText("x" + drawScale);
+
+         // 現在の表示領域サイズを取得
+         float showSizeWidth = screenWidth * drawScale;
+         float showSizeHeight = screenHeight * drawScale;
+
+         // 倍率にあわせて並行移動する場所を調整する
+         drawTransX = (prevSizeWidth - showSizeWidth) / 2.0f  + drawTransX;
+         drawTransY = (prevSizeHeight - showSizeHeight) / 2.0f + drawTransY;
+          
+             // preferenceに状態を記録する
+             recordTranslateAndZoomScale(progress);
+      }
+
+      /**
+       *    平行移動状態と倍率の状態を記憶する
+       * 
+       */
+      private void recordTranslateAndZoomScale(int progress)
+      {
+         //Log.v(Main.APP_IDENTIFIER, "recordTranslateAndZoomScale() : x" + drawScale + " X:" + drawTransX + " Y: " + drawTransY);
+          SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+          SharedPreferences.Editor editor = preferences.edit();
+          editor.putFloat("drawScale", drawScale);
+          editor.putFloat("drawTransX", drawTransX);
+          editor.putFloat("drawTransY", drawTransY);
+          editor.putInt("zoomProgress", progress);
+          editor.commit();       
+      }
+
+      /**
+       *    平行移動状態と倍率の状態を記憶する
+       * 
+       */
+      private void restoreTranslateAndZoomScale()
+      {
+          SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+          drawScale = preferences.getFloat("drawScale", 1.0f);
+          drawTransX = preferences.getFloat("drawTransX", 0.0f);
+          drawTransY = preferences.getFloat("drawTransY", 0.0f);
+         Log.v(Main.APP_IDENTIFIER, "restoreTranslateAndZoomScale() : x" + drawScale + " X:" + drawTransX + " Y: " + drawTransY);
+      }
+
+      /**
+       *    GestureDetector.OnGestureListener の実装
+       */
+      public boolean onDown(MotionEvent event)
+      {
+          //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onDown() "  + event.getX()  + "," + event.getY());           
+          return (false);        
+      }
+
+      /**
+       *    GestureDetector.OnGestureListener の実装
+       */
+      public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
+      {
+          //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onFling() "  + velocityX  + "," + velocityY);        
+          return (false);        
+      }
+
+      /**
+       *    GestureDetector.OnGestureListener の実装
+       */
+      public void onLongPress(MotionEvent event)
+      {
+         Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onLongPress() "  + event.getX()  + "," + event.getY());   
+
+         // タッチ位置をオブジェクト画像の座標に変換する
+         float x = (event.getX() - drawTransX) / drawScale;
+         float y = (event.getY() - drawTransY) / drawScale;
+
+         // タッチ位置にオブジェクトが存在するか確認する
+          MeMoMaObjectHolder.PositionObject  position = checkSelectedObject(x, y);
+         if (position != null)
+         {
+                 // 長押し処理を実施していることを記憶する
+             onGestureProcessed = true;
+
+                 // タッチした場所にオブジェクトが存在した!!
+             selectionReceiver.objectSelectedContext(position.getKey());
+         }          
+      }
+
+      /**
+       *    GestureDetector.OnGestureListener の実装
+       */
+      public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
+      {
+          //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onScroll() "  + distanceX  + "," + distanceY);       
+          return (false);        
+      }
+
+      /**
+       *    GestureDetector.OnGestureListener の実装
+       */
+      public void onShowPress(MotionEvent event)
+      {
+         //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onShowPress() "  + event.getX()  + "," + event.getY());       
+      }
+
+      /**
+       *    GestureDetector.OnGestureListener の実装
+       */
+      public boolean onSingleTapUp(MotionEvent event)
+      {
+            //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onSingleTapUp() "  + event.getX()  + "," + event.getY());
+            return (false);
+      }
+
+      /**
+       *    スライドバーを変更された時の処理
+       *    (SeekBar.OnSeekBarChangeListener の実装)
+       */
+      public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
+      {        
+           // 画面描画の倍率を変更する
+           zoomScaleChanged(progress);
+
+           // 画面描画クラスに再描画を指示する
+               final GokigenSurfaceView surfaceView = (GokigenSurfaceView) parent.findViewById(R.id.GraphicView);
+               surfaceView.doDraw();
+      }
+
+      /**
+       *    SeekBar.OnSeekBarChangeListener の実装
+       */
+      public void onStartTrackingTouch(SeekBar seekBar)
+      {
+           // 何もしない
+      }
+
+      /**
+       *    SeekBar.OnSeekBarChangeListener の実装
+       */
+      public void onStopTrackingTouch(SeekBar seekBar)
+      {
+          // 何もしない 
+      }
+
+      /**
+       *   (ScaleGestureDetector.OnScaleGestureListener の実装)
+       * 
+       * @param detector
+       * @return
+       */
+      public boolean onScale(ScaleGestureDetector detector)
+      {
+          float scaleFactor = detector.getScaleFactor();
+          //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onScale() : " + scaleFactor + " (" + currentScaleBar + ")");
+
+          /** 画面表示の倍率が変更された! x < 1 : 縮小、 1 < x : 拡大 **/
+          if (scaleFactor < 1.0f)
+          {
+                 currentScaleBar = (currentScaleBar == 0) ? 0 : currentScaleBar - 1;
+          }
+          else if (scaleFactor > 1.0f)
+          {
+                 currentScaleBar = (currentScaleBar == 100) ? 100 : currentScaleBar + 1;
+          }
+          zoomScaleChanged(currentScaleBar);
+
+          return (onScaling);
+      }
+
+      /**
+       *   (ScaleGestureDetector.OnScaleGestureListener の実装)
+       *   
+       * 
+       */
+      public  boolean   onScaleBegin(ScaleGestureDetector detector)
+      {
+          //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onScaleBegin() ");
+          SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+          currentScaleBar = preferences.getInt("zoomProgress", 50);
+         onScaling = true;
+         return (onScaling);
+      }
+
+      /**
+       *   (ScaleGestureDetector.OnScaleGestureListener の実装)
+       *   
+       */
+      public void       onScaleEnd(ScaleGestureDetector detector)
+      {
+          //Log.v(Main.APP_IDENTIFIER, "MeMoMaCanvasDrawer::onScaleEnd() " + currentScaleBar);
+         onScaling = false;
+         
+         // シークバーを設定し、値を記憶する
+             final SeekBar seekbar = (SeekBar) parent.findViewById(R.id.ZoomInOut);
+             seekbar.setProgress(currentScaleBar);             
+             zoomScaleChanged(currentScaleBar);
+      }
+ }
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaConnectLineHolder.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaConnectLineHolder.java
new file mode 100644 (file)
index 0000000..25aa3b9
--- /dev/null
@@ -0,0 +1,150 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import android.util.Log;
+
+
+/**
+ *   表示オブジェクト間の接続情報を保持するクラス
+ * 
+ * @author MRSa
+ *
+ */public class MeMoMaConnectLineHolder
+{
+               public static final int ID_NOTSPECIFY = -1;
+
+               /**
+                *   オブジェクト間を接続するクラス
+                *   
+                * @author MRSa
+                *
+                */
+               public class ObjectConnector
+               {
+                       public Integer key;
+                       public Integer fromObjectKey;
+                       public Integer toObjectKey;
+                       public Integer lineStyle;
+                       public Integer lineShape;
+                       public Integer lineThickness;
+/**
+                       public int fromShape;
+                       public int toShape;
+                       public String fromString;
+                       public String toString;
+**/
+               };
+
+               private Hashtable<Integer, ObjectConnector>  connectLines = null;
+        private Integer serialNumber = 1;
+
+           public MeMoMaConnectLineHolder()
+           {
+                         connectLines = new Hashtable<Integer, ObjectConnector>();
+                         connectLines.clear();
+           }
+
+           public Enumeration<Integer> getLineKeys()
+           {
+               return (connectLines.keys());
+           }
+
+           public ObjectConnector getLine(Integer key)
+           {
+               return (connectLines.get(key));
+           }
+
+           public boolean disconnectLines(Integer key)
+           {
+               connectLines.remove(key);
+               Log.v(Main.APP_IDENTIFIER, "DISCONNECT LINES : " + key);
+               return (true);
+           }
+
+           public void setSerialNumber(int id)
+           {
+               serialNumber = (id == ID_NOTSPECIFY) ? ++serialNumber : id;
+           }
+           
+           public int getSerialNumber()
+           {
+               return (serialNumber);
+           }
+           
+           public void removeAllLines()
+           {
+               connectLines.clear();
+               serialNumber = 1;
+           }       
+
+           public void dumpConnectLine(ObjectConnector conn)
+           {
+               if (conn == null)
+               {
+                       return;
+               }
+               Log.v(Main.APP_IDENTIFIER, "LINE " + conn.key + " [" + conn.fromObjectKey + " -> " + conn.toObjectKey + "] ");
+           }
+           
+           /**
+            *    keyToRemove で指定されたobjectの接続をすべて削除する
+            * 
+            * @param keyToRemove
+            */
+           public void removeAllConnection(Integer keyToRemove)
+           {
+                 Enumeration<Integer> keys = connectLines.keys();
+                         while (keys.hasMoreElements())
+                         {
+                                 Integer key = keys.nextElement();
+                                 ObjectConnector connector = connectLines.get(key);
+                                 if ((connector.fromObjectKey == keyToRemove)||(connector.toObjectKey == keyToRemove))
+                                 {
+                                         // 削除するキーが見つかった!
+                                         connector.key = -1;   // 一応...大丈夫だとは思うけど
+                                         connectLines.remove(key);
+                                 }
+                         }
+           }
+
+           public ObjectConnector createLine(int id)
+           {
+               ObjectConnector connector = new ObjectConnector();
+               connector.key = id;
+               connector.fromObjectKey = 1;
+               connector.toObjectKey = 1;
+               connector.lineStyle = LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW;
+               connector.lineShape = LineStyleHolder.LINESHAPE_NORMAL;
+               connector.lineThickness = LineStyleHolder.LINETHICKNESS_THIN;
+               
+/**
+               connector.fromShape = 0;
+                       connector.toShape = 0;
+                       connector.fromString = "";
+                       connector.toString = "";
+**/
+               connectLines.put(id, connector);
+               return (connector);     
+           }
+
+           public ObjectConnector setLines(Integer fromKey, Integer toKey, LineStyleHolder lineHolder)
+           {
+               ObjectConnector connector = new ObjectConnector();
+               connector.key = serialNumber;
+               connector.fromObjectKey = fromKey;
+               connector.toObjectKey = toKey;
+               connector.lineStyle = lineHolder.getLineStyle();
+               connector.lineShape = lineHolder.getLineShape();
+               connector.lineThickness = lineHolder.getLineThickness();
+/**
+               connector.fromShape = 0;
+                       connector.toShape = 0;
+                       connector.fromString = "";
+                       connector.toString = "";
+**/
+               connectLines.put(serialNumber, connector);
+               serialNumber++;
+               return (connector);     
+           }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaDataFileHolder.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaDataFileHolder.java
new file mode 100644 (file)
index 0000000..15256c7
--- /dev/null
@@ -0,0 +1,78 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+import android.content.Context;
+import android.widget.ArrayAdapter;
+
+/**
+ *    めもまのデータファイル名を保持するクラス (ArrayAdapterを拡張)
+ * 
+ * @author MRSa
+ *
+ */
+public class MeMoMaDataFileHolder extends ArrayAdapter<String> implements FilenameFilter
+{
+       private ExternalStorageFileUtility fileUtility = null;
+       private String fileExtension = "";
+
+       /**
+        *    コンストラクタ
+        * 
+        */
+    public MeMoMaDataFileHolder(Context context, int textViewRscId, ExternalStorageFileUtility utility, String extension)
+    {
+       super(context, textViewRscId);
+       fileUtility = utility;
+       fileExtension = extension;
+    }
+    
+    /**
+     *    ファイル一覧を生成する。
+     * 
+     */
+    public int updateFileList(String currentFileName, String extendDirectory)
+    {
+       int outputIndex = -1;
+       
+       clear();
+        String directory = fileUtility.getGokigenDirectory();
+        if (extendDirectory != null)
+        {
+               // ディレクトリが指定されていた時には、そのディレクトリを追加する
+               directory = directory + extendDirectory;
+        }
+       String[] dirFileList = (new File(directory)).list(this);
+        try {
+                       for (int index = 0; index < dirFileList.length; index++) {
+                               String fileName = dirFileList[index].substring(0, dirFileList[index].indexOf(fileExtension));
+                               if (fileName.contentEquals(currentFileName) == true)  // ファイル先頭にない場合は追加する。
+                               {
+                                       // 選択したインデックスを設定する。
+                                       outputIndex = index;
+                               }
+                               add(fileName);
+                               //Log.v(Main.APP_IDENTIFIER, fileName + ", File : " + dirFileList[index]);
+                       }
+               }
+               catch (Exception e)
+               {
+                               e.printStackTrace();
+               }
+       System.gc();
+       
+       //Log.v(Main.APP_IDENTIFIER, "::::::: "  + " (" + currentFileName + ") : " + outputIndex);
+       return (outputIndex);
+    }
+
+    /**
+     *    受け付けるファイル名のフィルタを応答する。
+     *    (指定された拡張子を持つなファイルだけ抽出する。)
+     * 
+     */
+    public boolean accept(File dir, String filename)
+    {
+       return (filename.endsWith(fileExtension) ? true : false);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaDataInOutManager.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaDataInOutManager.java
new file mode 100644 (file)
index 0000000..44f66db
--- /dev/null
@@ -0,0 +1,330 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+import android.support.v7.app.ActionBar;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.widget.Toast;
+
+public class MeMoMaDataInOutManager implements MeMoMaFileSavingProcess.ISavingStatusHolder, MeMoMaFileSavingProcess.IResultReceiver, MeMoMaFileLoadingProcess.IResultReceiver,  ActionBar.OnNavigationListener, ObjectLayoutCaptureExporter.ICaptureLayoutExporter
+{
+       private Activity parent = null;
+       private MeMoMaObjectHolder objectHolder = null;
+       private ExternalStorageFileUtility fileUtility = null;
+    private MeMoMaDataFileHolder dataFileHolder = null;
+       
+       private boolean isSaving = false;       
+       private boolean isShareExportedData = false;
+       
+       /**
+        *    コンストラクタ
+        * 
+        */
+       public MeMoMaDataInOutManager(Activity activity)
+       {
+           parent = activity;
+        fileUtility = new ExternalStorageFileUtility(Main.APP_BASEDIR);
+       }
+
+       /**
+        *
+        *
+        */
+       public void prepare(MeMoMaObjectHolder objectHolder, ActionBar bar, String fileName)
+       {
+        this.objectHolder = objectHolder;
+        //this.lineHolder = lineHolder;
+        
+       // データファイルフォルダを更新する
+        dataFileHolder = new MeMoMaDataFileHolder(parent, android.R.layout.simple_spinner_dropdown_item, fileUtility, ".xml");
+        int index = dataFileHolder.updateFileList(fileName, null);
+
+        try
+               {
+                       // アクションバーを設定する
+                       prepareActionBar(bar);
+               }
+               catch (Exception e)
+               {
+                       e.printStackTrace();
+               }
+
+        // タイトルの設定を変更する
+        if ((bar != null)&&(index >= 0))
+        {
+            bar.setSelectedNavigationItem(index);  // 実験...
+        }
+       }
+
+       /**
+        *   データファイル一覧を更新し、アクションバーに反映させる
+        *
+        */
+       public void updateFileList(String titleName, ActionBar bar)
+       {
+               if (dataFileHolder != null)
+               {
+                       // データファイル一覧を更新する
+            int index = dataFileHolder.updateFileList(titleName, null);
+
+            // タイトルをオブジェクトフォルダに記憶させる
+               objectHolder.setDataTitle(titleName);
+
+               // タイトルの設定を変更する
+            if ((bar != null)&&(index >= 0))
+            {
+                bar.setSelectedNavigationItem(index);  // 実験...
+            }
+               }
+       }
+
+    /**
+     *   データの保存を行う (同名のファイルが存在していた場合、 *.BAKにリネーム(上書き)してから保存する)
+     *   
+     *   
+     *   @param forceOverwrite  trueの時は、ファイル名が確定していたときは(確認せずに)上書き保存を自動で行う。
+     *   
+     */
+       public void saveFile(String dataTitle, boolean forceOverwrite)
+       {
+               if (objectHolder == null)
+               {
+                       Log.e(Main.APP_IDENTIFIER, "ERR>MeMoMaDataInOutManager::saveFile() : "  + dataTitle);
+                       return;
+               }
+
+               // タイトルをオブジェクトフォルダに記憶させる
+               objectHolder.setDataTitle(dataTitle);
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaDataInOutManager::saveFile() : "  + dataTitle);
+
+               // 同期型でファイルを保存する。。。
+               String message = saveFileSynchronous();
+               onSavedResult(message);
+       }
+
+       /**
+        *    データファイルのフルパスを応答する
+        * 
+        * @param dataTitle
+        * @return
+        */
+       public String getDataFileFullPath(String dataTitle, String extension)
+       {
+               return (fileUtility.getGokigenDirectory() + "/" + dataTitle + extension);
+       }
+       
+       /**  保存中状態を設定する **/
+    public void setSavingStatus(boolean isSaving)
+    {
+       this.isSaving = isSaving;
+    }
+    
+    /** 保存中状態を取得する **/
+    public boolean getSavingStatus()
+    {
+       return (isSaving);
+    }
+
+       /**
+        *    保存終了時の処理
+        */
+    public  void onSavedResult(String detail)
+    {
+        // 保存したことを伝達する
+               String outputMessage = parent.getString(R.string.save_data) + " " + objectHolder.getDataTitle() + " " + detail;
+        Toast.makeText(parent, outputMessage, Toast.LENGTH_SHORT).show();      
+
+               // ファイルリスト更新 ... (ここでやっちゃあ、AsyncTaskにしている意味ないなあ...)
+        dataFileHolder.updateFileList(objectHolder.getDataTitle(), null);
+    }
+
+    /**
+        *    読み込み終了時の処理
+        */
+    public  void onLoadedResult(String detail)
+    {
+        // 読み込みしたことを伝達する
+               String outputMessage = parent.getString(R.string.load_data) + " " + objectHolder.getDataTitle() + " " + detail;
+        Toast.makeText(parent, outputMessage, Toast.LENGTH_SHORT).show();
+
+       // 画面を再描画する
+       final GokigenSurfaceView surfaceview = (GokigenSurfaceView) parent.findViewById(R.id.GraphicView);
+       surfaceview.doDraw();
+    }
+
+    /**
+     *    ファイルをロードする途中のバックグラウンド処理...
+     * 
+     */
+       public void onLoadingProcess()
+       {
+        // 何もしない...
+       }
+
+    /**
+     *    ファイルからデータを読み込む。
+     * 
+     * @param dataTitle
+     */
+    public void loadFile(String dataTitle)
+    {
+        loadFileWithName(dataTitle);
+    }
+    
+    
+    /**
+     *   ファイルからのデータ読み込み処理
+     * 
+     * @param dataTitle
+     */
+       private void loadFileWithName(String dataTitle)
+       {
+        if (objectHolder == null)
+               {
+                       Log.e(Main.APP_IDENTIFIER, "ERR>MeMoMaDataInOutManager::loadFile() : "  + dataTitle);
+                       return;
+               }
+
+               // タイトルをオブジェクトフォルダに記憶させる
+               objectHolder.setDataTitle(dataTitle);
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaDataInOutManager::loadFile() : "  + dataTitle);
+
+               // AsyncTaskを使ってデータを読み込む
+               MeMoMaFileLoadingProcess asyncTask = new MeMoMaFileLoadingProcess(parent, fileUtility, this);
+        asyncTask.execute(objectHolder);
+       }
+
+       /**
+        *    アクションバーを更新する...
+        * 
+        * @param bar
+        */
+       private void prepareActionBar(ActionBar bar)
+       {
+               try {
+                       bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);  // リストを入れる
+                       bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);   // タイトルの表示をマスクする
+                       bar.setListNavigationCallbacks(dataFileHolder, this);
+               }
+               catch (Exception e)
+               {
+                       e.printStackTrace();
+               }
+       }
+
+       /**
+        *    ファイルを保存する...同期型で。
+        * 
+        * @return
+        */
+       private String saveFileSynchronous()
+       {
+               // 同期型でファイルを保存する。。。
+       SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+       String backgroundUri = preferences.getString("backgroundUri","");
+       String userCheckboxString = preferences.getString("userCheckboxString","");
+       MeMoMaFileSavingEngine saveEngine = new MeMoMaFileSavingEngine(fileUtility, backgroundUri, userCheckboxString);
+       String message = saveEngine.saveObjects(objectHolder);
+        return (message);              
+       }
+       
+       
+       /**
+        * 
+        * 
+        */
+       public boolean onNavigationItemSelected(int itemPosition, long itemId)
+       {
+               String data = dataFileHolder.getItem(itemPosition);
+               Log.v(Main.APP_IDENTIFIER, "onNavigationItemSelected(" + itemPosition + "," + itemId + ") : " + data);
+
+               // 同期型で現在のファイルを保存する。。。
+               String message = saveFileSynchronous();
+               if (message.length() != 0)
+               {
+            onSavedResult(message);
+               }
+               
+       // 選択したファイル名をタイトルに反映し、またPreferenceにも記憶する
+        parent.setTitle(data);
+       SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putString("MeMoMaInfo", data);
+        editor.commit();
+
+               // 選択したアイテムをロードする!
+        loadFileWithName(data);
+
+                return (true);
+       }
+
+       /**
+        *    スクリーンキャプチャを実施する
+        * 
+        */
+       public void doScreenCapture(String title, MeMoMaObjectHolder holder, MeMoMaCanvasDrawer drawer, boolean isShare)
+       {
+               isShareExportedData = isShare;
+               
+       // AsyncTaskを使ってデータをエクスポートする
+               ObjectLayoutCaptureExporter asyncTask = new ObjectLayoutCaptureExporter(parent, fileUtility, holder, drawer, this);
+        asyncTask.execute(title);
+       }
+       
+    /**
+     *    ファイルのエクスポート結果を受け取る
+     * 
+     */
+       public void onCaptureLayoutExportedResult(String exportedFileName, String detail)
+    {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaDataInOutManager::onCaptureExportedResult() '"  + objectHolder.getDataTitle() +"' : " + detail);
+
+               // エクスポートしたことを伝達する
+               String outputMessage = parent.getString(R.string.capture_data) + " " + objectHolder.getDataTitle() + " " + detail;
+        Toast.makeText(parent, outputMessage, Toast.LENGTH_SHORT).show();
+        
+        if (isShareExportedData == true)
+        {
+               // エクスポートしたファイルを共有する
+               shareContent(exportedFileName);
+        }
+       isShareExportedData = false;
+    }
+
+    /**
+     *    エクスポートしたファイルを共有する
+     * 
+     * @param fileName
+     */
+    private void shareContent(String fileName)
+    {
+       String message = "";
+        try
+        {
+               // 現在の時刻を取得する
+            Calendar calendar = Calendar.getInstance();
+               SimpleDateFormat outFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+            String date =  outFormat.format(calendar.getTime());
+
+            // メールタイトル
+            String title = parent.getString(R.string.app_name) + " | "+ objectHolder.getDataTitle() + " | " + date;
+
+            // メールの本文を構築する
+            message = message + "Name : " + objectHolder.getDataTitle() + "\n";
+            message = message + "exported : " + date + "\n";
+            message = message + "number of objects : " + objectHolder.getCount() + "\n";
+
+            // Share Intentを発行する。
+            SharedIntentInvoker.shareContent(parent, MeMoMaListener.MENU_ID_SHARE, title, message,  fileName, "image/png");
+        }
+        catch (Exception ex)
+        {
+               ex.printStackTrace();
+        }
+    }
+
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileExportCsvProcess.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileExportCsvProcess.java
new file mode 100644 (file)
index 0000000..3a059b2
--- /dev/null
@@ -0,0 +1,192 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Enumeration;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.Log;
+
+/**
+ *  データをファイルに保存するとき用 アクセスラッパ (非同期処理を実行)
+ *  
+ *  AsyncTask
+ *    MeMoMaObjectHolder : 実行時に渡すクラス(Param)
+ *    Integer    : 途中経過を伝えるクラス(Progress)
+ *    String     : 処理結果を伝えるクラス(Result)
+ *    
+ * @author MRSa
+ *
+ */
+public class MeMoMaFileExportCsvProcess extends AsyncTask<MeMoMaObjectHolder, Integer, String>
+{      
+       private IResultReceiver receiver = null;
+       private ExternalStorageFileUtility fileUtility = null;  
+       private String exportedFileName = null;
+
+       ProgressDialog savingDialog = null;
+       
+       /**
+        *   コンストラクタ
+        */
+    public MeMoMaFileExportCsvProcess(Context context, ExternalStorageFileUtility utility,  IResultReceiver resultReceiver)
+    {
+       receiver = resultReceiver;
+       fileUtility = utility;
+
+        //  プログレスダイアログ(「保存中...」)を表示する。
+       savingDialog = new ProgressDialog(context);
+       savingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+       savingDialog.setMessage(context.getString(R.string.dataSaving));
+       savingDialog.setIndeterminate(true);
+       savingDialog.setCancelable(false);
+       savingDialog.show();
+       
+       /** ファイルをバックアップするディレクトリを作成する **/
+       File dir = new File(fileUtility.getGokigenDirectory() + "/exported");
+       dir.mkdir();
+
+    }
+       
+    /**
+     *  非同期処理実施前の前処理
+     * 
+     */
+    @Override
+    protected void onPreExecute()
+    {
+    }
+    
+    /**
+     *    データを(CSV形式で)保管する。
+     * 
+     * @param fileName
+     * @param objectHolder
+     * @return
+     */
+    private String exportToCsvFile(String fileName, MeMoMaObjectHolder objectHolder)
+    {
+       String resultMessage = "";
+        try
+        {
+               // エクスポートするファイル名を決定する
+            Calendar calendar = Calendar.getInstance();
+            SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+            exportedFileName = fileName + "_" + outFormat.format(calendar.getTime()) + ".csv";
+               FileWriter writer = new FileWriter(new File(exportedFileName));         
+            
+               //  データのタイトルを出力
+               String str = "";
+               str = "; label,detail,userChecked,shape,style,centerX,centerY,width,height,;!<_$ (';!<_$' is a record Separator)\r\n";
+            writer.write(str);
+               
+               // オブジェクトの出力 (保持しているものをすべて表示する)
+               Enumeration<Integer> keys = objectHolder.getObjectKeys();
+            while (keys.hasMoreElements())
+            {
+                Integer key = keys.nextElement();
+                MeMoMaObjectHolder.PositionObject pos = objectHolder.getPosition(key);
+
+                // TODO:  絞り込み条件がある場合には、その条件に従ってしぼり込む必要あり。
+
+                str = "";
+                str = str + "\"" + pos.label + "\"";
+                str = str + ",\"" + pos.detail + "\"";
+                if (pos.userChecked == true)
+                {
+                       str = str + ",True";
+                }
+                else
+                {
+                       str = str + ",False";
+                }
+                str = str + "," + pos.drawStyle;   // オブジェクトの形状
+                str = str + "," + pos.paintStyle;   // オブジェクトの塗りつぶし状態
+                str = str + "," + (Math.round(pos.rect.centerX() * 100.0f) / 100.0f);
+                str = str + "," + (Math.round(pos.rect.centerY() * 100.0f) / 100.0f);
+                str = str + "," + (Math.round(pos.rect.width() * 100.0f) / 100.0f);
+                str = str + "," + (Math.round(pos.rect.height() * 100.0f) / 100.0f);
+                str = str + ",;!<_$\r\n";
+                writer.write(str);
+            }
+            writer.flush();
+            writer.close();
+        }
+        catch (Exception e)
+        {
+               resultMessage = " ERR>" + e.toString();
+            Log.v(Main.APP_IDENTIFIER, resultMessage);
+            e.printStackTrace();
+        } 
+        return (resultMessage);
+    }
+
+    /**
+     *  非同期処理
+     *  (バックグラウンドで実行する(このメソッドは、UIスレッドと別のところで実行する))
+     * 
+     */
+    @Override
+    protected String doInBackground(MeMoMaObjectHolder... datas)
+    {          
+        // ファイル名の設定 ... (拡張子なし)
+       String fileName = fileUtility.getGokigenDirectory() + "/exported/" + datas[0].getDataTitle();
+
+       // データを保管する
+        String result = exportToCsvFile(fileName, datas[0]);
+
+        System.gc();
+
+               return (result);
+    }
+
+    /**
+     *  非同期処理の進捗状況の更新
+     * 
+     */
+       @Override
+       protected void onProgressUpdate(Integer... values)
+       {
+        // 今回は何もしない
+       }
+
+    /**
+     *  非同期処理の後処理
+     *  (結果を応答する)
+     */
+    @Override
+    protected void onPostExecute(String result)
+    {
+       try
+       {
+            if (receiver != null)
+            {
+               receiver.onExportedResult(exportedFileName, result);
+            }
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaFileExportCsvProcess::onPostExecute() : " + ex.toString());
+       }
+       // プログレスダイアログを消す
+       savingDialog.dismiss();
+
+       return;
+    }     
+    
+    /**
+     *    結果報告用のインタフェース(積極的に使う予定はないけど...)
+     *    
+     * @author MRSa
+     *
+     */
+    public interface IResultReceiver
+    {
+        /**  保存結果の報告 **/
+        public abstract void onExportedResult(String exportedFileName, String detail);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileImportCsvProcess.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileImportCsvProcess.java
new file mode 100644 (file)
index 0000000..565ba4a
--- /dev/null
@@ -0,0 +1,307 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+/**
+ *  データをファイルに保存するとき用 アクセスラッパ (非同期処理を実行)
+ *  
+ *  AsyncTask
+ *    MeMoMaObjectHolder : 実行時に渡すクラス(Param)
+ *    Integer    : 途中経過を伝えるクラス(Progress)
+ *    String     : 処理結果を伝えるクラス(Result)
+ *    
+ * @author MRSa
+ *
+ */
+public class MeMoMaFileImportCsvProcess extends AsyncTask<MeMoMaObjectHolder, Integer, String> implements MeMoMaFileSavingProcess.ISavingStatusHolder, MeMoMaFileSavingProcess.IResultReceiver
+{      
+       private Context parent = null;
+       private IResultReceiver receiver = null;
+       private ExternalStorageFileUtility fileUtility = null;  
+       private String targetFileName = null;
+    private String fileSavedResult = "";
+       private ProgressDialog importingDialog = null;
+
+       private String backgroundUri = null;
+       private String userCheckboxString = null;
+       
+       /**
+        *   コンストラクタ
+        */
+    public MeMoMaFileImportCsvProcess(Context context, ExternalStorageFileUtility utility,  IResultReceiver resultReceiver, String fileName)
+    {
+       parent = context;
+       receiver = resultReceiver;
+       fileUtility = utility;
+       targetFileName = fileName;
+
+        //  プログレスダイアログ(「データインポート中...」)を表示する。
+       importingDialog = new ProgressDialog(context);
+       importingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+       importingDialog.setMessage(context.getString(R.string.dataImporting));
+       importingDialog.setIndeterminate(true);
+       importingDialog.setCancelable(false);
+       importingDialog.show();
+
+       //  設定読み出し用...あらかじめ、UIスレッドで読みだしておく。         
+       SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+       backgroundUri = preferences.getString("backgroundUri","");
+       userCheckboxString = preferences.getString("userCheckboxString","");
+    }
+       
+    /**
+     *  非同期処理実施前の前処理
+     * 
+     */
+    @Override
+    protected void onPreExecute()
+    {
+    }
+
+    /**
+     *    1レコード分のデータを読み込む。 
+     * 
+     * @param buf
+     * @return
+     */
+    private String readRecord(BufferedReader buf )
+    {
+       String oneRecord = null;
+       try
+       {
+               String oneLine = buf.readLine();
+            while (oneLine != null)
+            {
+               oneRecord = (oneRecord == null) ? oneLine : oneRecord + oneLine;
+               if (oneRecord.indexOf(",;!<_$") > 0)
+               {
+                       // レコード末尾が見つかったので break する。
+                       break;
+               }
+               // 次の行を読みだす。
+               oneLine = buf.readLine();
+            }
+       }
+       catch (Exception ex)
+       {
+            //
+               Log.v(Main.APP_IDENTIFIER, "CSV:readRecord() ex : " + ex.toString());
+               oneRecord = null;
+       }
+       return (oneRecord);
+    }
+
+    /**
+     *   1レコード分のデータを区切る
+     * 
+     * 
+     * @param dataLine
+     */
+    private void parseRecord(String dataLine,  MeMoMaObjectHolder objectHolder)
+    {
+        int detailIndex = 0;
+        int userCheckIndexTrue = 0;
+        int userCheckIndexFalse = 0;
+        int nextIndex = 0;
+        String label = "";
+        String detail = "";
+        boolean userChecked = false;
+        try
+        {
+            detailIndex = dataLine.indexOf("\",\"");
+            if (detailIndex < 0)
+            {
+                Log.v(Main.APP_IDENTIFIER, "parseRecord() : label wrong : " + dataLine);
+               return;
+            }
+            label = dataLine.substring(1, detailIndex);
+            userCheckIndexTrue = dataLine.indexOf("\",True,", detailIndex);
+            userCheckIndexFalse = dataLine.indexOf("\",False,", detailIndex);
+            if (userCheckIndexFalse > detailIndex)
+            {
+                //
+                detail = dataLine.substring(detailIndex + 3, userCheckIndexFalse);
+               userChecked = false;
+               nextIndex = userCheckIndexFalse + 8; // 8は、 ",False, を足した数
+            }
+            else if (userCheckIndexTrue > detailIndex)
+            {
+                //
+                detail = dataLine.substring(detailIndex + 3, userCheckIndexTrue);
+               userChecked = true;
+               nextIndex = userCheckIndexTrue + 7; // 7は、 ",True,  を足した数
+            }
+            else // if ((userCheckIndexTrue <= detailIndex)&&(userCheckIndexFalse <= detailIndex))
+            {
+                Log.v(Main.APP_IDENTIFIER, "parseRecord() : detail wrong : " + dataLine);
+               return;                 
+            }
+            
+            //  残りのデータを切り出す。
+            String[] datas = (dataLine.substring(nextIndex)).split(",");
+            if (datas.length < 6)
+            {
+               Log.v(Main.APP_IDENTIFIER, "parseRecord() : data size wrong : " + datas.length);
+               return;
+            }
+            int drawStyle = Integer.parseInt(datas[0]);
+            String paintStyle = datas[1];
+            float centerX = Float.parseFloat(datas[2]);
+            float centerY = Float.parseFloat(datas[3]);
+            float width = Float.parseFloat(datas[4]);
+            float height = Float.parseFloat(datas[5]);
+
+            float left = centerX - (width / 2.0f);
+            float top = centerY - (height / 2.0f);
+
+            // オブジェクトのデータを作成する
+            MeMoMaObjectHolder.PositionObject pos = objectHolder.createPosition(left, top, drawStyle);
+            if (pos == null)
+            {
+                Log.v(Main.APP_IDENTIFIER, "parseRecord() : object create failure.");
+               return;                 
+            }
+            pos.rect.right = left + width;
+            pos.rect.bottom = top + height;
+            pos.label = label;
+            pos.detail = detail;
+            pos.paintStyle = paintStyle;
+            pos.userChecked = userChecked;
+            Log.v(Main.APP_IDENTIFIER, "OBJECT CREATED: " + label + "(" + left + "," + top + ") [" +drawStyle + "]");
+        }
+        catch (Exception ex)
+        {
+               Log.v(Main.APP_IDENTIFIER, "parseRecord() " + ex.toString());
+        }
+       
+    }
+
+    
+    /**
+     *    (CSV形式の)データを読み込んで格納する。
+     * 
+     * @param fileName
+     * @param objectHolder
+     * @return
+     */
+    private String importFromCsvFile(String fileName, MeMoMaObjectHolder objectHolder)
+    {
+       String resultMessage = "";
+        try
+        {
+            Log.v(Main.APP_IDENTIFIER, "CSV(import)>> " + fileName);                   
+               BufferedReader buf = new BufferedReader(new FileReader(fileName));
+            String dataLine = readRecord(buf);
+            while (dataLine != null)
+            {
+                       if (dataLine.startsWith(";") != true)
+                       {
+                               // データ行だった。ログに出力する!
+                    parseRecord(dataLine, objectHolder);
+                       }
+                // 次のデータ行を読み出す
+                       dataLine = readRecord(buf);
+            }
+        }
+        catch (Exception e)
+        {
+               resultMessage = " ERR(import)>" + e.toString();
+            Log.v(Main.APP_IDENTIFIER, resultMessage);
+            e.printStackTrace();
+        } 
+        return (resultMessage);
+    }
+
+    /**
+     *  非同期処理
+     *  (バックグラウンドで実行する(このメソッドは、UIスレッドと別のところで実行する))
+     * 
+     */
+    @Override
+    protected String doInBackground(MeMoMaObjectHolder... datas)
+    {          
+        // ファイル名の設定 ... (拡張子なし)
+       String fileName = fileUtility.getGokigenDirectory() + "/exported/" + targetFileName;
+
+       // データを読み込む
+        String result = importFromCsvFile(fileName, datas[0]);
+
+        // データを保存する
+       MeMoMaFileSavingEngine savingEngine = new MeMoMaFileSavingEngine(fileUtility, backgroundUri, userCheckboxString);
+       String message = savingEngine.saveObjects(datas[0]);
+
+        System.gc();
+
+               return (result + " " + message);
+    }
+
+    /**
+     *  非同期処理の進捗状況の更新
+     * 
+     */
+       @Override
+       protected void onProgressUpdate(Integer... values)
+       {
+        // 今回は何もしない
+       }
+
+    /**
+     *  非同期処理の後処理
+     *  (結果を応答する)
+     */
+    @Override
+    protected void onPostExecute(String result)
+    {
+       try
+       {
+            if (receiver != null)
+            {
+               receiver.onImportedResult(result + "  " + fileSavedResult);
+            }
+            fileSavedResult = "";
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaFileImportCsvProcess::onPostExecute() : " + ex.toString());
+       }
+       // プログレスダイアログを消す
+       importingDialog.dismiss();
+
+       return;
+    }
+    
+    public void onSavedResult(String detail)
+    {
+        fileSavedResult = detail;
+    }
+
+    public void setSavingStatus(boolean isSaving)
+    {
+       
+    }
+
+    public boolean getSavingStatus()
+    {
+        return (false);
+    }
+
+    /**
+     *    結果報告用のインタフェース(積極的に使う予定はないけど...)
+     *    
+     * @author MRSa
+     *
+     */
+    public interface IResultReceiver
+    {
+        /**  保存結果の報告 **/
+        public abstract void onImportedResult(String detail);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileLoadingProcess.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileLoadingProcess.java
new file mode 100644 (file)
index 0000000..188c907
--- /dev/null
@@ -0,0 +1,401 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.io.File;
+import java.io.FileReader;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.util.Xml;
+
+/**
+ *  データをファイルに保存するとき用 アクセスラッパ (非同期処理を実行)
+ *  
+ *  AsyncTask
+ *    MeMoMaObjectHolder : 実行時に渡すクラス(Param)
+ *    Integer    : 途中経過を伝えるクラス(Progress)
+ *    String     : 処理結果を伝えるクラス(Result)
+ *    
+ * @author MRSa
+ *
+ */
+public class MeMoMaFileLoadingProcess extends AsyncTask<MeMoMaObjectHolder, Integer, String>
+{
+       private Context parent = null;
+       private IResultReceiver receiver = null;
+       private ExternalStorageFileUtility fileUtility = null;
+
+        private MeMoMaObjectHolder.PositionObject position = null;
+        private MeMoMaConnectLineHolder.ObjectConnector line = null;
+
+        private String backgroundUri = "";
+     private String userCheckboxString = "";
+       
+       /**
+        *   コンストラクタ
+        */
+    public MeMoMaFileLoadingProcess(Context context, ExternalStorageFileUtility utility, IResultReceiver resultReceiver)
+    {
+       parent = context;
+       receiver = resultReceiver;
+       fileUtility = utility;
+    }
+
+    /**
+     *  非同期処理実施前の前処理
+     * 
+     */
+    @Override
+    protected void onPreExecute()
+    {
+         // 今回は何もしない
+    }
+
+    private void parseStartTag(String name, XmlPullParser parser, MeMoMaObjectHolder objectHolder)
+    {
+       try
+       {
+               //Log.v(Main.APP_IDENTIFIER, "parseStartTag() name = " + name);
+            if ((name.equalsIgnoreCase("top"))&&(position != null))
+            {
+               position.rect.top = Float.parseFloat(parser.nextText());
+            }
+            else if ((name.equalsIgnoreCase("bottom"))&&(position != null))
+            {
+               position.rect.bottom = Float.parseFloat(parser.nextText());             
+            }
+            else if ((name.equalsIgnoreCase("left"))&&(position != null))
+            {
+               position.rect.left = Float.parseFloat(parser.nextText());               
+            }
+            else if ((name.equalsIgnoreCase("right"))&&(position != null))
+            {
+               position.rect.right = Float.parseFloat(parser.nextText());              
+            }
+            else if ((name.equalsIgnoreCase("drawStyle"))&&(position != null))
+            {
+               position.drawStyle = Integer.parseInt(parser.nextText());
+            }
+            else if ((name.equalsIgnoreCase("icon"))&&(position != null))
+            {
+               position.icon = Integer.parseInt(parser.nextText());                    
+            }
+            else if ((name.equalsIgnoreCase("label"))&&(position != null))
+            {
+               position.label = parser.nextText();
+            }
+            else if ((name.equalsIgnoreCase("detail"))&&(position != null))
+            {
+               position.detail = parser.nextText();                    
+            }
+/**
+            else if ((name.equalsIgnoreCase("backgroundUri"))&&(position != null))
+            {
+               position.backgroundUri = parser.nextText();                             
+            }
+            else if ((name.equalsIgnoreCase("otherInfoUri"))&&(position != null))
+            {
+               position.otherInfoUri = parser.nextText();                              
+            }
+            else if ((name.equalsIgnoreCase("objectStatus"))&&(position != null))
+            {
+               position.objectStatus = parser.nextText();              
+            }
+**/
+            else if ((name.equalsIgnoreCase("userChecked"))&&(position != null))
+            {
+               String parseData = parser.nextText();
+               position.userChecked =(parseData.equalsIgnoreCase("true")) ? true : false;
+            }
+            else if ((name.equalsIgnoreCase("labelColor"))&&(position != null))
+            {
+               position.labelColor = Integer.parseInt(parser.nextText());              
+            }
+            else if ((name.equalsIgnoreCase("objectColor"))&&(position != null))
+            {
+               position.objectColor = Integer.parseInt(parser.nextText());             
+            }
+            else if ((name.equalsIgnoreCase("paintStyle"))&&(position != null))
+            {
+               position.paintStyle = parser.nextText();
+            }
+            else if ((name.equalsIgnoreCase("strokeWidth"))&&(position != null))
+            {
+               position.strokeWidth = Float.parseFloat(parser.nextText());             
+            }
+            else if ((name.equalsIgnoreCase("fontSize"))&&(position != null))
+            {
+               position.fontSize = Float.parseFloat(parser.nextText());                
+            }
+            else if ((name.equalsIgnoreCase("fromObjectKey"))&&(line != null))
+            {
+               line.fromObjectKey = Integer.parseInt(parser.nextText());               
+            }
+            else if ((name.equalsIgnoreCase("toObjectKey"))&&(line != null))
+            {
+               line.toObjectKey = Integer.parseInt(parser.nextText());                 
+            }
+            else if ((name.equalsIgnoreCase("lineStyle"))&&(line != null))
+            {
+               line.lineStyle = Integer.parseInt(parser.nextText());                   
+            }
+            else if ((name.equalsIgnoreCase("lineShape"))&&(line != null))
+            {
+               line.lineShape = Integer.parseInt(parser.nextText());                   
+            }
+            else if ((name.equalsIgnoreCase("lineThickness"))&&(line != null))
+            {
+               line.lineThickness = Integer.parseInt(parser.nextText());               
+            }
+/**
+            else if ((name.equalsIgnoreCase("fromShape"))&&(line != null))
+            {
+               line.fromShape = Integer.parseInt(parser.nextText());                   
+            }
+            else if ((name.equalsIgnoreCase("toShape"))&&(line != null))
+            {
+               line.toShape = Integer.parseInt(parser.nextText());             
+            }
+            else if ((name.equalsIgnoreCase("fromString"))&&(line != null))
+            {
+               line.fromString = parser.nextText();                    
+            }
+            else if ((name.equalsIgnoreCase("toString"))&&(line != null))
+            {
+               line.toString = parser.nextText();              
+            }
+**/
+            else if ((name.equalsIgnoreCase("title"))&&(objectHolder != null))
+            {
+               objectHolder.setDataTitle(parser.nextText());
+            }
+            else if ((name.equalsIgnoreCase("background"))&&(objectHolder != null))
+            {
+               objectHolder.setBackground(parser.nextText());
+            }
+            else if ((name.equalsIgnoreCase("backgroundUri"))&&(objectHolder != null))
+            {
+                backgroundUri = parser.nextText();
+            }
+            else if ((name.equalsIgnoreCase("userCheckboxString"))&&(objectHolder != null))
+            {
+                userCheckboxString = parser.nextText();
+            }
+            else if ((name.equalsIgnoreCase("objserial"))&&(objectHolder != null))
+            {
+               objectHolder.setSerialNumber(Integer.parseInt(parser.nextText()));
+               //Log.v(Main.APP_IDENTIFIER, "objSerial : " + objectHolder.getSerialNumber());
+            }
+            else if ((name.equalsIgnoreCase("lineserial"))&&(objectHolder != null))
+            {
+               objectHolder.getConnectLineHolder().setSerialNumber(Integer.parseInt(parser.nextText()));               
+               //Log.v(Main.APP_IDENTIFIER, "lineSerial : " + objectHolder.getSerialNumber());
+            }
+            else if (name.equalsIgnoreCase("object"))
+            {
+                int key = Integer.parseInt(parser.getAttributeValue(Main.APP_NAMESPACE, "key"));
+                //Log.v(Main.APP_IDENTIFIER, "create object, key :" + key);
+                position = null;
+                position = objectHolder.createPosition(key);
+            }
+            else if (name.equalsIgnoreCase("line"))
+            {
+                int key = Integer.parseInt(parser.getAttributeValue(Main.APP_NAMESPACE, "key"));
+                //Log.v(Main.APP_IDENTIFIER, "create line, key :" + key);
+                line = null;
+                line = objectHolder.getConnectLineHolder().createLine(key);            
+            }
+       }
+        catch (Exception e)
+        {
+            Log.v(Main.APP_IDENTIFIER, "ERR>parseStartTag() name:" + name + " " + e.toString());
+        }
+    }
+    
+    private void parseEndTag(String name, XmlPullParser parser, MeMoMaObjectHolder objectHolder)
+    {
+       try
+       {
+            if (name.equalsIgnoreCase("object"))
+            {
+                //Log.v(Main.APP_IDENTIFIER, "parseEndTag() : OBJECT");
+                //objectHolder.dumpPositionObject(position);
+
+               // 領域サイズがおかしい場合には、オブジェクトサイズを補正する (ふつーありえないはずなんだけど...)
+               if ((position.rect.left > position.rect.right)||(position.rect.top > position.rect.bottom))
+               {
+                       Log.v(Main.APP_IDENTIFIER, "RECT IS ILLEGAL. : [" + position.rect.left + "," + position.rect.top + "-[" + position.rect.right + "," + position.rect.bottom + "]");
+                       position.rect.right = position.rect.left + MeMoMaObjectHolder.OBJECTSIZE_DEFAULT_X;
+                       position.rect.bottom = position.rect.top + MeMoMaObjectHolder.OBJECTSIZE_DEFAULT_Y;
+               }
+               
+            }
+            else if (name.equalsIgnoreCase("line"))
+            {
+                //Log.v(Main.APP_IDENTIFIER, "parseEndTag() : LINE");       
+                //objectHolder.getConnectLineHolder().dumpConnectLine(line);
+            }
+        }
+        catch (Exception e)
+        {
+            Log.v(Main.APP_IDENTIFIER, "ERR>parseEndTag() name:" + name + " " + e.toString());
+        }
+    }
+    
+    /**
+     *    (XML形式の)データを読みだす。
+     * 
+     * @param fileName
+     * @param objectHolder
+     * @return
+     */
+    private String restoreToXmlFile(String fileName, MeMoMaObjectHolder objectHolder)
+    {
+       String resultMessage = "";
+        XmlPullParser parser = Xml.newPullParser();
+        
+        if (objectHolder == null)
+        {
+                return ("ERR>objectHolder is null.");
+        }
+        
+        try
+        {
+                File inputFile = new File(fileName);
+                if (inputFile.exists() == false)
+                {
+                        // ファイルがなかったときには、「ファイルなし」と報告する。
+                        resultMessage = "ERR>File not found.";
+                        return (resultMessage);
+                }
+                // ファイルの読み込み
+                FileReader reader = new FileReader(inputFile);
+                parser.setInput(reader);
+
+                int eventType = parser.getEventType();
+             boolean done = false;
+
+             // オブジェクトとラインをすべてクリアする
+             objectHolder.removeAllPositions();
+             MeMoMaConnectLineHolder lineHolder = objectHolder.getConnectLineHolder();
+             if (lineHolder == null)
+             {
+                        return ("ERR>lineHolder is null.");                     
+             }
+             lineHolder.removeAllLines();
+             
+             while ((eventType != XmlPullParser.END_DOCUMENT)&&(done != true))
+             {
+                 switch (eventType)
+                 {
+                     case XmlPullParser.START_DOCUMENT:
+                         break;
+
+                     case XmlPullParser.START_TAG:
+                         parseStartTag(parser.getName(), parser, objectHolder);
+                         break;
+
+                     case XmlPullParser.END_TAG:
+                        parseEndTag(parser.getName(), parser, objectHolder);
+                         break;
+
+                     default:
+                        // 省略...
+                        break;
+                 }
+                 eventType = parser.next();
+             }
+             reader.close();
+        }
+        catch (Exception e)
+        {
+                resultMessage = " ERR>" + e.toString();
+             Log.v(Main.APP_IDENTIFIER, resultMessage);
+                e.printStackTrace();
+        }
+       return (resultMessage);
+    }
+
+    /**
+     *  非同期処理
+     *  (バックグラウンドで実行する(このメソッドは、UIスレッドと別のところで実行する))
+     * 
+     */
+    @Override
+    protected String doInBackground(MeMoMaObjectHolder... datas)
+    {
+        // ファイル名の設定 ... (拡張子あり...保存時とは違う)
+       String fileName = fileUtility.getGokigenDirectory() + "/" + datas[0].getDataTitle() + ".xml";
+       
+       // データを読みだす。
+        String result = restoreToXmlFile(fileName, datas[0]);
+
+        //何か必要な場合、 非同期処理をここで実効
+        if (receiver != null)
+        {
+               receiver.onLoadingProcess();
+        }
+
+               System.gc();
+               return (result);
+    }
+    /**
+     *  非同期処理の進捗状況の更新
+     * 
+     */
+       @Override
+       protected void onProgressUpdate(Integer... values)
+       {
+        // 今回は何もしない
+       }
+
+    /**
+     *  非同期処理の後処理
+     *  (結果を応答する)
+     */
+    @Override
+    protected void onPostExecute(String result)
+    {
+       try
+       {
+               if (result.isEmpty() == true)
+               {
+               //  エラーが発生していない場合には、読みだしたデータをPreferenceに設定登録...
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+                SharedPreferences.Editor editor = preferences.edit();
+                editor.putString("backgroundUri", backgroundUri);
+                editor.putString("userCheckboxString", userCheckboxString);
+                editor.commit();
+               }
+
+            if (receiver != null)
+            {
+               receiver.onLoadedResult(result);
+            }
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaFileSavingProcess::onPostExecute() : " + ex.toString());
+       }
+        return;
+    }     
+       
+    /**
+     *    結果報告用のインタフェース(積極的に使う予定はないけど...)
+     *    
+     * @author MRSa
+     *
+     */
+    public interface IResultReceiver
+    {
+        /**   処理中の処理   **/
+       public abstract void onLoadingProcess();
+       
+        /**  保存結果の報告 **/
+        public abstract void onLoadedResult(String detail);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileSavingEngine.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileSavingEngine.java
new file mode 100644 (file)
index 0000000..284d3fa
--- /dev/null
@@ -0,0 +1,315 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.util.Enumeration;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import android.util.Log;
+import android.util.Xml;
+
+/**
+ *  データをファイルに保存するエンジン部分
+ *  
+ * @author MRSa
+ *
+ */
+public class MeMoMaFileSavingEngine
+{      
+       private ExternalStorageFileUtility fileUtility = null;
+       private String backgroundUri = null;
+       private String userCheckboxString = null;    
+       
+       /**
+        *   コンストラクタ
+        */
+    public MeMoMaFileSavingEngine(ExternalStorageFileUtility utility, String bgUri, String checkBoxLabel)
+    {
+       /** ファイルユーティリティを記憶する **/
+       fileUtility = utility;
+       
+       /** ファイルをバックアップするディレクトリを作成する **/
+       File dir = new File(fileUtility.getGokigenDirectory() + "/backup");
+       dir.mkdir();
+
+       //  設定データ読み出し用...。
+       backgroundUri = bgUri;
+       userCheckboxString = checkBoxLabel;
+    }
+
+    /**
+     *   ファイルが存在したとき、リネームする
+     * 
+     * @param targetFileName
+     * @param newFileName
+     */
+    private boolean renameFile(String targetFileName, String newFileName)
+    {
+       boolean ret = true;
+               File targetFile = new File(targetFileName);
+               if (targetFile.exists() == true)
+               {
+                       // ファイルが存在した、、、ファイル名を1世代古いものに変更する
+                       ret = targetFile.renameTo(new File(newFileName));
+               }
+               return (ret);
+    }
+    
+    /**
+     *    保管データを複数世代保管する。
+     * 
+     * @param fileName
+     */
+    private void backupFiles(String dirName, String backupFileName)
+    {
+       //  データをバックアップする。(上書き予定のファイルがあれば、それをコピーする)
+        boolean result = true;
+        try
+        {
+               String  fileName = dirName +  "backup/" + backupFileName;
+               File backFile = new File(fileName + ".xml.bak5");
+               if (backFile.exists() == true)
+               {
+                       // ファイルが存在した、、、削除する
+                       backFile.delete();
+               }
+               backFile = null;
+               renameFile((fileName + ".xml.bak4"), (fileName + ".xml.bak5"));
+               renameFile((fileName + ".xml.bak3"), (fileName + ".xml.bak4"));
+               renameFile((fileName + ".xml.bak2"), (fileName + ".xml.bak3"));
+               renameFile((fileName + ".xml.bak1"), (fileName + ".xml.bak2"));
+               renameFile((fileName + ".xml.bak"), (fileName + ".xml.bak1"));
+               renameFile((dirName + backupFileName + ".xml"), (fileName + ".xml.bak"));
+        }
+        catch (Exception ex)
+        {
+               // 何か例外が発生した場合にはエラーと認識する。
+               result = false;
+        }
+               if (result == false)
+               {
+            // バックアップファイルのコピー失敗をログに記述する
+            Log.v(Main.APP_IDENTIFIER, "rename failure : " + dirName +  backupFileName + ".xml");
+               }
+               return;
+    }
+    
+    /**
+     *    データを(XML形式で)保管する。
+     * 
+     * @param fileName
+     * @param objectHolder
+     * @return
+     */
+    private String storeToXmlFile(String fileName, MeMoMaObjectHolder objectHolder)
+    {
+       String resultMessage = "";
+        try
+        {
+            FileWriter writer = new FileWriter(new File(fileName + ".xml"));           
+            XmlSerializer serializer = Xml.newSerializer();
+
+            serializer.setOutput(writer);
+            serializer.startDocument("UTF-8", true);
+            serializer.startTag(Main.APP_NAMESPACE, "memoma");
+            
+            // タイトルの出力
+            serializer.startTag(Main.APP_NAMESPACE, "title");
+            serializer.text(objectHolder.getDataTitle());
+            serializer. endTag(Main.APP_NAMESPACE, "title");
+
+            // 背景情報の出力
+            serializer.startTag(Main.APP_NAMESPACE, "background");
+            serializer.text(objectHolder.getBackground());
+            serializer. endTag(Main.APP_NAMESPACE, "background");
+
+            // 背景画像URIの出力
+            serializer.startTag(Main.APP_NAMESPACE, "backgroundUri");
+            serializer.text(backgroundUri);
+            serializer. endTag(Main.APP_NAMESPACE, "backgroundUri");
+            
+            // ユーザチェックボックス名の出力
+            serializer.startTag(Main.APP_NAMESPACE, "userCheckboxString");
+            serializer.text(userCheckboxString);
+            serializer. endTag(Main.APP_NAMESPACE, "userCheckboxString");
+            
+            serializer.startTag(Main.APP_NAMESPACE, "objserial");
+            serializer.text(Integer.toString(objectHolder.getSerialNumber()));
+            serializer.endTag(Main.APP_NAMESPACE, "objserial");
+
+            serializer.startTag(Main.APP_NAMESPACE, "lineserial");
+            serializer.text(Integer.toString(objectHolder.getConnectLineHolder().getSerialNumber()));
+            serializer.endTag(Main.APP_NAMESPACE, "lineserial");
+            
+            
+               // オブジェクトの出力 (保持しているものはすべて表示する)
+               Enumeration<Integer> keys = objectHolder.getObjectKeys();
+            while (keys.hasMoreElements())
+            {
+                Integer key = keys.nextElement();
+                MeMoMaObjectHolder.PositionObject pos = objectHolder.getPosition(key);
+                serializer.startTag(Main.APP_NAMESPACE, "object");
+
+                serializer.attribute(Main.APP_NAMESPACE, "key", Integer.toString(key));
+
+                serializer.startTag(Main.APP_NAMESPACE, "rect");
+                serializer.startTag(Main.APP_NAMESPACE, "top");
+                serializer.text(Float.toString(pos.rect.top));
+                serializer. endTag(Main.APP_NAMESPACE, "top");
+                serializer.startTag(Main.APP_NAMESPACE, "left");
+                serializer.text(Float.toString(pos.rect.left));
+                serializer. endTag(Main.APP_NAMESPACE, "left");
+                serializer.startTag(Main.APP_NAMESPACE, "right");
+                serializer.text(Float.toString(pos.rect.right));
+                serializer. endTag(Main.APP_NAMESPACE, "right");
+                serializer.startTag(Main.APP_NAMESPACE, "bottom");
+                serializer.text(Float.toString(pos.rect.bottom));
+                serializer. endTag(Main.APP_NAMESPACE, "bottom");
+                serializer. endTag(Main.APP_NAMESPACE, "rect");
+
+                serializer.startTag(Main.APP_NAMESPACE, "drawStyle");
+                serializer.text(Integer.toString(pos.drawStyle));
+                serializer. endTag(Main.APP_NAMESPACE, "drawStyle");
+
+                serializer.startTag(Main.APP_NAMESPACE, "icon");
+                serializer.text(Integer.toString(pos.icon));
+                serializer. endTag(Main.APP_NAMESPACE, "icon");
+
+                serializer.startTag(Main.APP_NAMESPACE, "label");
+                serializer.text(pos.label);
+                serializer. endTag(Main.APP_NAMESPACE, "label");
+
+                serializer.startTag(Main.APP_NAMESPACE, "detail");
+                serializer.text(pos.detail);
+                serializer. endTag(Main.APP_NAMESPACE, "detail");
+/**
+                serializer.startTag(Main.APP_NAMESPACE, "otherInfoUri");
+                serializer.text(pos.otherInfoUri);
+                serializer. endTag(Main.APP_NAMESPACE, "otherInfoUri");
+
+                serializer.startTag(Main.APP_NAMESPACE, "backgroundUri");
+                serializer.text(pos.backgroundUri);
+                serializer. endTag(Main.APP_NAMESPACE, "backgroundUri");
+
+                serializer.startTag(Main.APP_NAMESPACE, "objectStatus");
+                serializer.text(pos.objectStatus);
+                serializer. endTag(Main.APP_NAMESPACE, "objectStatus");
+**/
+                serializer.startTag(Main.APP_NAMESPACE, "userChecked");
+                serializer.text(Boolean.toString(pos.userChecked));
+                serializer. endTag(Main.APP_NAMESPACE, "userChecked");
+                
+                serializer.startTag(Main.APP_NAMESPACE, "labelColor");
+                serializer.text(Integer.toString(pos.labelColor));
+                serializer. endTag(Main.APP_NAMESPACE, "labelColor");
+
+                serializer.startTag(Main.APP_NAMESPACE, "objectColor");
+                serializer.text(Integer.toString(pos.objectColor));
+                serializer. endTag(Main.APP_NAMESPACE, "objectColor");
+
+                serializer.startTag(Main.APP_NAMESPACE, "paintStyle");
+                serializer.text(pos.paintStyle);
+                serializer. endTag(Main.APP_NAMESPACE, "paintStyle");
+               
+                serializer.startTag(Main.APP_NAMESPACE, "strokeWidth");
+                serializer.text(Float.toString(pos.strokeWidth));
+                serializer. endTag(Main.APP_NAMESPACE, "strokeWidth");
+
+                serializer.startTag(Main.APP_NAMESPACE, "fontSize");
+                serializer.text(Float.toString(pos.fontSize));
+                serializer. endTag(Main.APP_NAMESPACE, "fontSize");
+
+                serializer.endTag(Main.APP_NAMESPACE, "object");
+            }
+
+            // 接続線の出力 (保持しているものはすべて表示する)
+               Enumeration<Integer> lineKeys = objectHolder.getConnectLineHolder().getLineKeys();
+            while (lineKeys.hasMoreElements())
+            {
+                Integer key = lineKeys.nextElement();
+                MeMoMaConnectLineHolder.ObjectConnector line = objectHolder.getConnectLineHolder().getLine(key);
+                serializer.startTag(Main.APP_NAMESPACE, "line");
+                serializer.attribute(Main.APP_NAMESPACE, "key", Integer.toString(key));
+
+                serializer.startTag(Main.APP_NAMESPACE, "fromObjectKey");
+                serializer.text(Integer.toString(line.fromObjectKey));
+                serializer.endTag(Main.APP_NAMESPACE, "fromObjectKey");
+
+                serializer.startTag(Main.APP_NAMESPACE, "toObjectKey");
+                serializer.text(Integer.toString(line.toObjectKey));
+                serializer.endTag(Main.APP_NAMESPACE, "toObjectKey");
+
+                serializer.startTag(Main.APP_NAMESPACE, "lineStyle");
+                serializer.text(Integer.toString(line.lineStyle));
+                serializer.endTag(Main.APP_NAMESPACE, "lineStyle");
+
+                serializer.startTag(Main.APP_NAMESPACE, "lineShape");
+                serializer.text(Integer.toString(line.lineShape));
+                serializer.endTag(Main.APP_NAMESPACE, "lineShape");
+
+                serializer.startTag(Main.APP_NAMESPACE, "lineThickness");
+                serializer.text(Integer.toString(line.lineThickness));
+                serializer.endTag(Main.APP_NAMESPACE, "lineThickness");
+/**
+                serializer.startTag(Main.APP_NAMESPACE, "fromShape");
+                serializer.text(Integer.toString(line.fromShape));
+                serializer.endTag(Main.APP_NAMESPACE, "fromShape");
+
+                serializer.startTag(Main.APP_NAMESPACE, "toShape");
+                serializer.text(Integer.toString(line.toShape));
+                serializer.endTag(Main.APP_NAMESPACE, "toShape");
+                
+                serializer.startTag(Main.APP_NAMESPACE, "fromString");
+                serializer.text(line.fromString);
+                serializer.endTag(Main.APP_NAMESPACE, "fromString");
+
+                serializer.startTag(Main.APP_NAMESPACE, "toString");
+                serializer.text(line.toString);
+                serializer.endTag(Main.APP_NAMESPACE, "toString");
+**/
+                serializer.endTag(Main.APP_NAMESPACE, "line");
+            }
+
+            serializer.endTag(Main.APP_NAMESPACE, "memoma");
+            serializer.endDocument();
+            serializer.flush();
+            writer.close();
+        }
+        catch (Exception e)
+        {
+               resultMessage = " ERR>" + e.toString();
+            Log.v(Main.APP_IDENTIFIER, resultMessage);
+            e.printStackTrace();
+        } 
+        return (resultMessage);
+    }
+
+    /**
+     *    オブジェクトを保存する
+     * 
+     * @param objectHolder
+     * @return
+     */
+    public String saveObjects(MeMoMaObjectHolder objectHolder)
+    {
+               // データタイトルがない場合...保存処理は行わない。
+       if (objectHolder.getDataTitle().length() <= 0)
+        {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaFileSavingEngine::saveObjects() : specified file name is illegal, save aborted. : " + objectHolder.getDataTitle() );
+
+               return ("");
+        }
+
+       // バックアップを保存する
+       backupFiles(fileUtility.getGokigenDirectory() + "/" , objectHolder.getDataTitle());
+       
+        // ファイル名の設定 ... (拡張子なし)
+       String fileName = fileUtility.getGokigenDirectory() + "/" + objectHolder.getDataTitle();
+
+       // データを保管する
+        String result = storeToXmlFile(fileName, objectHolder);
+
+        return (result);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileSavingProcess.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaFileSavingProcess.java
new file mode 100644 (file)
index 0000000..e5caa9e
--- /dev/null
@@ -0,0 +1,154 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+/**
+ *  データをファイルに保存するとき用 アクセスラッパ (非同期処理を実行)
+ *  
+ *  AsyncTask
+ *    MeMoMaObjectHolder : 実行時に渡すクラス(Param)
+ *    Integer    : 途中経過を伝えるクラス(Progress)
+ *    String     : 処理結果を伝えるクラス(Result)
+ *    
+ * @author MRSa
+ *
+ */
+public class MeMoMaFileSavingProcess extends AsyncTask<MeMoMaObjectHolder, Integer, String>
+{      
+       private IResultReceiver receiver = null;
+       private ExternalStorageFileUtility fileUtility = null;
+       private ISavingStatusHolder statusHolder = null;
+       
+       private String backgroundUri = null;
+       private String userCheckboxString = null;
+       private ProgressDialog savingDialog = null;
+       
+       /**
+        *   コンストラクタ
+        */
+    public MeMoMaFileSavingProcess(Context context, ISavingStatusHolder holder, ExternalStorageFileUtility utility,  IResultReceiver resultReceiver)
+    {
+       receiver = resultReceiver;
+       fileUtility = utility;
+       statusHolder = holder;
+
+        //  プログレスダイアログ(「保存中...」)を表示する。
+       savingDialog = new ProgressDialog(context);
+       savingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+       savingDialog.setMessage(context.getString(R.string.dataSaving));
+       savingDialog.setIndeterminate(true);
+       savingDialog.setCancelable(false);
+       savingDialog.show();
+
+       //  設定読み出し用...あらかじめ、UIスレッドで読みだしておく。
+       SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+       backgroundUri = preferences.getString("backgroundUri","");
+       userCheckboxString = preferences.getString("userCheckboxString","");
+               
+       // 未保管状態にリセットする
+       statusHolder.setSavingStatus(false);
+    }
+       
+    /**
+     *  非同期処理実施前の前処理
+     * 
+     */
+    @Override
+    protected void onPreExecute()
+    {
+       // 未保管状態にリセットする
+       statusHolder.setSavingStatus(false);
+    }
+
+    /**
+     *  非同期処理
+     *  (バックグラウンドで実行する(このメソッドは、UIスレッドと別のところで実行する))
+     * 
+     */
+    @Override
+    protected String doInBackground(MeMoMaObjectHolder... datas)
+    {
+       // 保管中状態を設定する
+       statusHolder.setSavingStatus(true);
+
+       // データの保管メイン
+       MeMoMaFileSavingEngine savingEngine = new MeMoMaFileSavingEngine(fileUtility, backgroundUri, userCheckboxString);
+       String result = savingEngine.saveObjects(datas[0]);
+
+        System.gc();
+               
+       // 未保管状態にリセットする
+       statusHolder.setSavingStatus(false);
+
+               return (result);
+    }
+
+    /**
+     *  非同期処理の進捗状況の更新
+     * 
+     */
+       @Override
+       protected void onProgressUpdate(Integer... values)
+       {
+        // 今回は何もしない
+       }
+
+    /**
+     *  非同期処理の後処理
+     *  (結果を応答する)
+     */
+    @Override
+    protected void onPostExecute(String result)
+    {
+       try
+       {
+            if (receiver != null)
+            {
+               receiver.onSavedResult(result);
+            }
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaFileSavingProcess::onPostExecute() : " + ex.toString());
+       }
+       // プログレスダイアログを消す
+       savingDialog.dismiss();
+
+       // 未保管状態にセットする
+       statusHolder.setSavingStatus(false);
+        return;
+    }     
+    
+    /**
+     *    結果報告用のインタフェース(積極的に使う予定はないけど...)
+     *    
+     * @author MRSa
+     *
+     */
+    public interface IResultReceiver
+    {
+        /**  保存結果の報告 **/
+        public abstract void onSavedResult(String detail);
+    }
+
+    /**
+     *     ファイル保存実施状態を記憶するインタフェースクラス
+     *     
+     * @author MRSa
+     *
+     */
+    public interface ISavingStatusHolder
+    {
+       /**  保存中状態を設定する **/
+        public abstract void setSavingStatus(boolean isSaving);
+        
+        /** 保存中状態を取得する **/
+        public abstract boolean getSavingStatus();
+    }
+
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaListener.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaListener.java
new file mode 100644 (file)
index 0000000..907db79
--- /dev/null
@@ -0,0 +1,1240 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Color;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnKeyListener;
+import android.view.View.OnTouchListener;
+import android.widget.ImageButton;
+import android.widget.SeekBar;
+
+/**
+ *   メモま! のメイン画面処理
+ *   
+ * @author MRSa
+ */
+public class MeMoMaListener implements OnClickListener, OnTouchListener, OnKeyListener, IObjectSelectionReceiver, ConfirmationDialog.IResultReceiver, ObjectDataInputDialog.IResultReceiver, ItemSelectionDialog.ISelectionItemReceiver, TextEditDialog.ITextEditResultReceiver, ObjectAligner.IAlignCallback, SelectLineShapeDialog.IResultReceiver
+{
+           public static final int MENU_ID_PREFERENCES = (Menu.FIRST + 1);    // 設定画面の表示
+           public static final int MENU_ID_ABOUT_GOKIGEN = (Menu.FIRST + 2);  // アプリケーションの情報表示
+           public static final int MENU_ID_NEW = (Menu.FIRST + 3);                     // 新規作成
+           public static final int MENU_ID_EXTEND= (Menu.FIRST + 4);                   // 拡張機能
+           public static final int MENU_ID_ALIGN = (Menu.FIRST + 5);                     // オブジェクトの整列
+           public static final int MENU_ID_INSERT_PICTURE = (Menu.FIRST + 6);   // 画像の指定
+           public static final int MENU_ID_OPERATION = (Menu.FIRST + 7);           // 操作コマンド
+           public static final int MENU_ID_RENAME = (Menu.FIRST + 8);                // リネーム
+           public static final int MENU_ID_CAPTURE = (Menu.FIRST + 9);              // 画像のキャプチャ
+           public static final int MENU_ID_SHARE = (Menu.FIRST + 10);              // 画像の共有
+           
+
+           private AppCompatActivity parent = null;  // 親分
+           private TextEditDialog editTextDialog = null;   // テキスト編集用ダイアログ
+           private MeMoMaCanvasDrawer objectDrawer = null; // 画像の表示
+           private MeMoMaObjectHolder objectHolder = null;  // オブジェクトの保持クラス
+           private MeMoMaConnectLineHolder lineHolder =null;  // オブジェクト間の接続状態保持クラス
+           //private SelectFeatureListener featureListener = null;  // 機能選択用のリスナ
+           
+           private MeMoMaDataInOutManager dataInOutManager = null;
+           
+           private OperationModeHolder drawModeHolder = null;
+           private LineStyleHolder lineStyleHolder = null;
+           
+           private ConfirmationDialog confirmationDialog = null;
+           
+           private ObjectDataInputDialog objectDataInputDialog = null;
+           
+           private SelectLineShapeDialog lineSelectionDialog = null;
+           
+           private ItemSelectionDialog itemSelectionDialog = null;
+           private ObjectOperationCommandHolder commandHolder = null;
+           
+           private boolean isEditing = false;
+           private Integer  selectedObjectKey = 0;
+           private Integer  objectKeyToDelete = 0;
+           private Integer selectedContextKey = 0;
+
+           /**
+            *  コンストラクタ
+            * @param argument
+            */
+           public MeMoMaListener(AppCompatActivity argument, MeMoMaDataInOutManager inoutManager)
+           {
+               parent = argument;
+               dataInOutManager = inoutManager;
+               lineHolder = new MeMoMaConnectLineHolder();
+               objectHolder = new MeMoMaObjectHolder(argument, lineHolder);
+               editTextDialog = new TextEditDialog(parent, R.drawable.icon);
+               //lineHolder = new MeMoMaConnectLineHolder();
+               //featureListener = new SelectFeatureListener(parent);
+               drawModeHolder = new OperationModeHolder(parent);
+
+               lineStyleHolder = new LineStyleHolder(parent);
+               lineStyleHolder.prepare();
+
+               // 新規作成時の確認ダイアログについて
+               confirmationDialog = new ConfirmationDialog(argument);          
+            confirmationDialog.prepare(this, android.R.drawable.ic_dialog_alert, parent.getString(R.string.createnew_title), parent.getString(R.string.createnew_message));            
+
+            // オブジェクトのデータ入力ダイアログを生成
+            objectDataInputDialog = new ObjectDataInputDialog(argument, objectHolder);
+            objectDataInputDialog.setResultReceiver(this);
+            
+            // 接続線の形状と太さを選択するダイアログを生成
+            lineSelectionDialog = new SelectLineShapeDialog(argument, lineStyleHolder);
+            lineSelectionDialog.setResultReceiver(this);
+            
+            // アイテム選択ダイアログを生成
+            commandHolder = new ObjectOperationCommandHolder(argument);
+            itemSelectionDialog = new ItemSelectionDialog(argument);
+            itemSelectionDialog.prepare(this,  commandHolder, parent.getString(R.string.object_operation));
+            
+               // 描画クラスの生成
+               objectDrawer = new MeMoMaCanvasDrawer(argument, objectHolder, lineStyleHolder, this);
+
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+               String colorString = preferences.getString("backgroundColor", "0xff004000");
+               objectDrawer.setBackgroundColor(colorString);
+
+           }
+
+           /**
+            *  がっつりこのクラスにイベントリスナを接続する
+            * 
+            */
+           public void prepareListener()
+           {
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+
+               // 表示位置リセットボタン
+               final ImageButton homeButton = (ImageButton) parent.findViewById(R.id.HomeButton);
+               homeButton.setOnClickListener(this);
+
+               // 拡張ボタン
+               final ImageButton expandButton = (ImageButton) parent.findViewById(R.id.ExpandButton);
+               expandButton.setOnClickListener(this);
+
+               // 作成ボタン
+               final ImageButton createObjectButton = (ImageButton) parent.findViewById(R.id.CreateObjectButton);
+               createObjectButton.setOnClickListener(this);
+
+               final ImageButton deleteObjectButton = (ImageButton) parent.findViewById(R.id.DeleteObjectButton);
+            deleteObjectButton.setOnClickListener(this);
+
+               // 線の形状切り替えボタン
+               final ImageButton lineStyleButton = (ImageButton) parent.findViewById(R.id.LineStyleButton);
+               lineStyleButton.setOnClickListener(this);
+
+               // データ保存ボタン
+               final ImageButton saveButton = (ImageButton) parent.findViewById(R.id.SaveButton);
+               saveButton.setOnClickListener(this);
+
+               // 画面描画クラス
+               final GokigenSurfaceView surfaceView = (GokigenSurfaceView) parent.findViewById(R.id.GraphicView);
+               surfaceView.setOnTouchListener(this);
+                               
+               // スライドバーが動かされた時の処理
+               final SeekBar seekbar = (SeekBar) parent.findViewById(R.id.ZoomInOut);
+               seekbar.setOnSeekBarChangeListener(objectDrawer);
+               int progress = preferences.getInt("zoomProgress", 50);
+               seekbar.setProgress(progress);
+
+               // 「実行中」の表示を消す
+               parent.setProgressBarIndeterminateVisibility(false);
+               
+            //// 起動時にデータを読み出す          
+               prepareMeMoMaInfo();
+           }
+
+           /**
+            *  終了準備
+            */
+           public void finishListener()
+           {
+               // 終了時に状態を保存する
+            saveData(true);
+           }
+
+           /**
+            *  スタート準備
+            */
+           public void prepareToStart()
+           {
+               //  設定に記録されているデータを画面に反映させる
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+
+               // 描画オブジェクトの形状を設定する
+               //int objectStyle = Integer.parseInt(preferences.getString("drawStyle", "0"));
+
+               // ラインの形状を取得し、設定する
+               setLineStyle();
+
+               // 操作モードを画面に反映させる
+               updateButtons(Integer.parseInt(preferences.getString("operationMode", "0")));
+
+               // 条件に合わせて、描画クラスを変更する
+               final GokigenSurfaceView surfaceView = (GokigenSurfaceView) parent.findViewById(R.id.GraphicView);
+               surfaceView.setCanvasDrawer(objectDrawer);
+
+               // 背景画像(の名前)を設定しておく
+               String backgroundString = preferences.getString("backgroundUri", "");
+            objectDrawer.setBackgroundUri(backgroundString);
+           }
+
+           /**
+            *  終了準備
+            */
+           public void shutdown()
+           {
+               
+           }
+           
+           /**
+            *  他画面から戻ってきたとき...
+            * @param requestCode
+            * @param resultCode
+            * @param data
+            */
+           public void onActivityResult(int requestCode, int resultCode, Intent data)
+           {
+               if ((requestCode == MENU_ID_INSERT_PICTURE)&&(resultCode == Activity.RESULT_OK))
+               {
+                   try
+                   {
+                       // 取得したuri を preferenceに記録する
+                       SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+                       Uri backgroundUri = data.getData();
+                       SharedPreferences.Editor editor = preferences.edit();
+                       editor.putString("backgroundUri", backgroundUri.toString());
+                       editor.commit();
+                       
+                       // 背景画像イメージの更新処理
+                       updateBackgroundImage(backgroundUri.toString());
+                       
+                           System.gc();
+                   }
+                   catch (Exception ex)
+                   {
+                       Log.v(Main.APP_IDENTIFIER, "Ex:" + ex.toString() + " " + ex.getMessage());
+                   }
+                   return;
+               }
+               else if (requestCode == MENU_ID_PREFERENCES)
+            {
+                       // 背景色、背景画像の設定を行う。
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+               String colorString = preferences.getString("backgroundColor", "0xff004000");
+               objectDrawer.setBackgroundColor(colorString);
+
+               // 背景画像イメージの更新処理
+               String backgroundString = preferences.getString("backgroundUri", "");
+               updateBackgroundImage(backgroundString);
+
+               Log.v(Main.APP_IDENTIFIER, "RETURENED PREFERENCES " + backgroundString);
+
+            }
+               else if (requestCode == MENU_ID_EXTEND)
+               {
+                       // その他...今開いているファイルを読みなおす
+                   dataInOutManager.loadFile((String) parent.getTitle());
+               }
+               else
+               {
+                       // 画面表示の準備を実行...
+                       //prepareToStart();
+                       return;
+               }
+            // 画面の再描画を指示する
+                   redrawSurfaceview();
+           }
+
+           /**
+            *    背景画像イメージの更新処理
+            * 
+            */
+           private void updateBackgroundImage(String uri)
+           {
+             // 背景画像イメージの更新処理                
+            GokigenSurfaceView graphView = (GokigenSurfaceView) parent.findViewById(R.id.GraphicView);
+
+            // ビットマップを設定する
+            objectDrawer.updateBackgroundBitmap(uri, graphView.getWidth(), graphView.getHeight());
+
+            // 画面の再描画指示
+            graphView.doDraw();
+           }
+           
+           
+           /**
+            *   クリックされたときの処理
+            */
+           public void onClick(View v)
+           {
+                int id = v.getId();
+
+                //Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::onClick() " + id);
+                if (id == R.id.MeMoMaInfo)
+                {
+                        // テキスト編集ダイアログを表示する
+                 showInfoMessageEditDialog();
+                }
+                else if (id == R.id.LineStyleButton)
+                {
+                        // ライン形状を変えるダイアログで変更するように変更する
+                        selectLineShapeDialog();
+                }
+                else if (id == R.id.ExpandButton)
+                {
+                        // 拡張メニューを呼び出す
+                        callExtendMenu();
+                }
+                else if ((id == R.id.DeleteObjectButton)||(id == R.id.CreateObjectButton))
+                {
+                        // 削除ボタン or 作成ボタンが押された時の処理
+                        updateButtons(drawModeHolder.updateOperationMode(id));
+                }
+                else if (id == R.id.HomeButton)
+                {
+                        /**  表示位置をリセットする **/
+                        // 表示倍率と並行移動についてリセットする
+                        objectDrawer.resetScaleAndLocation((SeekBar) parent.findViewById(R.id.ZoomInOut));
+                        
+                        // 画面の再描画を指示する
+                        redrawSurfaceview();
+            }
+               else if (id == R.id.SaveButton)
+               {
+                       // データ保存が指示された!
+                       saveData(true);
+               }
+           }
+
+           /**
+            *   触られたときの処理
+            * 
+            */
+           public boolean onTouch(View v, MotionEvent event)
+           {
+               int id = v.getId();
+               // int action = event.getAction();
+
+               //Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::onTouch() " + id);
+
+               if (id == R.id.GraphicView)
+               {
+                       // 画面をタッチした!
+                   ((GokigenSurfaceView) v).onTouchEvent(event);
+                   return (true);
+               }
+               return (false);
+           }
+
+           /**
+            *  キーを押したときの操作
+            */
+           public boolean onKey(View v, int keyCode, KeyEvent event)
+           {
+               int action = event.getAction();
+               if ((action == KeyEvent.ACTION_DOWN)&&(keyCode == KeyEvent.KEYCODE_DPAD_CENTER))
+               {
+                       //
+               }
+
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::onKey() ");
+               return (false);
+           }
+
+           /**
+            *   メニューへのアイテム追加
+            * @param menu
+            * @return
+            */
+           public Menu onCreateOptionsMenu(Menu menu)
+           {
+            // 新規作成
+               MenuItem menuItem = menu.add(Menu.NONE, MENU_ID_NEW, Menu.NONE, parent.getString(R.string.createnew));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_add);    // 丸プラス
+
+               // 画像の共有
+               menuItem = menu.add(Menu.NONE, MENU_ID_SHARE, Menu.NONE, parent.getString(R.string.shareContent));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_share);
+
+               // 画像のキャプチャ
+               menuItem = menu.add(Menu.NONE, MENU_ID_CAPTURE, Menu.NONE, parent.getString(R.string.capture_data));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_crop);    // オブジェクトのキャプチャ
+
+               // オブジェクトの整列
+               menuItem = menu.add(Menu.NONE, MENU_ID_ALIGN, Menu.NONE, parent.getString(R.string.align_data));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_rotate);    // オブジェクトの整列
+
+               // タイトルの変更
+               menuItem = menu.add(Menu.NONE, MENU_ID_RENAME, Menu.NONE, parent.getString(R.string.rename_title));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_edit);    // タイトルの変更
+
+               // 壁紙の選択
+               menuItem = menu.add(Menu.NONE, MENU_ID_INSERT_PICTURE, Menu.NONE, parent.getString(R.string.background_data));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_gallery);    // 壁紙の選択
+
+               // 拡張メニュー
+               menuItem = menu.add(Menu.NONE, MENU_ID_EXTEND, Menu.NONE, parent.getString(R.string.extend_menu));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_share);    // 拡張メニュー...
+
+               // 設定
+               menuItem = menu.add(Menu.NONE, MENU_ID_PREFERENCES, Menu.NONE, parent.getString(R.string.preference_name));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_preferences);
+
+            // クレジット情報の表示
+               menuItem = menu.add(Menu.NONE, MENU_ID_ABOUT_GOKIGEN, Menu.NONE, parent.getString(R.string.about_gokigen));
+               menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);   /*  for Android 3.1  */
+               menuItem.setIcon(android.R.drawable.ic_menu_info_details);
+
+               return (menu);
+           }
+
+           /**
+            *   メニュー表示前の処理
+            * @param menu
+            * @return
+            */
+           public void onPrepareOptionsMenu(Menu menu)
+           {
+               menu.findItem(MENU_ID_NEW).setVisible(true);
+               menu.findItem(MENU_ID_SHARE).setVisible(true);
+               menu.findItem(MENU_ID_CAPTURE).setVisible(true);
+               menu.findItem(MENU_ID_ALIGN).setVisible(true);
+               menu.findItem(MENU_ID_RENAME).setVisible(true);
+               menu.findItem(MENU_ID_INSERT_PICTURE).setVisible(true);
+               menu.findItem(MENU_ID_EXTEND).setVisible(true);
+               menu.findItem(MENU_ID_PREFERENCES).setVisible(true);
+               menu.findItem(MENU_ID_ABOUT_GOKIGEN).setVisible(true);
+               return;
+           }
+
+           /**
+            *   メニューのアイテムが選択されたときの処理
+            * @param item
+            * @return
+            */
+           public boolean onOptionsItemSelected(MenuItem item)
+           {
+               boolean result = false;
+               switch (item.getItemId())
+               {
+                 case MENU_ID_PREFERENCES:
+                   showPreference();
+                       result = true;
+                       break;
+
+                 case MENU_ID_ABOUT_GOKIGEN:
+                       showAboutGokigen();
+                       result = true;
+                       break;
+
+                 case MENU_ID_NEW:
+                       createNewScreen();
+                       result = true;
+                       break;
+
+                 case MENU_ID_EXTEND:
+                       // 拡張メニューを呼び出す
+                       callExtendMenu();
+                       result = true;
+                       break;
+
+                 case MENU_ID_ALIGN:
+                // オブジェクトの整列を行う
+                       alignData();
+                result = true;
+                       break;
+
+                 case MENU_ID_RENAME:
+                       // タイトル名の変更  (テキスト編集ダイアログを表示する)
+                   showInfoMessageEditDialog();
+                       result = true;
+                       break;
+
+                 case MENU_ID_INSERT_PICTURE:
+                   // 背景画像の設定を行う
+                       insertPicture();
+                   result = true;
+                           break;
+
+                 case MENU_ID_CAPTURE:
+                       // 画面キャプチャを指示された場合...
+                       doCapture(false);
+                       result = true;
+                       break;
+
+                 case MENU_ID_SHARE:
+                       // 画面キャプチャ&共有を指示された場合...
+                       doCapture(true);
+                       result = true;
+                       break;
+
+                 case android.R.id.home:
+                       /** アイコンが押された時の処理... **/
+                       // テキスト編集ダイアログを表示する
+                   showInfoMessageEditDialog();
+                           result = true;
+                           break;
+
+                 default:
+                       result = false;
+                       break;
+               }
+               return (result);
+           }
+
+           /**
+            *  画像ファイルの挿入 (データファイルの更新)
+            * 
+            */
+           private void insertPicture()
+           {
+               Intent intent = new Intent();
+               intent.setType("image/*");
+               intent.setAction(Intent.ACTION_GET_CONTENT);
+               parent.startActivityForResult(intent, MENU_ID_INSERT_PICTURE);
+           }
+
+           /**
+            *    画面キャプチャの実施
+            * 
+            * @param isShare
+            */
+           private void doCapture(boolean isShare)
+           {
+               // 画面のスクリーンショットをとる処理を実行する
+               dataInOutManager.doScreenCapture((String) parent.getTitle(), objectHolder, objectDrawer, isShare);
+
+               // 画面を再描画する
+            redrawSurfaceview();
+           }
+
+           /**
+            *   アプリの情報を表示する
+            * 
+            */
+           private void showAboutGokigen()
+           {
+               // アプリの情報(クレジット)を表示する!
+               parent.showDialog(R.id.info_about_gokigen);
+           }
+
+           /**
+            *   拡張メニューを呼び出す
+            * 
+            */
+           private void callExtendMenu()
+           {
+               // 現在表示中のデータをファイルに保存する
+               dataInOutManager.saveFile((String) parent.getTitle(), true);
+               
+               // 現在読み込んでいるファイルのファイル名を生成する
+               String fullPath = dataInOutManager.getDataFileFullPath((String) parent.getTitle(), ".xml");
+               
+            //  ここで拡張メニューを呼び出す             
+               // (渡すデータを作って Intentとする)
+               Intent intent = new Intent();
+               
+               intent.setAction(ExtensionActivity.MEMOMA_EXTENSION_LAUNCH_ACTIVITY);
+               intent.putExtra(ExtensionActivity.MEMOMA_EXTENSION_DATA_FULLPATH, fullPath);
+               intent.putExtra(ExtensionActivity.MEMOMA_EXTENSION_DATA_TITLE, (String) parent.getTitle());
+
+               // データ表示用Activityを起動する
+               parent.startActivityForResult(intent, MENU_ID_EXTEND);
+           }
+
+           /**
+            *    データの読み込みを行う
+            * 
+            */
+           private void prepareMeMoMaInfo()
+           {
+               //  設定に記録されているデータを画面のタイトルに反映させる
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+               String memomaInfo = preferences.getString("MeMoMaInfo", parent.getString(R.string.app_name));
+               parent.setTitle(memomaInfo);
+
+               // アクションバーとファイル名の準備
+                       android.support.v7.app.ActionBar bar = parent.getSupportActionBar();
+               if (bar != null)
+               {
+                               dataInOutManager.prepare(objectHolder, bar, memomaInfo);
+                       }
+
+            //dataInOutManager.loadFile((String) parent.getTitle());
+           }
+
+           /**
+            *   データの保存を行う
+            *   
+            *   
+            *   @param forceOverwrite  trueの時は、ファイル名が確定していたときは(確認せずに)上書き保存を自動で行う。
+            *   
+            */
+           private void saveData(boolean forceOverwrite)
+           {
+            dataInOutManager.saveFile((String) parent.getTitle(), forceOverwrite);
+           }
+
+           /**
+            *   データの整列を行う
+            * 
+            */
+           private void alignData()
+           {
+               ObjectAligner aligner = new ObjectAligner(parent, this);
+               aligner.execute(objectHolder);
+           }
+           
+           /**
+            *    メッセージ編集ダイアログを表示する
+            * 
+            */
+           private void showInfoMessageEditDialog()
+           {
+               parent.showDialog(R.id.editTextArea);                   
+           }
+
+           /**
+            *   新規作成が指示されたとき...全部クリアして作りなおして良いか確認する。
+            * 
+            */
+           private void createNewScreen()
+           {
+               parent.showDialog(R.id.confirmation);
+           }
+           
+           /**
+            *    接続線の設定ダイアログを表示する
+            */
+           private void selectLineShapeDialog()
+           {
+               // 接続線の設定ダイアログを表示する...
+               parent.showDialog(R.id.selectline_dialog);
+           }
+
+           /**
+            *    メッセージ編集ダイアログの表示を準備する
+            * 
+            */
+           private void prepareInfoMessageEditDialog(Dialog dialog)
+           {
+               String message = (String) parent.getTitle();
+               editTextDialog.prepare(dialog, this, parent.getString(R.string.dataTitle), message, true);
+           }
+
+           /**
+            *    メッセージ編集ダイアログの表示を準備する
+            * 
+            */
+           private void prepareConfirmationDialog(Dialog dialog)
+           {
+               // Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::prepareConfirmationDialog() " );
+           }
+
+           /**
+            *    オブジェクト入力用ダイアログの表示を準備する
+            * 
+            */
+           private void prepareObjectInputDialog(Dialog dialog)
+           {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::prepareObjectInputDialog(), key: " + selectedObjectKey);
+               
+               //  ダイアログの準備を行う
+               objectDataInputDialog.prepareObjectInputDialog(dialog, selectedObjectKey);
+               
+           }
+
+           /**
+            *   アイテム選択ダイアログの表示を準備する
+            * 
+            * @param dialog
+            */
+           private void prepareItemSelectionDialog(Dialog dialog)
+           {
+               // アイテム選択ダイアログの表示設定
+               // (動的変更時。。。今回は固定なので何もしない)
+           }
+
+           /**
+            *    接続線選択用ダイアログの表示を準備する
+            * 
+            */
+           private void prepareLineSelectionDialog(Dialog dialog)
+           {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::prepareLineSelectionDialog(), key: " + selectedObjectKey);
+               
+               //  ダイアログの準備を行う
+               lineSelectionDialog.prepareSelectLineShapeDialog(dialog, selectedObjectKey);
+           }
+
+           /**
+            *  設定画面を表示する処理
+            */
+           private void showPreference()
+           {
+               try
+               {
+                   // 設定画面を呼び出す
+                   Intent prefIntent = new Intent(parent,jp.sourceforge.gokigen.memoma.Preference.class);
+                   parent.startActivityForResult(prefIntent, MENU_ID_PREFERENCES);
+               }
+               catch (Exception e)
+               {
+                    // 例外発生...なにもしない。
+                        //updater.showMessage("ERROR", MainUpdater.SHOWMETHOD_DONTCARE);
+               }
+           }
+
+        /**
+         *    接続線の形状を反映させる
+         * 
+         */
+           private void setLineStyle()
+           {
+               int buttonId = LineStyleHolder.getLineShapeImageId(lineStyleHolder.getLineStyle(), lineStyleHolder.getLineShape());
+               final ImageButton lineStyleObj = (ImageButton) parent.findViewById(R.id.LineStyleButton);
+               lineStyleObj.setImageResource(buttonId);        
+           }
+
+           /**
+            *    オブジェクトが生成された!
+            * 
+            */
+           public void objectCreated()
+           {
+            // ここで動作モードを移動モードに戻す。
+                drawModeHolder.changeOperationMode(OperationModeHolder.OPERATIONMODE_MOVE);
+                updateButtons(OperationModeHolder.OPERATIONMODE_MOVE);
+
+                  // 画面を再描画する
+                  redrawSurfaceview();
+           }
+
+           /**
+            *    空き領域がタッチされた!
+            * 
+            */
+           public int touchedVacantArea()
+           {
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+               return (Integer.parseInt(preferences.getString("operationMode", "0")));
+           }
+
+           /**
+            *    空き領域でタッチが離された!
+            * 
+            */
+           public int touchUppedVacantArea()
+           {
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+               return (Integer.parseInt(preferences.getString("operationMode", "0")));
+           }
+
+           /**
+            *    オブジェクトを本当に削除して良いか確認した後に、オブジェクトを削除する。
+            * 
+            * @param key
+            */
+           private void removeObject(Integer key)
+           {
+               // 本当に消して良いか、確認をするダイアログを表示して、OKが押されたら消す。
+                AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(parent);
+                alertDialogBuilder.setTitle(parent.getString(R.string.deleteconfirm_title));
+                alertDialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
+                alertDialogBuilder.setMessage(parent.getString(R.string.deleteconfirm_message));
+
+                // 削除するオブジェクトのキーを覚えこむ。
+                objectKeyToDelete = key;
+
+                // OKボタンの生成
+                alertDialogBuilder.setPositiveButton(parent.getString(R.string.confirmYes), new DialogInterface.OnClickListener()
+             {
+                  public void onClick(DialogInterface dialog, int id)
+                  {
+                                   //  削除モードの時... 確認後削除だけど、今は確認なしで削除を行う。
+                               objectHolder.removePosition(objectKeyToDelete);
+                               
+                               // 削除するオブジェクトに接続されている線もすべて削除する
+                               objectHolder.getConnectLineHolder().removeAllConnection(objectKeyToDelete);
+                               
+                               // ダイアログを閉じる
+                          dialog.dismiss();
+
+                          // ここで動作モードを削除モードから移動モードに戻す。
+                                  drawModeHolder.changeOperationMode(OperationModeHolder.OPERATIONMODE_MOVE);
+                                  updateButtons(OperationModeHolder.OPERATIONMODE_MOVE);
+                               
+
+                          // 画面を再描画する
+                          redrawSurfaceview();
+                  }
+              });
+                
+                // Cancelボタンの生成
+                alertDialogBuilder.setNegativeButton(parent.getString(R.string.confirmNo), new DialogInterface.OnClickListener()
+             {
+                 public void onClick(DialogInterface dialog, int id)
+                 {
+                        dialog.cancel();
+                 }
+             });
+               
+                // ダイアログはキャンセル可能に設定する
+                alertDialogBuilder.setCancelable(true);
+
+                // ダイアログを表示する
+                AlertDialog alertDialog = alertDialogBuilder.create();
+                alertDialog.show();
+
+                return;
+           }
+
+           /**
+            *    オブジェクトを複製する
+            * 
+            * @param key
+            */
+           private void duplicateObject(Integer key)
+           {
+               // 選択中オブジェクトを複製する
+               objectHolder.duplicatePosition(key);
+
+               // 画面を再描画する
+          redrawSurfaceview();
+           }       
+
+           /**
+            *    オブジェクトを拡大する
+            * 
+            * @param key
+            */
+           private void expandObject(Integer key)
+           {
+               // 選択中オブジェクトを拡大する
+               objectHolder.expandObjectSize(key);
+
+               // 画面を再描画する
+          redrawSurfaceview();
+           }       
+           /**
+            *    オブジェクトを縮小する
+            * 
+            * @param key
+            */
+           private void shrinkObject(Integer key)
+           {
+               // 選択中オブジェクトを縮小する
+               objectHolder.shrinkObjectSize(key);
+
+               // 画面を再描画する
+          redrawSurfaceview();
+           }
+
+            private void setButtonBorder(ImageButton button, boolean isHighlight)
+             {
+               try
+               {
+                     BitmapDrawable btnBackgroundShape = (BitmapDrawable)button.getBackground();
+                     if (isHighlight == true)
+                     {
+//                             btnBackgroundShape.setColorFilter(Color.rgb(51, 181, 229), Mode.LIGHTEN);
+                       btnBackgroundShape.setColorFilter(Color.BLUE, Mode.LIGHTEN);
+                     }
+                     else
+                     {
+                       btnBackgroundShape.setColorFilter(Color.BLACK, Mode.LIGHTEN);
+                     } 
+               }
+               catch (Exception ex)
+               {
+                       // 
+                       Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::setButtonBorder(): " + ex.toString());
+               }
+             }      
+
+            /**
+            *   ボタンを更新する
+            * 
+            */
+           private void updateButtons(int mode)
+           {
+               final ImageButton createObjectButton = (ImageButton) parent.findViewById(R.id.CreateObjectButton);
+               final ImageButton deleteObjectButton = (ImageButton) parent.findViewById(R.id.DeleteObjectButton);
+
+               if (mode == OperationModeHolder.OPERATIONMODE_DELETE)
+               {
+                       setButtonBorder(createObjectButton, false);
+                       setButtonBorder(deleteObjectButton, true);
+               }
+               else if (mode == OperationModeHolder.OPERATIONMODE_CREATE)
+               {
+                       setButtonBorder(createObjectButton, true);
+                       setButtonBorder(deleteObjectButton, false);                     
+               }
+               else // if (mode == OperationModeHolder.OPERATIONMODE_MOVE)
+               {
+                       setButtonBorder(createObjectButton, false);
+                       setButtonBorder(deleteObjectButton, false);                     
+               }
+           }
+
+           
+           /**
+            *   オブジェクトが選択された(長押しで!)
+            * 
+            */
+           public void objectSelectedContext(Integer key)
+           {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::objectSelectedContext(),  key:" + key);
+               selectedContextKey = key;
+
+               // オブジェクトのアイテム選択ダイアログを表示する...
+               parent.showDialog(MENU_ID_OPERATION);
+
+           }
+           
+           
+           /**
+            *   オブジェクトが選択された!
+            * 
+            */
+           public boolean objectSelected(Integer key)
+           {
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+               int operationMode = Integer.parseInt(preferences.getString("operationMode", "0"));
+               if (operationMode == OperationModeHolder.OPERATIONMODE_DELETE)
+               {
+                       // オブジェクトを削除する
+                       removeObject(key);
+                       
+                       return (true);
+               }
+               //if ((operationMode == OperationModeHolder.OPERATIONMODE_MOVE)||
+               //              (operationMode == OperationModeHolder.OPERATIONMODE_CREATE))
+               {
+                       // 選択されたオブジェクトを記憶する
+                       selectedObjectKey = key;
+                       Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::objectSelected() key : " + key);
+
+                       // オブジェクトの詳細設定ダイアログを表示する...
+                       parent.showDialog(R.id.objectinput_dialog);
+               }
+               return (true);
+           }
+           
+           /**
+            *  ダイアログの生成
+            * 
+            */
+           public Dialog onCreateDialog(int id)
+           {
+            if (id == R.id.info_about_gokigen)
+           {
+               // クレジットダイアログを表示
+                   CreditDialog dialog = new CreditDialog(parent);
+                   return (dialog.getDialog());
+           }
+            if (id == R.id.editTextArea)
+            {
+                       // 変更するテキストを表示
+                return (editTextDialog.getDialog());
+            }
+            if (id == R.id.confirmation)
+            {
+               // 確認するメッセージを表示する
+               return (confirmationDialog.getDialog());
+            }
+            if (id == R.id.objectinput_dialog)
+            {
+               // オブジェクト入力のダイアログを表示する
+               return (objectDataInputDialog.getDialog());
+            }
+            if (id == MENU_ID_OPERATION)
+            {
+               // アイテム選択ダイアログの準備を行う
+               return (itemSelectionDialog.getDialog());
+            }
+            if (id == R.id.selectline_dialog)
+            {
+               // 接続線選択ダイアログの準備を行う
+               return (lineSelectionDialog.getDialog());
+            }
+               return (null);
+           }
+
+           /**
+            *  ダイアログ表示の準備
+            * 
+            */
+           public void onPrepareDialog(int id, Dialog dialog)
+           {
+            if (id == R.id.editTextArea)
+            {
+               // 変更するデータを表示する
+               prepareInfoMessageEditDialog(dialog);
+               return;
+            }
+            if (id == R.id.confirmation)
+            {
+               // 確認ダイアログを表示する。
+               prepareConfirmationDialog(dialog);
+               return;
+            }
+            if (id == R.id.objectinput_dialog)
+            {
+               // オブジェクト入力のダイアログを表示する
+               prepareObjectInputDialog(dialog);
+            }
+            if (id == MENU_ID_OPERATION)
+            {
+               // オブジェクト操作選択のダイアログを表示する
+               prepareItemSelectionDialog(dialog);
+            }
+            if (id == R.id.selectline_dialog)
+            {
+               // 接続線選択のダイアログを表示する
+               prepareLineSelectionDialog(dialog);
+            }
+           }
+
+        /**
+         *    新規状態に変更する。
+         * 
+         */
+        public void acceptConfirmation()
+        {
+            //
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::acceptConfirmation()");
+               
+               // オブジェクトデータをクリアする。
+           objectHolder.removeAllPositions();  // オブジェクトの保持クラス
+           objectHolder.getConnectLineHolder().removeAllLines();  // オブジェクト間の接続状態保持クラス
+
+               // 画面の倍率と表示位置を初期状態に戻す
+               if (objectDrawer != null)
+               {
+               final SeekBar zoomBar = (SeekBar) parent.findViewById(R.id.ZoomInOut);
+                       objectDrawer.resetScaleAndLocation(zoomBar);
+               }
+
+               /**
+               // 題名を "無題"に変更し、関係情報をクリアする
+               String newName = parent.getString(R.string.no_name);
+               parent.setTitle(newName);
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+            SharedPreferences.Editor editor = preferences.edit();
+            editor.putString("MeMoMaInfo", newName);
+            editor.commit();
+            **/
+            
+               // 画面を再描画する
+            redrawSurfaceview();
+
+            // ファイル名選択ダイアログを開く
+            showInfoMessageEditDialog();
+
+        }
+
+        /**
+         *   画面を再描画する
+         * 
+         */
+        private void redrawSurfaceview()
+        {
+               final GokigenSurfaceView surfaceview = (GokigenSurfaceView) parent.findViewById(R.id.GraphicView);
+               surfaceview.doDraw();           
+        }
+        
+        /**
+         *    不許可。何もしない。
+         * 
+         */
+        public  void rejectConfirmation()
+        {
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::rejectConfirmation()");
+        }
+
+        /**
+         *   オブジェクトが整列された時の処理
+         * 
+         */
+        public void objectAligned()
+        {
+            // 画面の再描画を指示する
+                   redrawSurfaceview();                
+        }
+        
+        /**
+         *   オブジェクト編集ダイアログが閉じられた時の処理
+         * 
+         */
+        public void finishObjectInput()
+        {
+            // 画面の再描画を指示する
+                   redrawSurfaceview();
+        }
+        
+        /**
+         *   オブジェクト編集ダイアログが閉じられた時の処理
+         * 
+         */
+        public void cancelObjectInput()
+        {
+            // 何もしない 
+        }
+        
+        
+        /**
+         *   現在編集中かどうかを知る
+         * 
+         * @return
+         */
+        public boolean isEditing()
+        {
+               return (isEditing);
+        }
+
+        /**
+         *   現在編集中のフラグを更新する
+         * 
+         * @param value
+         */
+        public void setIsEditing(boolean value)
+        {
+               isEditing = value;
+        }
+
+        /**
+         *   アイテムが選択された!
+         * 
+         */
+        public void itemSelected(int index, String itemValue)
+        {
+            //
+               Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::itemSelected() : " + itemValue + " [" + index + "]");
+               
+               if (index == ObjectOperationCommandHolder.OBJECTOPERATION_DELETE)
+               {
+                       // オブジェクト削除の確認
+                       removeObject(selectedContextKey);
+               }
+               else if (index == ObjectOperationCommandHolder.OBJECTOPERATION_DUPLICATE)
+               {
+                       // オブジェクトの複製
+                       duplicateObject(selectedContextKey);                    
+               }
+               else if (index == ObjectOperationCommandHolder.OBJECTOPERATION_SIZEBIGGER)
+               {
+                       // オブジェクトの拡大
+                       expandObject(selectedContextKey);
+               }
+               else if (index == ObjectOperationCommandHolder.OBJECTOPERATION_SIZESMALLER)
+               {
+                       // オブジェクトの縮小
+                       shrinkObject(selectedContextKey);
+               }
+        }
+
+        /**
+         *    (今回未使用)
+         * 
+         */
+        public void itemSelectedMulti(String[] items, boolean[] status)
+        {
+               
+        }
+        public void canceledSelection()
+        {
+               
+        }
+        
+        public void onSaveInstanceState(Bundle outState)
+        {
+           /* ここで状態を保存 */ 
+           //Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::onSaveInstanceState()");
+        }
+        
+        public void onRestoreInstanceState(Bundle savedInstanceState)
+        {
+               /* ここで状態を復元 */
+           Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::onRestoreInstanceState()");
+        }
+
+        public boolean finishTextEditDialog(String message)
+        {
+               if ((message == null)||(message.length() == 0))
+               {
+                // データが入力されていなかったので、何もしない。
+                       return (false);
+               }
+               
+               // 文字列を記録
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+            SharedPreferences.Editor editor = preferences.edit();
+            editor.putString("MeMoMaInfo", message);
+            editor.commit();
+
+            // タイトルに設定
+            parent.setTitle(message);
+
+            // 保存シーケンスを一度走らせる 
+            saveData(true);
+
+            // ファイル選択リストの更新
+            dataInOutManager.updateFileList(message, parent.getSupportActionBar());
+
+            return (true);
+        }
+        public boolean cancelTextEditDialog()
+        {
+            return (false);
+        }
+
+        /**
+         *    接続線
+         * 
+         */
+        public void finishSelectLineShape(int style, int shape, int thickness)
+        {
+               int buttonId = LineStyleHolder.getLineShapeImageId(style, shape);
+            final ImageButton lineStyleObj = (ImageButton) parent.findViewById(R.id.LineStyleButton);
+            lineStyleObj.setImageResource(buttonId);   
+            //Log.v(Main.APP_IDENTIFIER, "MeMoMaListener::finishSelectLineShape() buttonId:" + buttonId);
+        }
+
+        /**
+         * 
+         * 
+         */
+        public void cancelSelectLineShape()
+        {
+               
+        }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaObjectHolder.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/MeMoMaObjectHolder.java
new file mode 100644 (file)
index 0000000..6cf48e5
--- /dev/null
@@ -0,0 +1,420 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.Log;
+import android.widget.Toast;
+
+/**
+ *   表示オブジェクトの情報を保持するクラス
+ * 
+ * @author MRSa
+ *
+ */
+public class MeMoMaObjectHolder
+{
+       public static final int ID_NOTSPECIFY = -1;
+       
+    public static final int DRAWSTYLE_RECTANGLE = 0;
+    public static final int DRAWSTYLE_ROUNDRECT = 1;
+    public static final int DRAWSTYLE_OVAL = 2;
+    public static final int DRAWSTYLE_DIAMOND = 3;
+    public static final int DRAWSTYLE_HEXAGONAL = 4;
+    public static final int DRAWSTYLE_PARALLELOGRAM = 5;
+    public static final int DRAWSTYLE_KEYBOARD = 6;
+    public static final int DRAWSTYLE_PAPER = 7;
+    public static final int DRAWSTYLE_DRUM = 8;
+    public static final int DRAWSTYLE_CIRCLE = 9;
+    public static final int DRAWSTYLE_NO_REGION = 10;
+    
+    public static final int DRAWSTYLE_LOOP_START = 11;
+    public static final int DRAWSTYLE_LOOP_END = 12;
+    public static final int DRAWSTYLE_LEFT_ARROW = 13;
+    public static final int DRAWSTYLE_DOWN_ARROW = 14;
+    public static final int DRAWSTYLE_UP_ARROW = 15;
+    public static final int DRAWSTYLE_RIGHT_ARROW = 16;
+
+    public static final float ROUNDRECT_CORNER_RX = 8;
+    public static final float ROUNDRECT_CORNER_RY = 8;
+    
+    public static final float STOROKE_BOLD_WIDTH = 3.5f;
+    public static final float STOROKE_NORMAL_WIDTH = 0.0f;
+    
+    public static final float DUPLICATEPOSITION_MARGIN = 15.0f;
+
+    public static final float OBJECTSIZE_DEFAULT_X = 144.0f;
+       public static final float OBJECTSIZE_DEFAULT_Y = (OBJECTSIZE_DEFAULT_X / 16.0f * 9.0f);
+
+       public static final float OBJECTSIZE_MINIMUM_X = 48.0f;
+       public static final float OBJECTSIZE_MINIMUM_Y = (OBJECTSIZE_MINIMUM_X / 16.0f * 9.0f);
+       
+       public static final float OBJECTSIZE_MAXIMUM_X = 14400.0f;
+       public static final float OBJECTSIZE_MAXIMUM_Y =  (OBJECTSIZE_MAXIMUM_X / 16.0f * 9.0f);
+
+       public static final float OBJECTSIZE_STEP_X = OBJECTSIZE_MINIMUM_X * 1.0f;
+       public static final float OBJECTSIZE_STEP_Y = OBJECTSIZE_MINIMUM_Y * 1.0f;
+       
+       public static final float FONTSIZE_DEFAULT = 12.0f;
+       
+    private MeMoMaConnectLineHolder connectLineHolder = null;
+    
+    /**
+     *    オブジェクトの情報 
+     * 
+     * @author MRSa
+     *
+     */
+       public class PositionObject
+       {
+               private Integer key;                 // オブジェクト識別子 (変更不可)
+               public RectF rect;                    // オブジェクトの大きさ
+           public int drawStyle;               // オブジェクトの形状
+
+           public int icon;                        // オブジェクトのアイコン
+           public String label;                   // オブジェクトの表示ラベル
+           public String detail;                  // オブジェクトの説明
+           //public String backgroundUri;     // オブジェクトの背景画像
+           //public String otherInfoUri;        // 補足(写真とかへのURI)
+           //public String objectStatus;        // オブジェクトの状態
+           public boolean userChecked;    // ユーザチェックボックス
+
+           public int labelColor;               // オブジェクト内に表示する色
+           public int objectColor;             // オブジェクトの色
+           public String paintStyle;           // オブジェクトの表示方法 (枠線のみ、塗りつぶし、塗りつぶしと枠線)
+           public float strokeWidth;         // 枠線の太さ
+           public float fontSize;               // フォントサイズ
+
+           /**
+            *    コンストラクタ (キーを設定する)
+            * @param id
+            */
+           public PositionObject(int id)
+           {
+               key = id;
+           }
+
+           /**
+            *    オブジェクトのキーを取得する
+            * @return
+            */
+           public Integer getKey()
+           {
+               return (key);
+           }
+       };
+
+       private Hashtable<Integer, PositionObject> objectPoints = null;
+       private Integer serialNumber = 1;
+       private String  dataTitle = "";
+       private String  background = "";
+       private Context parent = null;
+
+    public MeMoMaObjectHolder(Context context, MeMoMaConnectLineHolder lineHolder)
+    {
+                 objectPoints = new Hashtable<Integer, PositionObject>();
+                 connectLineHolder = lineHolder;
+                 parent = context;
+    }
+
+    /**
+     *    データの有無を見る (true の場合、データはない。)
+     * 
+     * @return
+     */
+    public boolean isEmpty()
+    {  
+       if ((connectLineHolder == null)||(objectPoints == null))
+       {
+               return (true);
+       }
+       return (objectPoints.isEmpty());
+    }
+    
+    public MeMoMaConnectLineHolder getConnectLineHolder()
+    {
+       return (connectLineHolder);
+    }
+    
+    public void setDataTitle(String title)
+    {
+       dataTitle = title;
+    }
+    
+    public String getDataTitle()
+    {
+       return (dataTitle);
+    }
+
+    public void setBackground(String data)
+    {
+       background = data;
+    }
+    
+    public String getBackground()
+    {
+       return (background);
+    }
+
+    public int getCount()
+    {
+       return (objectPoints.size());
+    }
+
+    public Enumeration<Integer> getObjectKeys()
+    {
+       return (objectPoints.keys());
+    }
+
+    public PositionObject getPosition(Integer key)
+    {
+        return  (objectPoints.get(key));
+    }
+
+    public boolean removePosition(Integer key)
+    {
+       objectPoints.remove(key);
+       Log.v(Main.APP_IDENTIFIER, "REMOVE : " + key);
+       return (true);
+    }
+    
+    public void removeAllPositions()
+    {
+        objectPoints.clear();
+        serialNumber = 1;
+    }
+
+    public void setSerialNumber(int id)
+    {
+       serialNumber = (id == ID_NOTSPECIFY) ? ++serialNumber : id;
+    }
+    
+    public int getSerialNumber()
+    {
+       return (serialNumber);
+    }
+
+    public void dumpPositionObject(PositionObject position)
+    {
+       if (position == null)
+       {
+               return;
+       }
+        Log.v(Main.APP_IDENTIFIER, "[" + position.rect.left + "," + position.rect.top + "][" + position.rect.right + "," + position.rect.bottom + "] " + "label : " + position.label + " detail : " + position.detail);
+    }
+    
+    
+    /**
+     *   オブジェクトを複製する。
+     * 
+     * @param key
+     * @return
+     */
+    public PositionObject duplicatePosition(int key)
+    {
+       PositionObject orgPosition = objectPoints.get(key);
+       if (orgPosition == null)
+       {
+               // 元のオブジェクトが見つからなかったので、何もせずに戻る
+               return (null);
+       }
+       PositionObject position = new PositionObject(serialNumber);
+       position.rect = new RectF();
+       position.rect.left = orgPosition.rect.left + DUPLICATEPOSITION_MARGIN;
+       position.rect.right = orgPosition.rect.right + DUPLICATEPOSITION_MARGIN;
+       position.rect.top = orgPosition.rect.top + DUPLICATEPOSITION_MARGIN;
+       position.rect.bottom = orgPosition.rect.bottom + DUPLICATEPOSITION_MARGIN;
+       position.drawStyle = orgPosition.drawStyle;
+       position.icon = orgPosition.icon;
+       position.label = orgPosition.label;
+       position.detail = orgPosition.detail;
+       //position.otherInfoUri = orgPosition.otherInfoUri;
+       //position.backgroundUri = orgPosition.backgroundUri;
+       //position.objectStatus = orgPosition.objectStatus;
+       position.userChecked = orgPosition.userChecked;
+       position.objectColor = orgPosition.objectColor;
+       position.labelColor = orgPosition.labelColor;
+       position.paintStyle = orgPosition.paintStyle;
+       position.strokeWidth = orgPosition.strokeWidth;
+       position.fontSize = orgPosition.fontSize;
+               objectPoints.put(serialNumber, position);
+               serialNumber++;
+               return (position);
+    }
+
+    public PositionObject createPosition(int id)
+    {
+       PositionObject position = new PositionObject(id);
+       position.rect = new RectF();
+       position.rect.top = 0;
+       position.rect.bottom = OBJECTSIZE_DEFAULT_Y;
+       position.rect.left = 0;
+       position.rect.right = OBJECTSIZE_DEFAULT_X;
+       position.drawStyle = MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE;
+       position.icon = 0;
+       position.label = "";
+       position.detail = "";
+       //position.otherInfoUri = "";
+       //position.backgroundUri = "";
+       //position.objectStatus = "";
+       position.userChecked = false;
+       position.objectColor = Color.WHITE;
+       position.labelColor = Color.WHITE;
+       position.paintStyle = Paint.Style.STROKE.toString();
+       position.strokeWidth = STOROKE_NORMAL_WIDTH;
+       position.fontSize = FONTSIZE_DEFAULT;
+               objectPoints.put(id, position);
+               return (position);      
+    }
+    
+    public PositionObject createPosition(float x, float y, int drawStyle)
+    {
+       PositionObject position = createPosition(serialNumber);
+       position.rect.left = position.rect.left + x;
+       position.rect.right = position.rect.right + x;
+       position.rect.top = position.rect.top + y;
+       position.rect.bottom = position.rect.bottom + y;
+       position.drawStyle = drawStyle;
+               serialNumber++;
+               return (position);
+    }
+
+    /**
+     *   オブジェクトのサイズを拡大する
+     * 
+     * @param key
+     */
+    public void expandObjectSize(Integer key)
+    {
+       PositionObject position = objectPoints.get(key);
+       if (position == null)
+       {
+               // 元のオブジェクトが見つからなかったので、何もせずに戻る
+               return;
+       }
+        float width = position.rect.right - position.rect.left;
+        float height = position.rect.bottom - position.rect.top;
+        if (((width + (OBJECTSIZE_STEP_X * 2.0f)) > OBJECTSIZE_MAXIMUM_X)||((height + (OBJECTSIZE_STEP_Y * 2.0f)) > OBJECTSIZE_MAXIMUM_Y))
+        {
+            // 拡大リミットだった。。。拡大しない
+               String outputMessage = parent.getString(R.string.object_bigger_limit) + " ";
+            Toast.makeText(parent, outputMessage, Toast.LENGTH_SHORT).show();
+            return;
+        }
+        position.rect.left = position.rect.left - OBJECTSIZE_STEP_X;
+        position.rect.right = position.rect.right + OBJECTSIZE_STEP_X;
+        position.rect.top = position.rect.top - OBJECTSIZE_STEP_Y;
+        position.rect.bottom = position.rect.bottom + OBJECTSIZE_STEP_Y;       
+    }
+
+    /**
+     *   オブジェクトのサイズを縮小する
+     * 
+     * @param key
+     */
+    public void shrinkObjectSize(Integer key)
+    {
+       PositionObject position = objectPoints.get(key);
+       if (position == null)
+       {
+               // 元のオブジェクトが見つからなかったので、何もせずに戻る
+               return;
+       }
+        float width = position.rect.right - position.rect.left;
+        float height = position.rect.bottom - position.rect.top;
+        if (((width - (OBJECTSIZE_STEP_X * 2.0f)) < OBJECTSIZE_MINIMUM_X)||((height - (OBJECTSIZE_STEP_Y * 2.0f)) < OBJECTSIZE_MINIMUM_Y))
+        {
+            // 縮小リミットだった。。。縮小しない
+               String outputMessage = parent.getString(R.string.object_small_limit) + " ";
+            Toast.makeText(parent, outputMessage, Toast.LENGTH_SHORT).show();
+            return;
+        }
+        position.rect.left = position.rect.left + OBJECTSIZE_STEP_X;
+        position.rect.right = position.rect.right - OBJECTSIZE_STEP_X;
+        position.rect.top = position.rect.top + OBJECTSIZE_STEP_Y;
+        position.rect.bottom = position.rect.bottom - OBJECTSIZE_STEP_Y;               
+    }
+
+    public MeMoMaConnectLineHolder getLineHolder()
+       {
+               return (connectLineHolder);
+       }
+       
+       static public int getObjectDrawStyleIcon(int drawStyle)
+       {
+               int icon = 0;
+       if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE)
+       {
+               icon  = R.drawable.btn_rectangle;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_ROUNDRECT)
+       {
+               icon = R.drawable.btn_roundrect;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_OVAL)
+       {
+               icon = R.drawable.btn_oval;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DIAMOND)
+       {
+               icon = R.drawable.btn_diamond;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_HEXAGONAL)
+       {
+               icon = R.drawable.btn_hexagonal;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_PARALLELOGRAM)
+       {
+               icon = R.drawable.btn_parallelogram;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_KEYBOARD)
+       {
+               icon = R.drawable.btn_keyboard;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_PAPER)
+       {
+               icon = R.drawable.btn_paper;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DRUM)
+       {
+               icon = R.drawable.btn_drum;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_CIRCLE)
+       {
+               icon = R.drawable.btn_circle;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_NO_REGION)
+       {
+               icon = R.drawable.btn_noregion;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LOOP_START)
+       {
+               icon = R.drawable.btn_trapezoidy_up;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LOOP_END)
+       {
+               icon = R.drawable.btn_trapezoidy_down;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LEFT_ARROW)
+       {
+               icon = R.drawable.btn_arrow_left;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DOWN_ARROW)
+       {
+               icon = R.drawable.btn_arrow_down;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_UP_ARROW)
+       {
+               icon = R.drawable.btn_arrow_up;
+       }
+       else if (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_RIGHT_ARROW)
+       {
+               icon = R.drawable.btn_arrow_right;
+       }
+       return (icon);
+       }
+       
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectAligner.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectAligner.java
new file mode 100644 (file)
index 0000000..1e79817
--- /dev/null
@@ -0,0 +1,123 @@
+package jp.sourceforge.gokigen.memoma;
+
+
+import java.util.Enumeration;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.Log;
+
+/**
+ *  オブジェクトの位置を整列するクラス (非同期処理を実行)
+ *  
+ *  AsyncTask
+ *    MeMoMaObjectHolder : 実行時に渡すクラス(Param)
+ *    Integer    : 途中経過を伝えるクラス(Progress)
+ *    String     : 処理結果を伝えるクラス(Result)
+ *    
+ * @author MRSa
+ *
+ */
+public class ObjectAligner extends AsyncTask<MeMoMaObjectHolder, Integer, String>
+{
+       ProgressDialog executingDialog = null;
+       IAlignCallback  receiver = null;
+       /**
+        *   コンストラクタ
+        */
+    public ObjectAligner(Context context, IAlignCallback client)
+    {
+        receiver = client;
+       
+       //  プログレスダイアログ(「保存中...」)を表示する。
+       executingDialog = new ProgressDialog(context);
+       executingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+       executingDialog.setMessage(context.getString(R.string.dataAligning));
+       executingDialog.setIndeterminate(true);
+       executingDialog.setCancelable(false);
+       executingDialog.show();
+    }
+       
+    /**
+     *  非同期処理実施前の前処理
+     * 
+     */
+    @Override
+    protected void onPreExecute()
+    {
+       
+    }
+
+    /**
+     *  非同期処理
+     *  (バックグラウンドで実行する(このメソッドは、UIスレッドと別のところで実行する))
+     * 
+     */
+    @Override
+    protected String doInBackground(MeMoMaObjectHolder... datas)
+    {
+       MeMoMaObjectHolder objectHolder = datas[0];
+
+       // オブジェクトの出力 (保持しているものはすべて表示する)
+       Enumeration<Integer> keys = objectHolder.getObjectKeys();
+        while (keys.hasMoreElements())
+        {
+            Integer key = keys.nextElement();
+            MeMoMaObjectHolder.PositionObject pos = objectHolder.getPosition(key);
+            
+            float newLeft = (float) Math.floor((pos.rect.left + 15.0f)/ 30.0) * 30.0f;
+            float newTop = (float) Math.floor((pos.rect.top + 15.0f)/ 30.0) * 30.0f;
+            pos.rect.offsetTo(newLeft, newTop);
+        }
+        System.gc();
+               
+               return ("");
+    }
+
+    /**
+     *  非同期処理の進捗状況の更新
+     * 
+     */
+       @Override
+       protected void onProgressUpdate(Integer... values)
+       {
+        // 今回は何もしない
+       }
+
+    /**
+     *  非同期処理の後処理
+     *  (結果を応答する)
+     */
+    @Override
+    protected void onPostExecute(String result)
+    {
+       try
+       {
+               if (receiver != null)
+               {
+                       // 並べ変えたことを通知する
+                       receiver.objectAligned();
+               }
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "ObjectAligner::onPostExecute() : " + ex.toString());
+       }
+
+       // プログレスダイアログを消す
+       executingDialog.dismiss();
+        return;
+    }     
+    
+    /**
+     *    並べ変えたことを通知する
+     * 
+     * @author MRSa
+     *
+     */
+    public interface IAlignCallback
+    {
+        public abstract void objectAligned();
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectDataInputDialog.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectDataInputDialog.java
new file mode 100644 (file)
index 0000000..d321bf9
--- /dev/null
@@ -0,0 +1,577 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.GradientDrawable;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.CompoundButton;
+
+/**
+ *   オブジェクトのデータを入力するダイアログを表示する
+ * 
+ * @author MRSa
+ *
+ */
+public class ObjectDataInputDialog implements SeekBar.OnSeekBarChangeListener, CompoundButton.OnCheckedChangeListener, ImageButton.OnClickListener
+{
+       private final float FONTSIZE_SMALL = 4.0f;
+       private final float FONTSIZE_MIDDLE = 6.0f;
+       private final float FONTSIZE_LARGE = 10.0f;
+       
+       private Context context = null; 
+       private IResultReceiver resultReceiver = null;
+       private MeMoMaObjectHolder objectHolder = null;
+       private Integer key = 0;
+       
+       private View dialogLayout = null;
+       private TextView  colorBorderAreaView = null;
+       private SeekBar borderColorView = null;
+    private CheckBox  fillObjectView = null;
+    private GradientDrawable backgroundShape = null;
+    private int backgroundColor = MeMoMaCanvasDrawer.BACKGROUND_COLOR_DEFAULT; 
+    private int currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE;
+    private float textFontSize = 6.0f;
+       
+       public ObjectDataInputDialog(Context arg, MeMoMaObjectHolder holder)
+       {
+               context = arg;
+               objectHolder = holder;
+       }
+
+       public void setResultReceiver(IResultReceiver receiver)
+       {
+               resultReceiver = receiver;
+       }
+       
+    /**
+     *   確認ダイアログを応答する
+     * @return
+     */
+    public Dialog getDialog()
+    {
+       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final View layout = inflater.inflate(R.layout.objectinput, null);
+        dialogLayout = layout;
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+
+        //  ダイアログで表示するデータを設定する場所
+        
+        // 背景色を設定する
+        try
+        {
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+            String colorString = preferences.getString("backgroundColor", "0xff004000");
+            backgroundColor = Color.parseColor(colorString);
+        }
+        catch (Exception e)
+        {
+            backgroundColor = MeMoMaCanvasDrawer.BACKGROUND_COLOR_DEFAULT;
+        }
+
+        final TextView colorLabel = (TextView) layout.findViewById(R.id.setBorderColorLabel);
+        backgroundShape = (GradientDrawable)colorLabel.getBackground();
+
+        // 入力文字列の色を設定する
+        final EditText label = (EditText) layout.findViewById(R.id.labelInputArea);
+       // label.setTextColor(Color.LTGRAY);
+
+        final EditText detail = (EditText) layout.findViewById(R.id.descriptionInputArea);
+        //detail.setTextColor(Color.LTGRAY);
+
+        borderColorView = (SeekBar) layout.findViewById(R.id.borderColorSelectionBar);
+        borderColorView.setOnSeekBarChangeListener(this);        
+        
+        final CheckBox userCheckbox = (CheckBox) layout.findViewById(R.id.checkUserCheckbox);
+        final CheckBox boldText = (CheckBox) layout.findViewById(R.id.checkBoldText);
+        fillObjectView = (CheckBox) layout.findViewById(R.id.checkFillObject);
+        fillObjectView.setOnCheckedChangeListener(this);
+
+        colorBorderAreaView = (TextView) layout.findViewById(R.id.borderColorArea);
+        colorBorderAreaView.setOnClickListener(this);
+        
+        final ImageButton rect = (ImageButton) layout.findViewById(R.id.btnObjectRectangle);
+        rect.setOnClickListener(this);
+        final ImageButton roundRect = (ImageButton) layout.findViewById(R.id.btnObjectRoundRect);
+        roundRect.setOnClickListener(this);
+        final ImageButton oval = (ImageButton) layout.findViewById(R.id.btnObjectOval);
+        oval.setOnClickListener(this);
+        final ImageButton diamond = (ImageButton) layout.findViewById(R.id.btnObjectDiamond);
+        diamond.setOnClickListener(this);
+        final ImageButton hexagonal = (ImageButton) layout.findViewById(R.id.btnObjectHexagonal);
+        hexagonal.setOnClickListener(this);
+        final ImageButton parallelogram = (ImageButton) layout.findViewById(R.id.btnObjectParallelogram);
+        parallelogram.setOnClickListener(this);
+        final ImageButton keyboard = (ImageButton) layout.findViewById(R.id.btnObjectKeyboard);
+        keyboard.setOnClickListener(this);
+        final ImageButton paper = (ImageButton) layout.findViewById(R.id.btnObjectPaper);
+        paper.setOnClickListener(this);
+        final ImageButton drum = (ImageButton) layout.findViewById(R.id.btnObjectDrum);
+        drum.setOnClickListener(this);
+        final ImageButton circle = (ImageButton) layout.findViewById(R.id.btnObjectCircle);
+        circle.setOnClickListener(this);
+        final ImageButton noregion = (ImageButton) layout.findViewById(R.id.btnObjectNoRegion);
+        noregion.setOnClickListener(this);
+
+        final ImageButton loopStart = (ImageButton) layout.findViewById(R.id.btnObjectLoopStart);
+        loopStart.setOnClickListener(this);
+        final ImageButton loopEnd = (ImageButton) layout.findViewById(R.id.btnObjectLoopEnd);
+        loopEnd.setOnClickListener(this);
+        final ImageButton leftArrow = (ImageButton) layout.findViewById(R.id.btnObjectLeftArrow);
+        leftArrow.setOnClickListener(this);
+        final ImageButton downArrow = (ImageButton) layout.findViewById(R.id.btnObjectDownArrow);
+        downArrow.setOnClickListener(this);
+        final ImageButton upArrow = (ImageButton) layout.findViewById(R.id.btnObjectUpArrow);
+        upArrow.setOnClickListener(this);
+        final ImageButton rightArrow = (ImageButton) layout.findViewById(R.id.btnObjectRightArrow);
+        rightArrow.setOnClickListener(this);
+
+        // 背景の色を調整(塗りつぶしの時はオブジェクトの色とする。)
+        int color = convertColor(borderColorView.getProgress());
+               colorBorderAreaView.setBackgroundColor((fillObjectView.isChecked() == true) ? color : backgroundColor);
+               //backgroundShape.setStroke(2, color);
+
+               if (fillObjectView.isChecked() == true)
+               {
+                       // 塗りつぶし時は文字の色を変える。
+            color = (color ^ 0x00ffffff);
+               }
+               colorBorderAreaView.setTextColor(color);
+               colorBorderAreaView.setText(context.getString(R.string.labelTextColorSample));
+               
+        builder.setView(layout);
+        builder.setCancelable(false);
+        builder.setPositiveButton(context.getString(R.string.confirmYes), new DialogInterface.OnClickListener()
+              {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          boolean isUserCheck = false;
+                          if (userCheckbox != null)
+                          {
+                                  isUserCheck = userCheckbox.isChecked();
+                          }
+                          setObjectData(label.getText().toString(), detail.getText().toString(), borderColorView.getProgress(), boldText.isChecked(), fillObjectView.isChecked(), isUserCheck, currentObjectDrawStyle);
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.finishObjectInput();
+                          }
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+               });
+        builder.setNegativeButton(context.getString(R.string.confirmNo), new DialogInterface.OnClickListener()
+               {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.cancelObjectInput();
+                          }
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+               });
+        return (builder.create());     
+    }
+
+    /**
+     *    オブジェクト入力用ダイアログの表示を準備する
+     * 
+     */
+    public void prepareObjectInputDialog(Dialog dialog, Integer objectKey)
+    {
+        MeMoMaObjectHolder.PositionObject position = objectHolder.getPosition(objectKey);
+       key = objectKey;
+        if (position != null)
+        {
+               // 色を設定する
+            final SeekBar borderColorProgess = (SeekBar) dialog.findViewById(R.id.borderColorSelectionBar);
+            borderColorProgess.setProgress(convertProgress(position.objectColor));
+
+            final CheckBox  boldTextCheck = (CheckBox) dialog.findViewById(R.id.checkBoldText);
+            boldTextCheck.setChecked(position.strokeWidth == MeMoMaObjectHolder.STOROKE_BOLD_WIDTH);
+
+            final CheckBox  fillObjectCheck = (CheckBox) dialog.findViewById(R.id.checkFillObject);
+            fillObjectCheck.setChecked(Paint.Style.valueOf(position.paintStyle) != Paint.Style.STROKE);
+
+            // フォントサイズを設定する
+            textFontSize = position.fontSize / 2.0f;
+            
+               // 入力文字列を設定する
+            final EditText targetLabel = (EditText) dialog.findViewById(R.id.labelInputArea);
+            targetLabel.setText(position.label);
+
+            final EditText targetDetail = (EditText) dialog.findViewById(R.id.descriptionInputArea);
+            targetDetail.setText(position.detail);
+            
+               //  設定に記録されているデータを画面に反映させる
+               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+            String userCheckboxTitle = preferences.getString("userCheckboxString", "");
+
+            // 描画スタイルを設定する
+            currentObjectDrawStyle = position.drawStyle;
+               updateObjectDrawStyleImageButton(currentObjectDrawStyle);
+            
+            // 背景色を設定する
+            try
+            {
+                String colorString = preferences.getString("backgroundColor", "0xff004000");
+                backgroundColor = Color.parseColor(colorString);
+            }
+            catch (Exception e)
+            {
+                backgroundColor = MeMoMaCanvasDrawer.BACKGROUND_COLOR_DEFAULT;
+            }
+            setTextColorSample(borderColorProgess.getProgress(), textFontSize, fillObjectView.isChecked());
+
+            final CheckBox  userCheckbox = (CheckBox) dialog.findViewById(R.id.checkUserCheckbox);
+            userCheckbox.setEnabled(true);
+            userCheckbox.setText(userCheckboxTitle);
+            userCheckbox.setChecked(position.userChecked);
+        }
+    }
+    
+    /**
+     *    オブジェクトにデータを設定する
+     * @param label
+     * @param detail
+     * @param labelColor
+     * @param borderColor
+     * @param size
+     */
+    public void setObjectData(String label, String detail, int progress, boolean boldText, boolean fillObject, boolean userCheck, int drawStyle)
+    {
+       MeMoMaObjectHolder.PositionObject positionObject = objectHolder.getPosition(key);
+       if (positionObject != null)
+       {
+            positionObject.label = label;
+            positionObject.detail = detail;
+               int color = convertColor(progress);
+            positionObject.objectColor = color;
+               color = (color ^ 0x00ffffff);
+               positionObject.fontSize = textFontSize * 2.0f;
+            positionObject.labelColor = color;
+               positionObject.strokeWidth = (boldText == true) ? MeMoMaObjectHolder.STOROKE_BOLD_WIDTH : MeMoMaObjectHolder.STOROKE_NORMAL_WIDTH;
+               positionObject.paintStyle = ((fillObject == true) ? Paint.Style.FILL : Paint.Style.STROKE).toString();
+               positionObject.userChecked = userCheck;
+               
+               if (positionObject.drawStyle != drawStyle)
+               {
+                   if ((drawStyle == MeMoMaObjectHolder.DRAWSTYLE_CIRCLE)||
+                       (drawStyle == MeMoMaObjectHolder.       DRAWSTYLE_LEFT_ARROW)||
+                       (drawStyle == MeMoMaObjectHolder.       DRAWSTYLE_DOWN_ARROW)||
+                       (drawStyle == MeMoMaObjectHolder.       DRAWSTYLE_UP_ARROW)||
+                       (drawStyle == MeMoMaObjectHolder.       DRAWSTYLE_RIGHT_ARROW))
+                   {
+                       // (長方形の形状から)正方形の形状にする場合...
+                       setRectToSquare(positionObject);                        
+                   }
+                   else if ((positionObject.drawStyle == MeMoMaObjectHolder.DRAWSTYLE_CIRCLE)||
+                            (positionObject.drawStyle == MeMoMaObjectHolder.   DRAWSTYLE_LEFT_ARROW)||
+                            (positionObject.drawStyle == MeMoMaObjectHolder.   DRAWSTYLE_DOWN_ARROW)||
+                            (positionObject.drawStyle == MeMoMaObjectHolder.   DRAWSTYLE_UP_ARROW)||
+                            (positionObject.drawStyle == MeMoMaObjectHolder.   DRAWSTYLE_RIGHT_ARROW))
+                   {
+                       // 正方形の形状から、長方形の形状にする場合...
+                       setRectFromSquare(positionObject);
+                   }   
+                   positionObject.drawStyle = drawStyle;
+               }
+       }
+       positionObject = null;
+    }
+
+    /**
+     *   オブジェクトの領域を長方形から正方形にする
+     */
+    private void setRectToSquare(MeMoMaObjectHolder.PositionObject positionObject)
+    {
+           float bandWidth = ((positionObject.rect.right -  positionObject.rect.left)) / 2.0f;
+           float center = positionObject.rect.centerY();
+           
+           positionObject.rect.top = center - bandWidth;
+           positionObject.rect.bottom = center + bandWidth;
+    }
+
+    /**
+     *   オブジェクトの領域を正方形から長方形にする
+     */
+    private void setRectFromSquare(MeMoMaObjectHolder.PositionObject positionObject)
+    {
+        float bandWidth = ((positionObject.rect.right -  positionObject.rect.left) / 16.0f * 9.0f) / 2.0f;
+        float center = positionObject.rect.centerY();
+        
+        positionObject.rect.top = center - bandWidth;
+        positionObject.rect.bottom = center + bandWidth;
+    }
+
+    private void setButtonBorder(int id, boolean isHighlight)
+    {
+       try
+       {
+            ImageButton button = (ImageButton) dialogLayout.findViewById(id);
+            //GradientDrawable btnBackgroundShape = (GradientDrawable)button.getBackground();
+            BitmapDrawable btnBackgroundShape = (BitmapDrawable)button.getBackground();
+            if (isHighlight == true)
+            {
+//                     btnBackgroundShape.setColorFilter(Color.rgb(51, 181, 229), Mode.LIGHTEN);
+               btnBackgroundShape.setColorFilter(Color.BLUE, Mode.LIGHTEN);
+            }
+            else
+            {
+               btnBackgroundShape.setColorFilter(Color.BLACK, Mode.LIGHTEN);
+            } 
+       }
+       catch (Exception ex)
+       {
+               // 
+               Log.v(Main.APP_IDENTIFIER, "setButtonBorder(): " + ex.toString());
+       }
+       
+    }
+    
+    /**
+     *    イメージボタンの選択状態を更新する
+     * 
+     * @param drawStyle
+     */
+    private void updateObjectDrawStyleImageButton(int drawStyle)
+    {
+       setButtonBorder(R.id.btnObjectRectangle, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE));
+       setButtonBorder(R.id.btnObjectRoundRect, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_ROUNDRECT));
+       setButtonBorder(R.id.btnObjectOval, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_OVAL));
+       setButtonBorder(R.id.btnObjectDiamond, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DIAMOND));
+       setButtonBorder(R.id.btnObjectHexagonal, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_HEXAGONAL));
+       setButtonBorder(R.id.btnObjectParallelogram, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_PARALLELOGRAM));
+       setButtonBorder(R.id.btnObjectKeyboard, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_KEYBOARD));
+       setButtonBorder(R.id.btnObjectPaper, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_PAPER));
+       setButtonBorder(R.id.btnObjectDrum, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DRUM));
+       setButtonBorder(R.id.btnObjectCircle, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_CIRCLE));
+       setButtonBorder(R.id.btnObjectNoRegion, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_NO_REGION));
+       setButtonBorder(R.id.btnObjectLoopStart, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LOOP_START));
+       setButtonBorder(R.id.btnObjectLoopEnd, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LOOP_END));
+       setButtonBorder(R.id.btnObjectLeftArrow, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_LEFT_ARROW));
+       setButtonBorder(R.id.btnObjectDownArrow, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_DOWN_ARROW));
+       setButtonBorder(R.id.btnObjectUpArrow, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_UP_ARROW));
+       setButtonBorder(R.id.btnObjectRightArrow, (drawStyle == MeMoMaObjectHolder.DRAWSTYLE_RIGHT_ARROW));
+     }
+    
+    /**
+     *    ボタンが押された時の処理...
+     * 
+     */
+    public void onClick(View v)
+    {
+       int id = v.getId();
+       if (id == R.id.borderColorArea)
+       {
+               // フォントサイズを変更する...
+               if (textFontSize == FONTSIZE_MIDDLE)
+               {
+                       textFontSize = FONTSIZE_LARGE;
+               }
+               else if (textFontSize == FONTSIZE_LARGE)
+               {
+                       textFontSize = FONTSIZE_SMALL;
+               }
+               else // if (textFontSize == FONTSIZE_SMALL)
+               {
+                       textFontSize = FONTSIZE_MIDDLE;
+               }
+            setTextColorSample(borderColorView.getProgress(), textFontSize, fillObjectView.isChecked());
+               return;
+       }
+       
+       switch (id)
+       {
+         case R.id.btnObjectRoundRect:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_ROUNDRECT;
+                 break;
+         case R.id.btnObjectOval:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_OVAL;
+                 break;
+         case R.id.btnObjectDiamond:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_DIAMOND;
+                 break;
+         case R.id.btnObjectHexagonal:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_HEXAGONAL;
+                 break;
+         case R.id.btnObjectParallelogram:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_PARALLELOGRAM;
+                 break;
+         case R.id.btnObjectKeyboard:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_KEYBOARD;
+                 break;
+         case R.id.btnObjectPaper:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_PAPER;
+                 break;
+         case R.id.btnObjectDrum:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_DRUM;
+                 break;
+         case R.id.btnObjectNoRegion:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_NO_REGION;
+                 break;
+         case R.id.btnObjectCircle:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_CIRCLE;
+                 break;
+         case R.id.btnObjectLoopStart:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_LOOP_START;
+                 break;
+         case R.id.btnObjectLoopEnd:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_LOOP_END;
+                 break;
+         case R.id.btnObjectLeftArrow:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_LEFT_ARROW;
+                 break;
+         case R.id.btnObjectDownArrow:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_DOWN_ARROW;
+                 break;
+         case R.id.btnObjectUpArrow:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_UP_ARROW;
+                 break;
+         case R.id.btnObjectRightArrow:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_RIGHT_ARROW;
+                 break;
+         case R.id.btnObjectRectangle: 
+          default:
+                 currentObjectDrawStyle = MeMoMaObjectHolder.DRAWSTYLE_RECTANGLE;
+                 break;
+       }
+       updateObjectDrawStyleImageButton(currentObjectDrawStyle);
+    }
+
+    /**
+     *   0x00~0x3fの値(R, G, B, それぞれ2ビット)で色を変える
+     * 
+     * @param value
+     * @return
+     */
+    private int convertColor(int value)
+    {
+       int color = 0;  
+       int r = ((value >> 4 ) & 0x03) * 85;
+       int g = ((value >> 2) & 0x03) * 85;
+       int b = (value & 0x03)  * 85;
+        color = Color.rgb(r, g, b);
+        //Log.v(Main.APP_IDENTIFIER, "convertColor()  R : " + r + ", G : " + g + ", B : " + b + "color : " + color);
+        return (color);
+    }
+
+    /**
+     *    色をプログレスバーの値に変換する
+     *    
+     * @param color
+     * @return
+     */
+    private int convertProgress(int color)
+    {
+       int r = Color.red(color) / 85;
+       int g = Color.green(color) / 85;
+       int b = Color.blue(color) / 85;
+       
+       return ((r << 4) + (g << 2) + b);       
+    }
+    
+    /**
+     *   背景色を設定する処理
+     *   
+     * @param progress
+     * @param fontSize
+     * @param value
+     */
+    private void setTextColorSample(int progress, float fontSize, boolean value)
+    {
+       if (colorBorderAreaView != null)
+       {
+               int color = convertColor(progress);
+               int backColor = (value == true) ? color : backgroundColor;
+               colorBorderAreaView.setBackgroundColor(backColor);
+               
+               backgroundShape.setStroke(2, color);
+               
+               if (value == true)
+               {
+                       // 塗りつぶし時には色を変える
+                   color = (color ^ 0x00ffffff);
+               }
+               colorBorderAreaView.setTextSize(TypedValue.COMPLEX_UNIT_PT, fontSize);
+               colorBorderAreaView.setTextColor(color);
+               colorBorderAreaView.setText(context.getString(R.string.labelTextColorSample));
+       }
+    }
+    
+    /**
+     *   チェックボックスの値が変更された時の処理
+     * 
+     */
+    public void onCheckedChanged(CompoundButton view, boolean value)
+    {
+       int id = view.getId();
+       if ((id == R.id.checkFillObject)&&(borderColorView != null))
+       {
+               setTextColorSample(borderColorView.getProgress(), textFontSize, value);
+       }       
+    }
+    /**
+     *    プログレスバーで値を変更された時の処理
+     * 
+     */
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
+    {
+       int id = seekBar.getId();
+        //Log.v(Main.APP_IDENTIFIER, "onProgressChanged() : " + progress + " id : " + id);
+        
+       if ((id == R.id.borderColorSelectionBar)&&(fillObjectView != null))
+       {
+               setTextColorSample(progress, textFontSize, fillObjectView.isChecked());
+       }
+    }
+    
+    public void onStartTrackingTouch(SeekBar seekBar)
+    {
+        //     
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar)
+    {
+        //
+    }    
+    
+    public interface IResultReceiver
+    {
+        public abstract void finishObjectInput();
+        public abstract void cancelObjectInput();
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectLayoutCaptureExporter.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectLayoutCaptureExporter.java
new file mode 100644 (file)
index 0000000..d251b99
--- /dev/null
@@ -0,0 +1,269 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Enumeration;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.os.AsyncTask;
+import android.util.Log;
+import android.view.Display;
+
+/**
+ *  データをファイルに保存するとき用 アクセスラッパ (非同期処理を実行)
+ *  Viewの情報を画像形式(png形式)で保存する。
+ *  どのViewを保存するのかは、ICaptureExporter.getCaptureTargetView()クラスを使って教えてもらう。
+ *  
+ *  AsyncTask
+ *    String       : 実行時に渡すクラス(Param)           : ファイル名をもらう
+ *    Integer    : 途中経過を伝えるクラス(Progress)   : 今回は使っていない
+ *    String      : 処理結果を伝えるクラス(Result)      : 結果を応答する。
+ *    
+ * @author MRSa
+ *
+ */
+public class ObjectLayoutCaptureExporter extends AsyncTask<String, Integer, String>
+{
+       private static final int OUTPUT_MARGIN = 8;
+       private static final int OUTPUT_MARGIN_TOP = 50;
+       
+       private static final int MINIMUM_WIDTH = 800;
+       private static final int MINIMUM_HEIGHT = 600;
+       
+       private Activity parent = null;
+       private ICaptureLayoutExporter receiver = null;
+       private ExternalStorageFileUtility fileUtility = null;  
+       private String exportedFileName = null; 
+       private MeMoMaObjectHolder objectHolder = null;
+       private MeMoMaCanvasDrawer canvasDrawer = null;
+       private ProgressDialog savingDialog = null;
+       private float offsetX = 0.0f;
+       private float offsetY = 0.0f;
+
+       /**
+        *   コンストラクタ
+        */
+    public ObjectLayoutCaptureExporter(Activity context, ExternalStorageFileUtility utility,  MeMoMaObjectHolder holder, MeMoMaCanvasDrawer drawer, ICaptureLayoutExporter resultReceiver)
+    {
+       receiver = resultReceiver;
+       fileUtility = utility;
+       objectHolder = holder;
+       canvasDrawer = drawer;
+       parent = context;
+
+        //  プログレスダイアログ(「保存中...」)を表示する。
+       savingDialog = new ProgressDialog(context);
+       savingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+       savingDialog.setMessage(context.getString(R.string.dataSaving));
+       savingDialog.setIndeterminate(true);
+       savingDialog.setCancelable(false);
+       savingDialog.show();
+
+       /** ファイルをバックアップするディレクトリを作成する **/
+       File dir = new File(fileUtility.getGokigenDirectory() + "/exported");
+       dir.mkdir();
+    }
+       
+    /**
+     *  非同期処理実施前の前処理
+     * 
+     */
+    @Override
+    protected void onPreExecute()
+    {
+        // なにもしない。
+    }
+    
+    /**
+     *    ビットマップデータを(PNG形式で)保管する。
+     * 
+     * @param fileName
+     * @param objectHolder
+     * @return
+     */
+    private String exportToFile(String fileName, Bitmap targetBitmap)
+    {
+       String resultMessage = "";
+        try
+        {
+               if (targetBitmap == null)
+               {
+                       // ビットマップが取れないため、ここで折り返す。
+                       return ("SCREEN DATA GET FAILURE...");
+               }
+               
+               // エクスポートするファイル名を決定する
+            Calendar calendar = Calendar.getInstance();
+            SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+            exportedFileName = fileName + "_" + outFormat.format(calendar.getTime()) + ".png";
+
+            // PNG形式でファイル出力を行う。
+            OutputStream out = new FileOutputStream(exportedFileName);
+            targetBitmap.compress(CompressFormat.PNG, 100, out);
+            out.flush();
+            out.close();            
+        }
+        catch (Exception e)
+        {
+               resultMessage = " ERR(png)>" + e.toString();
+            Log.v(Main.APP_IDENTIFIER, resultMessage);
+            e.printStackTrace();
+        } 
+        return (resultMessage);
+    }
+    
+    /**
+     *    キャンバスの大きさがどれくらい必要か、チェックする。
+     * 
+     * @return
+     */
+    private Rect checkCanvasSize()
+    {
+        Rect canvasSize = new Rect();
+
+        // オブジェクトの配置位置を探る。
+       Enumeration<Integer> keys = objectHolder.getObjectKeys();
+        while (keys.hasMoreElements())
+        {
+            Integer key = keys.nextElement();
+            MeMoMaObjectHolder.PositionObject pos = objectHolder.getPosition(key);
+            if (canvasSize.left > pos.rect.left)
+            {
+               canvasSize.left = (int) pos.rect.left;
+            }
+            if (canvasSize.right < pos.rect.right)
+            {
+               canvasSize.right = (int) pos.rect.right;
+            }
+            if (canvasSize.top > pos.rect.top)
+            {
+               canvasSize.top = (int) pos.rect.top;
+            }
+            if (canvasSize.bottom < pos.rect.bottom)
+            {
+               canvasSize.bottom = (int) pos.rect.bottom;
+            }
+        }
+        
+        // 描画領域にちょっと余裕を持たせる
+        canvasSize.left = canvasSize.left - OUTPUT_MARGIN;
+        canvasSize.right = canvasSize.right + OUTPUT_MARGIN;
+        canvasSize.top = canvasSize.top - OUTPUT_MARGIN_TOP;
+        canvasSize.bottom = canvasSize.bottom + OUTPUT_MARGIN;
+        canvasSize.sort();
+
+        // 現在の画面サイズを取得
+        Display display = parent.getWindowManager().getDefaultDisplay();
+        int width = display.getWidth();
+        int height = display.getHeight();
+        if (width < MINIMUM_WIDTH)
+        {
+               width = MINIMUM_WIDTH;
+        }
+        if (height < MINIMUM_HEIGHT)
+        {
+               height = MINIMUM_HEIGHT;
+        }        
+
+        // 出力の最小サイズを(表示画面サイズに)設定
+        if (canvasSize.width() < width)
+        {
+               canvasSize.right = canvasSize.left + width;
+        }
+        if (canvasSize.height() < height)
+        {
+               canvasSize.bottom = canvasSize.top + height;
+        }
+        
+        
+        // 画像位置(キャンバス位置)の調整。。。
+        offsetX = 0.0f - canvasSize.left - (OUTPUT_MARGIN);
+        offsetY = 0.0f - canvasSize.top - (OUTPUT_MARGIN);
+
+        // 出力する画像データのサイズを表示する
+        Log.v(Main.APP_IDENTIFIER, "ObjectLayoutCaptureExporter::checkCanvasSize() w:" + canvasSize.width() + " , h:" + canvasSize.height() + "  offset :(" + offsetX + "," + offsetY + ")");
+        return (canvasSize);
+    }    
+
+    /**
+     *  非同期処理
+     *  (バックグラウンドで実行する(このメソッドは、UIスレッドと別のところで実行する))
+     * 
+     */
+    @Override
+    protected String doInBackground(String... datas)
+    {
+       Rect canvasSize = checkCanvasSize();
+       Bitmap targetBitmap = Bitmap.createBitmap(canvasSize.width(), canvasSize.height(), Bitmap.Config.RGB_565);
+       Canvas targetCanvas = new Canvas(targetBitmap);
+       
+       // オブジェクトをビットマップの中に書き込む
+       canvasDrawer.drawOnBitmapCanvas(targetCanvas, offsetX, offsetY);
+
+       // ファイル名の設定 ... (拡張子なし)
+       String fileName = fileUtility.getGokigenDirectory() + "/exported/" + datas[0];
+
+       // データを保管する
+        String result = exportToFile(fileName, targetBitmap);
+
+        System.gc();
+
+        return (result);
+    }
+
+    /**
+     *  非同期処理の進捗状況の更新
+     * 
+     */
+       @Override
+       protected void onProgressUpdate(Integer... values)
+       {
+        // 今回は何もしない
+       }
+
+    /**
+     *  非同期処理の後処理
+     *  (結果を応答する)
+     */
+    @Override
+    protected void onPostExecute(String result)
+    {
+       try
+       {
+            if (receiver != null)
+            {
+               receiver.onCaptureLayoutExportedResult(exportedFileName, result);
+            }
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "ViewCaptureExporter::onPostExecute() : " + ex.toString());
+       }
+       // プログレスダイアログを消す
+       if (savingDialog != null)
+       {
+            savingDialog.dismiss();
+       }
+       return;
+    }     
+    /**
+     *    結果報告用のインタフェース
+     *    
+     * @author MRSa
+     *
+     */
+    public interface ICaptureLayoutExporter
+    {
+        /**  保存結果の報告 **/
+        public abstract void onCaptureLayoutExportedResult(String exportedFileName, String detail);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectOperationCommandHolder.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectOperationCommandHolder.java
new file mode 100644 (file)
index 0000000..fe44e92
--- /dev/null
@@ -0,0 +1,105 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.content.Context;
+
+/**
+ * 
+ * 
+ * @author MRSa
+ *
+ */
+public class ObjectOperationCommandHolder implements ItemSelectionDialog.ISelectionItemHolder
+{
+    public static final int OBJECTOPERATION_DELETE = 0;
+    public static final int OBJECTOPERATION_DUPLICATE =1;
+    public static final int OBJECTOPERATION_SIZEBIGGER = 2;
+    public static final int OBJECTOPERATION_SIZESMALLER = 3;
+//    public static final int OBJECTOPERATION_BRINGTOP = 4;
+       
+       private Context parent = null;
+       
+       /**
+        *    コンストラクタ
+        * 
+        */
+    public ObjectOperationCommandHolder(Context context)
+    {
+       parent = context;
+    }  
+
+    /**
+     * 
+     * 
+     */
+    public boolean isMultipleSelection()
+       {
+               return (false);
+               
+       }
+
+    /**
+     * 
+     * 
+     */
+       public String[] getItems()
+       {
+        String[] ret = new String[4];
+        ret[0] = parent.getString(R.string.object_delete);
+        ret[1] = parent.getString(R.string.object_duplicate);
+        ret[2] = parent.getString(R.string.object_bigger);
+        ret[3] = parent.getString(R.string.object_smaller);
+        //ret[4] = parent.getString(R.string.object_bringtop);
+
+        return (ret);
+       }
+       
+       /**
+        * 
+        * 
+        */
+    public String  getItem(int index)
+    {
+       String message = "";
+       switch (index)
+       {
+          case OBJECTOPERATION_DELETE:
+               message = parent.getString(R.string.object_delete);
+               break;
+          case OBJECTOPERATION_DUPLICATE:
+               message = parent.getString(R.string.object_duplicate);
+               break;
+          case OBJECTOPERATION_SIZEBIGGER:
+               message = parent.getString(R.string.object_bigger);
+               break;
+          case OBJECTOPERATION_SIZESMALLER:
+               message = parent.getString(R.string.object_smaller);
+               break;
+/*
+          case OBJECTOPERATION_BRINGTOP:
+               message = parent.getString(R.string.object_bringtop);
+               break;
+*/
+          default:
+               break;
+       }
+       return (message);
+    }
+
+    /** 複数選択時に使用する **/
+    
+    /**
+     * 
+     */
+    public boolean[] getSelectionStatus()
+    {
+       return (null);
+    }
+    
+    /**
+     * 
+     */
+    public void setSelectionStatus(int index, boolean isSelected)
+    {
+         // なにもしない
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectShapeDrawer.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ObjectShapeDrawer.java
new file mode 100644 (file)
index 0000000..30842e0
--- /dev/null
@@ -0,0 +1,384 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+/**
+ *   めもまのオブジェクト・ライン・ラベルを描画するメソッド群
+ *   (現在のところ、MeMoMaCanvasDrawerクラスから追い出してきただけ...)
+ * 
+ * @author MRSa
+ *
+ */
+public class ObjectShapeDrawer
+{
+
+
+    static public float drawObjectOval(Canvas canvas, RectF objectShape, Paint paint)
+    {
+        // 楕円形の描画
+        canvas.drawOval(objectShape, paint);
+
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2);
+    }
+
+    static public float drawObjectRect(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 四角形を描画する
+        canvas.drawRect(objectShape, paint);
+        return (0.0f);
+    }
+
+    static public float drawObjectRoundRect(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 丸角四角形の描画
+        canvas.drawRoundRect(objectShape, MeMoMaObjectHolder.ROUNDRECT_CORNER_RX, MeMoMaObjectHolder.ROUNDRECT_CORNER_RY, paint);
+
+        return (0.0f);
+    }
+
+    static public float drawObjectDiamond(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 菱形の描画
+        Path path = new Path();
+        path.moveTo(objectShape.centerX(), objectShape.top);
+        path.lineTo(objectShape.left, objectShape.centerY());
+        path.lineTo(objectShape.centerX(), objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.centerY());
+        path.lineTo(objectShape.centerX(), objectShape.top);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2);
+    }
+
+    static public float drawObjectKeyboard(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 台形(キーボード型)の描画
+        Path path = new Path();
+        path.moveTo(objectShape.left, objectShape.centerY() - MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN);
+        path.lineTo(objectShape.left, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.centerY() - MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN);
+    }
+
+    static public float drawObjectParallelogram(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 平行四辺形の描画
+        Path path = new Path();
+        path.moveTo(objectShape.left + MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.bottom);
+        path.lineTo(objectShape.right - MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.top);
+        path.lineTo(objectShape.left + MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN, objectShape.top);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public float drawObjectHexagonal(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 六角形の描画
+        Path path = new Path();
+        float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 2;
+        path.moveTo(objectShape.left + margin, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.centerY());
+        path.lineTo(objectShape.left + margin, objectShape.bottom);
+        path.lineTo(objectShape.right - margin, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.centerY());
+        path.lineTo(objectShape.right - margin, objectShape.top);
+        path.lineTo(objectShape.left + margin, objectShape.top);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public float drawObjectPaper(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 書類の形の描画
+        float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 3.0f;
+        Path path = new Path();
+        path.moveTo(objectShape.left, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.bottom - margin);
+        path.cubicTo((objectShape.left + objectShape.centerX()) / 2.0f , objectShape.bottom, (objectShape.right + objectShape.centerX()) / 2.0f, objectShape.bottom - margin, objectShape.right, objectShape.bottom - margin);
+        path.lineTo(objectShape.right, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.top);
+        canvas.drawPath(path, paint);
+        return ( - MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN);
+    }
+
+    static public float drawObjectDrum(Canvas canvas, RectF objectShape, Paint paint, Paint.Style paintStyle)
+    {
+               float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 1.0f;
+               // 円柱の描画
+        Path path = new Path();
+        path.moveTo(objectShape.left, objectShape.top);
+        path.arcTo(new RectF(objectShape.left, objectShape.top,objectShape.right, objectShape.top + margin), 180.0f, 359.999f, true);
+        path.lineTo(objectShape.left, objectShape.bottom - (margin / 2.0f));
+        path.arcTo(new RectF(objectShape.left, objectShape.bottom - margin, objectShape.right, objectShape.bottom), 180.0f, -180.0f, true);
+        path.lineTo(objectShape.right, objectShape.top + (margin / 2.0f));
+        if (paintStyle != Paint.Style.STROKE)
+        {
+               // 塗りつぶし用に線の領域を追加する
+            path.arcTo(new RectF(objectShape.left, objectShape.top, objectShape.right, objectShape.top + margin), 180.0f, 180.0f, true);
+            path.lineTo(objectShape.left, objectShape.bottom - (margin / 2.0f));
+            path.arcTo(new RectF(objectShape.left, objectShape.bottom - margin, objectShape.right, objectShape.bottom), 180.0f, -180.0f, true);
+        }
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public float drawObjectCircle(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 円を描画する
+        canvas.drawCircle(objectShape.centerX(), objectShape.centerY(), ((objectShape.right - objectShape.left)/ 2.0f), paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public float drawObjectNoRegion(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 何も表示しないとわからないので、ラベルが無いときには枠を表示する
+        paint.setColor(Color.DKGRAY);
+        canvas.drawRect(objectShape, paint);
+        paint.setColor(Color.WHITE);
+        return (0.0f);
+    }
+
+    static public float drawObjectLoopStart(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // ループ開始図形の描画
+        Path path = new Path();
+        float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 2;
+        path.moveTo(objectShape.left + margin, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.centerY());
+        path.lineTo(objectShape.left, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.centerY());
+        path.lineTo(objectShape.right - margin, objectShape.top);
+        path.lineTo(objectShape.left + margin, objectShape.top);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public float drawObjectLoopEnd(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // ループ終了図形の描画
+        Path path = new Path();
+        float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 2;
+        path.moveTo(objectShape.left, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.centerY());
+        path.lineTo(objectShape.left + margin, objectShape.bottom);
+        path.lineTo(objectShape.right - margin, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.centerY());
+        path.lineTo(objectShape.right, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.top);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public float drawObjectLeftArrow(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 左側矢印図形の描画
+        Path path = new Path();
+        float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 4.0f;
+        path.moveTo(objectShape.left + margin, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.centerY());
+        path.lineTo(objectShape.left + margin, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.top);
+        path.lineTo(objectShape.left + margin, objectShape.top);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public float drawObjectDownArrow(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 下側矢印図形の描画
+        Path path = new Path();
+        float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 2;
+        path.moveTo(objectShape.left, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.centerY() + margin);
+        path.lineTo(objectShape.centerX(), objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.centerY() + margin);
+        path.lineTo(objectShape.right, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.top);
+        canvas.drawPath(path, paint);
+        return (- MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN);
+    }
+
+    static public float drawObjectUpArrow(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 上側矢印図形の描画
+        Path path = new Path();
+        float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 2.0f;
+        path.moveTo(objectShape.centerX(), objectShape.top);
+        path.lineTo(objectShape.left, objectShape.centerY() - margin);
+        path.lineTo(objectShape.left, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.centerY() - margin);
+        path.lineTo(objectShape.centerX(), objectShape.top);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public float drawObjectRightArrow(Canvas canvas, RectF objectShape, Paint paint)
+    {
+               // 右側矢印図形の描画
+        Path path = new Path();
+        float margin = MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 4.0f;
+        path.moveTo(objectShape.left, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.bottom);
+        path.lineTo(objectShape.right - margin, objectShape.bottom);
+        path.lineTo(objectShape.right, objectShape.centerY());
+        path.lineTo(objectShape.right - margin, objectShape.top);
+        path.lineTo(objectShape.left, objectShape.top);
+        canvas.drawPath(path, paint);
+        return (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN / 2.0f);
+    }
+
+    static public void drawLineStraight(Canvas canvas)
+    {
+       
+    }
+         /**
+          *    矢印を描画する処理 (ツリー表示時)
+          * 
+          * @param canvas
+          * @param paint
+          * @param x1
+          * @param y1
+          * @param checkVaule
+          * @param isXaxis
+          */
+       static public void drawArrowTree(Canvas canvas, Paint paint, float x1, float y1, float checkValue, boolean isXaxis)
+    {
+               float margin = 8.0f;
+               float direction = 1.0f;
+               if (isXaxis == true)
+        {
+                   direction = (checkValue < x1) ? -1.0f : 1.0f;
+            canvas.drawLine(x1, y1, (x1 + direction * margin), (y1 - margin), paint);
+               canvas.drawLine(x1, y1, (x1 + direction * margin), (y1 + margin), paint);
+               }
+               else
+               {
+                   direction = (checkValue < y1) ? -1.0f : 1.0f;
+               canvas.drawLine(x1, y1, (x1 - margin), (y1 + direction * margin), paint);
+               canvas.drawLine(x1, y1, (x1 + margin), (y1 + direction * margin), paint);                 
+               }
+    }
+         /**
+          *    矢印を描画する処理
+          * 
+          * @param canvas
+          * @param paint
+          * @param x1
+          * @param y1
+          * @param x2
+          * @param y2
+          */
+         static public void drawArrow(Canvas canvas, Paint paint, float x1, float y1, float x2, float y2)
+         {
+          // 矢印線の長さ
+                 float moveX = 14.0f;
+                 
+                 // 接続線の傾きが、どれくらいの角度で入っているか?
+                 float centerDegree = (float) (Math.atan2((y2 - y1) , (x2 - x1))  * 180.0d / Math.PI);
+
+                 // x1, y1 に x2, y2 方向から来た線に合わせた矢印を描画する
+                 // (2本、1本づつ引いて、それを回転行列で回転させている)
+
+                 // 回転行列の準備
+                 Matrix matrix1 = new Matrix();
+                 matrix1.setRotate((centerDegree + 30), x1, y1);
+             Matrix matrix2 = new Matrix();
+                 matrix2.setRotate((centerDegree - 30), x1, y1);
+
+                 // 線分を引いた後、回転行列で回転させる
+                 Path pathLine1 = new Path();
+             pathLine1.moveTo(x1, y1);
+             pathLine1.lineTo(x1 + moveX, y1);
+             pathLine1.transform(matrix1);
+             canvas.drawPath(pathLine1, paint);
+
+                 Path pathLine2 = new Path();
+             pathLine2.moveTo(x1, y1);
+             pathLine2.lineTo(x1 + moveX, y1);
+             pathLine2.transform(matrix2);
+             canvas.drawPath(pathLine2, paint);
+    }
+
+         /**
+            *    オブジェクトのラベルを表示する
+            * 
+            * @param canvas
+            * @param paint
+            * @param pos
+            */
+           public static void drawTextLabel(Canvas canvas, Paint paint, MeMoMaObjectHolder.PositionObject pos, RectF region, int displayObjectInformation, float offsetX, float offsetY)
+           {
+               // タイトルの先頭部分を表示する場合...
+               String labelToShow = pos.label;
+               if (displayObjectInformation == 0)
+               {
+               float width = region.width() - MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN_WIDTH;
+                int textLen = paint.breakText(pos.label, true, width, null);  // 省略文字を追加するから、そのぶん減らす
+               labelToShow = labelToShow.substring(0, textLen);
+               if (labelToShow != pos.label)
+               {
+                       // truncate した場合には、省略文字を出す。
+                       labelToShow = labelToShow + "...";
+               }
+               }
+
+               if (Paint.Style.valueOf(pos.paintStyle) != Paint.Style.STROKE)
+               {
+                   // オブジェクトを塗りつぶすのときは、文字の色を設定する
+                   paint.setColor(pos.labelColor);
+               }
+               
+               // 文字をちょっと影付きにする
+               paint.setShadowLayer(0.5f, 0.5f, 0.5f, Color.DKGRAY);
+               
+               // ユーザチェックの描画
+               if (pos.userChecked == true)
+               {
+                       canvas.drawText("*", region.centerX(), region.top + (MeMoMaCanvasDrawer.OBJECTLABEL_MARGIN * 2.0f), paint);
+              }
+               
+               // 強調表示
+               if (pos.strokeWidth != 0.0f)
+               {
+                       // そのまま表示すると、読めないので、太さを調整し、アンダーラインを引くことにする
+                       paint.setStrokeWidth(0.0f);
+                   paint.setSubpixelText(true);
+                   paint.setUnderlineText (true);
+               }
+
+               if (displayObjectInformation == 0)
+               {            
+                       // 1行分しか表示しない場合...そのまま表示して終了する
+                   canvas.drawText(labelToShow, (region.left + offsetX),   (region.centerY() + offsetY), paint);
+                   return;
+               }
+               
+               float tall = paint.getFontMetrics().top + 1.0f;
+               float posX = (region.left + offsetX);
+               float posY =  (region.centerY() + offsetY);
+               float width = region.right - region.left - 12.0f;  // 幅
+
+               int startChar  = 0;
+               int endChar = pos.label.length();
+               do
+               {
+                   int textLen = paint.breakText(pos.label, startChar, endChar, true, width, null);
+                   canvas.drawText(labelToShow, startChar, (startChar +textLen), posX, posY, paint);
+
+                   posY = posY - tall;
+                   startChar = startChar + textLen;
+               } while (startChar < endChar);  
+           }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/OperationModeHolder.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/OperationModeHolder.java
new file mode 100644 (file)
index 0000000..214975b
--- /dev/null
@@ -0,0 +1,64 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+/**
+ * 
+ * @author MRSa
+ *
+ */
+public class OperationModeHolder 
+{
+       private Activity activity = null;
+
+    public static final int OPERATIONMODE_CREATE = 0;
+    public static final int OPERATIONMODE_DELETE = 1;
+    public static final int OPERATIONMODE_MOVE = 2;
+
+       public OperationModeHolder(Activity arg)
+       {
+               activity = arg;
+       }
+
+       public void changeOperationMode(int value)
+       {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putString("operationMode", "" + value);
+        editor.commit();
+       }
+
+    public int updateOperationMode(int buttonId)
+    {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+       int operationMode = Integer.parseInt(preferences.getString("operationMode", "0"));
+        
+       if (buttonId == R.id.CreateObjectButton)
+       {
+               if (operationMode == OPERATIONMODE_CREATE)
+               {
+                       operationMode = OPERATIONMODE_MOVE;
+               }
+               else
+               {
+                       operationMode = OPERATIONMODE_CREATE;
+               }
+       }
+       else if (buttonId == R.id.DeleteObjectButton)
+       {
+               if (operationMode == OPERATIONMODE_DELETE)
+               {
+                       operationMode = OPERATIONMODE_MOVE;
+               }
+               else
+               {
+                       operationMode = OPERATIONMODE_DELETE;
+               }
+       }
+       changeOperationMode(operationMode);
+       
+       return (operationMode);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/Preference.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/Preference.java
new file mode 100644 (file)
index 0000000..385752f
--- /dev/null
@@ -0,0 +1,53 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+/**
+ *    Androidの設定画面
+ * 
+ * @author MRSa
+ *
+ */
+public class Preference extends PreferenceActivity implements OnSharedPreferenceChangeListener
+{
+    /**
+     *  コンストラクタ
+     *
+     **/
+    public Preference()
+    {
+       
+    }
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.layout.preference);
+    }
+
+    @Override
+    protected void onResume()
+    {
+        super.onResume();
+        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
+    }
+
+    @Override
+    protected void onPause()
+    {
+        super.onPause();
+        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
+    }
+
+    /**
+     *  設定値が変更されたときの処理
+     */
+    public void onSharedPreferenceChanged(SharedPreferences shardPref, String key)
+    {
+        //
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/SelectFeatureListener.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/SelectFeatureListener.java
new file mode 100644 (file)
index 0000000..39d883c
--- /dev/null
@@ -0,0 +1,34 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.Activity;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+/**
+ *   「フィーチャ選択ボタン」を押されたときの処理
+ *
+ * @author MRSa
+ *
+ */
+public class SelectFeatureListener implements OnClickListener
+{
+    //private Activity parent = null;  // 親分
+
+    /**
+     *  コンストラクタ
+     * @param argument
+     */
+    public SelectFeatureListener(Activity argument)
+    {
+        //parent = argument;
+    }
+
+    /**
+     *   クリックされたときの処理
+     */
+    public void onClick(View v)
+    {
+        // int id = v.getId();
+
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/SelectLineShapeDialog.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/SelectLineShapeDialog.java
new file mode 100644 (file)
index 0000000..14ae039
--- /dev/null
@@ -0,0 +1,481 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.Color;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.BitmapDrawable;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+
+/**
+ *   接続線の形状を選択するダイアログを表示する
+ * 
+ * @author MRSa
+ *
+ */
+public class SelectLineShapeDialog implements ImageButton.OnClickListener
+{
+       private int lineThickness = LineStyleHolder.LINETHICKNESS_THIN;
+       private int lineStyle = LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW;
+       private int lineShape = LineStyleHolder.LINESHAPE_NORMAL;
+       
+       private Context context = null; 
+       private IResultReceiver resultReceiver = null;
+       private LineStyleHolder lineStyleHolder = null;
+       
+       private View dialogLayout = null;
+
+       /**
+        *    コンストラクタ
+        * 
+        * @param arg
+        * @param holder
+        */
+       public SelectLineShapeDialog(Context arg, LineStyleHolder holder)
+       {
+               context = arg;
+               lineStyleHolder = holder;
+       }
+
+       /**
+        *    ダイアログで選択した結果を受信するためのレシーバを設定する
+        * 
+        * @param receiver
+        */
+       public void setResultReceiver(IResultReceiver receiver)
+       {
+               resultReceiver = receiver;
+       }
+       
+    /**
+     *   確認ダイアログを応答する
+     * @return
+     */
+    public Dialog getDialog()
+    {
+       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final View layout = inflater.inflate(R.layout.lineselection, null);
+        dialogLayout = layout;
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+
+        //  ダイアログで表示するデータを設定する場所
+
+        // 現在の線の形状と種類を取得する
+        lineShape = lineStyleHolder.getLineShape();
+        lineStyle = lineStyleHolder.getLineStyle();
+        lineThickness = lineStyleHolder.getLineThickness();
+
+        // 線の太さ
+        final ImageButton thin = (ImageButton) layout.findViewById(R.id.btnLineThicknessThin);
+        thin.setOnClickListener(this);
+        final ImageButton middle = (ImageButton) layout.findViewById(R.id.btnLineThicknessMiddle);
+        middle.setOnClickListener(this);
+        final ImageButton heavy = (ImageButton) layout.findViewById(R.id.btnLineThicknessHeavy);
+        heavy.setOnClickListener(this);
+
+        // 線の形状
+        final ImageButton straight = (ImageButton) layout.findViewById(R.id.btnLineShapeStraight);
+        straight.setOnClickListener(this);
+        final ImageButton tree = (ImageButton) layout.findViewById(R.id.btnLineShapeTree);
+        tree.setOnClickListener(this);
+        final ImageButton curve = (ImageButton) layout.findViewById(R.id.btnLineShapeCurve);
+        curve.setOnClickListener(this);
+        final ImageButton straightDash = (ImageButton) layout.findViewById(R.id.btnLineShapeStraightDash);
+        straightDash.setOnClickListener(this);
+        final ImageButton treeDash = (ImageButton) layout.findViewById(R.id.btnLineShapeTreeDash);
+        treeDash.setOnClickListener(this);
+        final ImageButton curveDash = (ImageButton) layout.findViewById(R.id.btnLineShapeCurveDash);
+        curveDash.setOnClickListener(this);
+        final ImageButton straightRarrow = (ImageButton) layout.findViewById(R.id.btnLineShapeStraightRarrow);
+        straightRarrow.setOnClickListener(this);
+        final ImageButton treeRarrow = (ImageButton) layout.findViewById(R.id.btnLineShapeTreeRarrow);
+        treeRarrow.setOnClickListener(this);
+        final ImageButton curveRarrow = (ImageButton) layout.findViewById(R.id.btnLineShapeCurveRarrow);
+        curveRarrow.setOnClickListener(this);
+        final ImageButton straightRarrowDash = (ImageButton) layout.findViewById(R.id.btnLineShapeStraightRarrowDash);
+        straightRarrowDash.setOnClickListener(this);
+        final ImageButton treeRarrowDash = (ImageButton) layout.findViewById(R.id.btnLineShapeTreeRarrowDash);
+        treeRarrowDash.setOnClickListener(this);
+        final ImageButton curveRarrowDash = (ImageButton) layout.findViewById(R.id.btnLineShapeCurveRarrowDash);
+        curveRarrowDash.setOnClickListener(this);
+
+        builder.setView(layout);
+        builder.setTitle(context.getString(R.string.Title_SelectLineShape));
+        builder.setCancelable(false);
+        builder.setPositiveButton(context.getString(R.string.confirmYes), new DialogInterface.OnClickListener()
+              {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          setLineShape(lineStyle, lineShape, lineThickness);
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.finishSelectLineShape(lineStyle, lineShape, lineThickness);
+                          }
+                          updateButtonHighlightLineThickness(0);
+                          updateButtonHighlightLineShape(0);
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+               });
+        builder.setNegativeButton(context.getString(R.string.confirmNo), new DialogInterface.OnClickListener()
+               {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.cancelSelectLineShape();
+                          }
+                          updateButtonHighlightLineThickness(0);
+                          updateButtonHighlightLineShape(0);
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+               });
+        return (builder.create());     
+    }
+
+    /**
+     *    オブジェクト入力用ダイアログの表示を準備する
+     *    (ダイアログの表示をした時に呼ばれる)
+     */
+    public void prepareSelectLineShapeDialog(Dialog dialog, Integer objectKey)
+    {
+        // 現在の線の形状と種類を取得する
+        lineShape = lineStyleHolder.getLineShape();
+        lineStyle = lineStyleHolder.getLineStyle();
+        lineThickness = lineStyleHolder.getLineThickness();
+
+        // 画面(ダイアログ)で、現在選択中のものをハイライトにする。
+        updateButtonHighlightLineThickness(getLineThicknessButtonId(lineThickness));
+        updateButtonHighlightLineShape(getLineShapeButtonId(lineStyle, lineShape));
+
+    }
+
+    /**
+     *    線の形状を設定する
+     * 
+     * @param toSetLineStyle
+     * @param toSetLineShape
+     */
+    public void setLineShape(int toSetLineStyle, int toSetLineShape, int toSetLineThickness)
+    {
+        lineStyleHolder.setLineShape(toSetLineShape);
+        lineStyleHolder.setLineStyle(toSetLineStyle);
+        lineStyleHolder.setLineThickness(toSetLineThickness);
+        
+        Log.v(Main.APP_IDENTIFIER, ":::CHANGE LINE :::  shape:" + toSetLineShape + " style:" + toSetLineStyle + " thickness:" + toSetLineThickness);
+    }
+
+    /**
+     * 
+     * 
+     * @param id       更新するボタンのID
+     * @param judge 判断するボタンのID
+     */
+    private void setButtonBorder(int id, int judge)
+    {
+       try
+       {
+            ImageButton button = (ImageButton) dialogLayout.findViewById(id);
+            //GradientDrawable btnBackgroundShape = (GradientDrawable)button.getBackground();
+            BitmapDrawable btnBackgroundShape = (BitmapDrawable)button.getBackground();
+            if (id == judge)
+            {
+                //btnBackgroundShape.setColorFilter(Color.rgb(51, 181, 229), Mode.LIGHTEN);
+               btnBackgroundShape.setColorFilter(Color.BLUE, Mode.LIGHTEN);
+            }
+            else
+            {
+               btnBackgroundShape.setColorFilter(Color.BLACK, Mode.LIGHTEN);
+            } 
+       }
+       catch (Exception ex)
+       {
+               // 
+               Log.v(Main.APP_IDENTIFIER, "setButtonBorder(): " + ex.toString());
+       }
+       
+    }
+    
+    /**
+     *    イメージボタンの選択状態を更新する (接続線の太さ)
+     * 
+     * @param buttonId
+     */
+    private void updateLineThickness(int buttonId)
+    {
+       switch (buttonId)
+       {
+          case R.id.btnLineThicknessMiddle:
+               lineThickness = LineStyleHolder.LINETHICKNESS_MIDDLE;
+               break;
+         case R.id.btnLineThicknessHeavy:
+               lineThickness = LineStyleHolder.LINETHICKNESS_HEAVY;
+               break;
+          case R.id.btnLineThicknessThin:
+         default:
+               lineThickness = LineStyleHolder.LINETHICKNESS_THIN;
+           break;
+       }
+    }
+
+    /**
+     *    線の形状の選択状態を記憶(更新)する
+     * 
+     * @param buttonId
+     */
+    private void updateLineStyle(int buttonId)
+    {
+       switch (buttonId)
+       {
+          case R.id.btnLineShapeTree:
+               lineStyle = LineStyleHolder.LINESTYLE_TREESTYLE_NO_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_NORMAL;
+               break;
+
+          case R.id.btnLineShapeCurve:
+               lineStyle = LineStyleHolder.LINESTYLE_CURVESTYLE_NO_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_NORMAL;
+               break;
+
+          case R.id.btnLineShapeStraightDash:
+               lineStyle = LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_DASH;
+           break;
+
+          case R.id.btnLineShapeTreeDash:
+               lineStyle = LineStyleHolder.LINESTYLE_TREESTYLE_NO_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_DASH;
+           break;
+
+          case R.id.btnLineShapeCurveDash:
+               lineStyle = LineStyleHolder.LINESTYLE_CURVESTYLE_NO_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_DASH;
+               break;
+
+         case R.id.btnLineShapeStraightRarrow:
+               lineStyle = LineStyleHolder.LINESTYLE_STRAIGHT_R_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_NORMAL;
+           break;
+
+         case R.id.btnLineShapeTreeRarrow:
+            lineStyle = LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW;
+            lineShape = LineStyleHolder.LINESHAPE_NORMAL;
+           break;
+
+          case R.id.btnLineShapeCurveRarrow:
+               lineStyle = LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_NORMAL;
+           break;
+               
+         case R.id.btnLineShapeStraightRarrowDash:
+               lineStyle = LineStyleHolder.LINESTYLE_STRAIGHT_R_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_DASH;
+           break;
+
+         case R.id.btnLineShapeTreeRarrowDash:
+               lineStyle = LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_DASH;
+           break;
+
+          case R.id.btnLineShapeCurveRarrowDash:
+               lineStyle = LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_DASH;
+           break;
+
+          case R.id.btnLineShapeStraight:
+         default:
+               lineStyle = LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW;
+               lineShape = LineStyleHolder.LINESHAPE_NORMAL;
+           break;
+       }
+       
+    }    
+    /**
+     *    現在の太さを設定する
+     * 
+     * @param thickness
+     * @return
+     */
+    private int getLineThicknessButtonId(int thickness)
+    {
+        int buttonId = R.id.btnLineThicknessThin;
+       switch (thickness)
+        {
+             case LineStyleHolder.LINETHICKNESS_HEAVY:
+            buttonId = R.id.btnLineThicknessHeavy;
+            break;
+
+         case LineStyleHolder.LINETHICKNESS_MIDDLE:
+              buttonId = R.id.btnLineThicknessMiddle;
+              break;
+
+         case LineStyleHolder.LINETHICKNESS_THIN:
+          default:
+                 buttonId = R.id.btnLineThicknessThin;
+                 break;
+        }
+        return (buttonId);
+    }    
+    
+    /**
+     * 
+     * 
+     * @param currentLineStyle
+     * @param currentLineShape
+     * @return
+     */
+    private int getLineShapeButtonId(int currentLineStyle, int currentLineShape)
+    {
+        int buttonId = R.id.btnLineShapeStraight;
+       
+        if ((currentLineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_NO_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+        {
+               buttonId = R.id.btnLineShapeTree;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_NO_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+        {
+               buttonId = R.id.btnLineShapeCurve;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+        {
+               buttonId = R.id.btnLineShapeStraightDash;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_NO_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+        {
+               buttonId = R.id.btnLineShapeTreeDash;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_NO_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+        {
+               buttonId = R.id.btnLineShapeCurveDash;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_R_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+        {
+               buttonId = R.id.btnLineShapeStraightRarrow;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+        {
+               buttonId = R.id.btnLineShapeTreeRarrow;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+        {
+               buttonId = R.id.btnLineShapeCurveRarrow;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_R_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+        {
+               buttonId = R.id.btnLineShapeStraightRarrowDash;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_TREESTYLE_R_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+        {
+               buttonId = R.id.btnLineShapeTreeRarrowDash;
+        }
+        else if ((currentLineStyle == LineStyleHolder.LINESTYLE_CURVESTYLE_R_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_DASH))
+        {
+               buttonId = R.id.btnLineShapeCurveRarrowDash;
+        }
+        /**
+        else  if ((currentLineStyle == LineStyleHolder.LINESTYLE_STRAIGHT_NO_ARROW)&&
+                       (currentLineShape == LineStyleHolder.LINESHAPE_NORMAL))
+        {
+               buttonId = R.id.btnLineShapeStraight;
+        }
+        **/
+        return (buttonId);
+    }
+
+    /**
+     * 
+     *     
+     * @param id
+     */
+    private void updateButtonHighlightLineThickness(int id)
+    {
+       setButtonBorder(R.id.btnLineThicknessThin, id); 
+       setButtonBorder(R.id.btnLineThicknessMiddle, id);       
+       setButtonBorder(R.id.btnLineThicknessHeavy, id);        
+    }
+    
+    /**
+     * 
+     * 
+     * @param id
+     */
+    private void updateButtonHighlightLineShape(int id)
+    {
+        setButtonBorder(R.id.btnLineShapeStraight, id);        
+       setButtonBorder(R.id.btnLineShapeTree, id);     
+       setButtonBorder(R.id.btnLineShapeCurve, id);    
+
+       setButtonBorder(R.id.btnLineShapeStraightDash, id);     
+       setButtonBorder(R.id.btnLineShapeTreeDash, id); 
+       setButtonBorder(R.id.btnLineShapeCurveDash, id);        
+
+       setButtonBorder(R.id.btnLineShapeStraightRarrow, id);   
+       setButtonBorder(R.id.btnLineShapeTreeRarrow, id);       
+       setButtonBorder(R.id.btnLineShapeCurveRarrow, id);      
+
+       setButtonBorder(R.id.btnLineShapeStraightRarrowDash, id);       
+       setButtonBorder(R.id.btnLineShapeTreeRarrowDash, id);   
+       setButtonBorder(R.id.btnLineShapeCurveRarrowDash, id);          
+    }
+    
+    /**
+     *    ボタンが押された時の処理...
+     * 
+     */
+    public void onClick(View v)
+    {
+       int id = v.getId();
+       
+       // 押されたボタンが接続線の太さだった場合...
+        if ((id == R.id.btnLineThicknessThin)||(id == R.id.btnLineThicknessMiddle)||(id == R.id.btnLineThicknessHeavy))
+        {
+               updateButtonHighlightLineThickness(id);
+               updateLineThickness(id);
+               return;
+        }
+
+        // 線の形状を更新した場合...
+        updateButtonHighlightLineShape(id);
+       updateLineStyle(id);
+    }
+
+    public interface IResultReceiver
+    {
+        public abstract void finishSelectLineShape(int style, int shape, int thickness);
+        public abstract void cancelSelectLineShape();
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/SharedIntentInvoker.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/SharedIntentInvoker.java
new file mode 100644 (file)
index 0000000..15d18dd
--- /dev/null
@@ -0,0 +1,65 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.util.Log;
+import android.widget.Toast;
+
+/**
+ *   共有Intentを発行するクラス。
+ * 
+ * @author MRSa
+ *
+ */
+public class SharedIntentInvoker
+{
+       private static final String  IDENTIFIER = "Gokigen";
+       
+    /**
+     *    メール送信用のIntentを発行する処理。
+     * @param parent   呼び出し元Activity
+     * @param id          Intentが呼び出し元Activityに戻った時に、呼ばれていたのは何か識別するID
+     * @param mailTitle         共有データタイトル
+     * @param mailMessage   共有データ本文
+     * @param fileName         添付データファイル名称
+     * @param fileType           添付データファイルの形 (text/plain とか  image/* とか ...)
+     */
+    static public void shareContent(Activity parent, int id, String mailTitle, String mailMessage, String fileName, String fileType)
+    {
+        Intent intent = new Intent();
+        intent.setAction(Intent.ACTION_SEND);
+        try
+        {
+            intent.setType("text/plain");
+            intent.putExtra(Intent.EXTRA_SUBJECT, mailTitle);
+            intent.putExtra(Intent.EXTRA_TEXT, mailMessage);
+            try
+            {
+               if ((fileName.isEmpty() == false)&&(fileType.isEmpty() == false))
+               {
+                       // ファイルを添付する
+                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 
+                    intent.setType(fileType);
+                    intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + fileName));
+                    Log.v(IDENTIFIER, "Attached :" + fileName);
+               }
+            }
+            catch (Exception ee)
+            {
+               // 
+                Log.v(IDENTIFIER, "attach failure : " + fileName + "  " + ee.toString() + " " + ee.getMessage());
+            }
+            parent.startActivityForResult(intent, id);                 
+        }
+        catch (android.content.ActivityNotFoundException ex)
+        {
+            Toast.makeText(parent, "" + ex.getMessage(), Toast.LENGTH_SHORT).show();
+            Log.v(IDENTIFIER, "android.content.ActivityNotFoundException : " + ex.toString() + " " + ex.getMessage());
+        }
+        catch (Exception e)
+        {
+            Log.v(IDENTIFIER, "xxx : " + e.toString() + " " + e.getMessage());
+        }
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/SymbolListArrayAdapter.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/SymbolListArrayAdapter.java
new file mode 100644 (file)
index 0000000..4fc0a13
--- /dev/null
@@ -0,0 +1,74 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.util.List;
+
+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;
+
+public class SymbolListArrayAdapter extends ArrayAdapter<SymbolListArrayItem>
+{
+    private LayoutInflater inflater = null;
+    private int textViewResourceId = 0;
+    private List<SymbolListArrayItem> listItems = null;
+    
+    /**
+     * コンストラクタ
+     */
+    public SymbolListArrayAdapter(Context context, int textId, List<SymbolListArrayItem> items)
+    {
+        super(context, textId, items);
+
+        // リソースIDと表示アイテム
+        textViewResourceId = textId;
+        listItems = items;
+
+        // ContextからLayoutInflaterを取得
+        inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+    }
+    
+    /**
+     * 
+     */
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent)
+    {
+        View view = null;
+        if(convertView != null)
+        {
+            view = convertView;
+        }
+        else
+        {
+            view = inflater.inflate(textViewResourceId, null);
+        }
+
+        SymbolListArrayItem item = listItems.get(position);
+        
+        ImageView imageView = (ImageView) view.findViewWithTag("icon");
+        imageView.setImageResource(item.getIconResource());
+
+        int subIcon = item.getSubIconResource();
+        //if (subIcon != 0)
+        {
+            ImageView subImage = (ImageView) view.findViewWithTag("subIcon");
+            subImage.setImageResource(subIcon);
+        }            
+
+        TextView titleView = (TextView)view.findViewWithTag("title");
+        titleView.setText(item.getTextResource1st());
+
+        TextView detailView = (TextView)view.findViewWithTag("detail");
+        detailView.setText(item.getTextResource2nd());
+
+        /**
+        TextView optionView = (TextView)view.findViewWithTag("option");
+        optionView.setText(item.getTextResource3rd());
+        **/
+        return (view);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/SymbolListArrayItem.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/SymbolListArrayItem.java
new file mode 100644 (file)
index 0000000..7da3cf8
--- /dev/null
@@ -0,0 +1,74 @@
+package jp.sourceforge.gokigen.memoma;
+
+public class SymbolListArrayItem
+{
+    private int iconResource = 0;
+    private int subIconResource = 0;
+    private String textResource1st = "";
+    private String textResource2nd = "";
+    private String textResource3rd = "";
+
+    /**
+     *  コンストラクタ
+     * @param iconId
+     * @param textId
+     */
+    public SymbolListArrayItem(int iconId1, String textData1, String textData2, String textData3, int iconId2)
+    {
+        iconResource = iconId1;
+        textResource1st = textData1;
+        textResource2nd = textData2;
+        textResource3rd = textData3;
+        subIconResource = iconId2;
+    }
+    
+    public int getIconResource()
+    {
+        return (iconResource);
+    }
+
+    public void setIconResource(int iconId)
+    {
+        iconResource = iconId;
+    }
+
+    public String getTextResource1st()
+    {
+        return (textResource1st);
+    }
+
+    public void setTextResource1st(String textData)
+    {
+        textResource1st = textData;
+    }    
+
+    public String getTextResource2nd()
+    {
+        return (textResource2nd);
+    }
+
+    public void setTextResource2nd(String textData)
+    {
+        textResource2nd = textData;
+    }
+    
+    public String getTextResource3rd()
+    {
+        return (textResource3rd);
+    }
+    
+    public void setTextResource3rd(String textData)
+    {
+        textResource3rd = textData;
+    }
+    
+    public int getSubIconResource()
+    {
+        return (subIconResource);
+    }
+    
+    public void setSubIconResource(int iconId)
+    {
+        subIconResource = iconId;
+    }    
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/TextEditDialog.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/TextEditDialog.java
new file mode 100644 (file)
index 0000000..7e8f497
--- /dev/null
@@ -0,0 +1,147 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ *  テキスト編集のダイアログ
+ * 
+ * @author MRSa
+ *
+ */
+public class TextEditDialog
+{
+       private Context context = null;
+       private ITextEditResultReceiver resultReceiver = null;
+       private int    icon = 0;
+       private String title = null;
+
+       /**
+        *   コンストラクタ
+        * @param arg
+        */
+       public TextEditDialog(Context arg, int titleIcon)
+       {
+               context = arg;
+               icon = titleIcon;
+       }
+
+       /**
+        *  クラスの準備
+        * @param receiver
+        * @param initialMessage
+        */
+       public void prepare(Dialog layout, ITextEditResultReceiver receiver, String titleMessage, String initialMessage, boolean isSingleLine)
+       {
+               if (receiver != null)
+               {
+                       resultReceiver = receiver;
+               }
+        try
+        {
+            final TextView  editComment = (TextView)  layout.findViewById(R.id.editTextArea);
+            if (titleMessage != null)
+            {
+                layout.setTitle(titleMessage);
+                title = titleMessage;
+            }
+
+            // テキスト入力エリアの文字を設定する
+            if (initialMessage != null)
+            {
+                editComment.setText(initialMessage);
+            }
+            else
+            {
+                editComment.setText("");
+            }
+
+            // 入力領域の行数を更新する
+            editComment.setSingleLine(isSingleLine);
+        }
+        catch (Exception ex)
+        {
+               // ログだけ吐いて、何もしない
+               Log.v(Main.APP_IDENTIFIER, "TextEditDialog::prepare() " + ex.toString());
+        }
+       }
+       
+    /**
+     *   テキスト編集ダイアログを応答する
+     * @return
+     */
+    public Dialog getDialog()
+    {
+       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final View layout = inflater.inflate(R.layout.messagedialog, null);
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        final TextView  editComment = (TextView)  layout.findViewById(R.id.editTextArea);
+
+        // 表示するデータ(アイコン、ダイアログタイトル、メッセージ)を準備する
+        if (icon != 0)
+        {
+            builder.setIcon(icon);
+        }
+        if (title != null)
+        {
+               builder.setTitle(title);
+        }
+
+        builder.setView(layout);
+        builder.setCancelable(false);
+        builder.setPositiveButton(context.getString(R.string.confirmYes), new DialogInterface.OnClickListener()
+              {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.finishTextEditDialog(editComment.getText().toString());
+                          }
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+               });
+        builder.setNegativeButton(context.getString(R.string.confirmNo), new DialogInterface.OnClickListener()
+               {
+                   public void onClick(DialogInterface dialog, int id)
+                   {
+                          boolean ret = false;
+                          if (resultReceiver != null)
+                          {
+                              resultReceiver.cancelTextEditDialog();
+                          }
+                       if (ret == true)
+                       {
+                          dialog.dismiss();
+                       }
+                       else
+                       {
+                           dialog.cancel();
+                       }
+                       System.gc();
+                   }
+               });
+        return (builder.create());     
+    }
+
+    public interface ITextEditResultReceiver
+    {
+        public abstract boolean finishTextEditDialog(String message);
+        public abstract boolean cancelTextEditDialog();
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/TextEditReceiver.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/TextEditReceiver.java
new file mode 100644 (file)
index 0000000..9cf6cfe
--- /dev/null
@@ -0,0 +1,71 @@
+package jp.sourceforge.gokigen.memoma;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.widget.TextView;
+
+/**
+ *   テキストデータの反映
+ * 
+ * @author MRSa
+ *
+ */
+public class TextEditReceiver implements TextEditDialog.ITextEditResultReceiver
+{
+       Activity parent = null;
+       String textId = null;
+       int     textResId = -1;
+       
+    /**
+     *    コンストラクタ
+     * 
+     */
+       public TextEditReceiver(Activity argument, String prefId, int resId)
+    {
+        textId = prefId;
+        parent = argument;
+        textResId = resId;
+    }
+       
+       /**
+        *   データの更新
+        * 
+        */
+    public boolean finishTextEditDialog(String message)
+    {
+       if ((message == null)||(message.length() == 0))
+       {
+            // データが入力されていなかったので、何もしない。
+               return (false);
+       }
+       
+       // 文字列を記録
+       SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putString(textId, message);
+        editor.commit();
+
+        if (textResId != 0)
+        {
+            // 画面表示の更新
+               final TextView infoText = (TextView) parent.findViewById(textResId);
+               infoText.setText(message);
+        }
+        else
+        {
+               // リソースIDが指定されていない場合は、タイトルを更新する
+               parent.setTitle(message);
+        }
+        
+        return (true);
+    }
+
+    /**
+     *   データを更新しないとき...
+     */
+    public boolean cancelTextEditDialog()
+    {
+        return (false);
+    }
+}
diff --git a/app/src/main/java/jp/sourceforge/gokigen/memoma/ViewCaptureExporter.java b/app/src/main/java/jp/sourceforge/gokigen/memoma/ViewCaptureExporter.java
new file mode 100644 (file)
index 0000000..0efcfa4
--- /dev/null
@@ -0,0 +1,193 @@
+package jp.sourceforge.gokigen.memoma;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.os.AsyncTask;
+import android.util.Log;
+import android.view.View;
+
+/**
+ *  データをファイルに保存するとき用 アクセスラッパ (非同期処理を実行)
+ *  Viewの情報を画像形式(png形式)で保存する。
+ *  どのViewを保存するのかは、ICaptureExporter.getCaptureTargetView()クラスを使って教えてもらう。
+ *  
+ *  AsyncTask
+ *    String       : 実行時に渡すクラス(Param)           : ファイル名をもらう
+ *    Integer    : 途中経過を伝えるクラス(Progress)   : 今回は使っていない
+ *    String      : 処理結果を伝えるクラス(Result)      : 結果を応答する。
+ *    
+ * @author MRSa
+ *
+ */
+public class ViewCaptureExporter extends AsyncTask<String, Integer, String>
+{
+       private ICaptureExporter receiver = null;
+       private ExternalStorageFileUtility fileUtility = null;  
+       private String exportedFileName = null;
+
+       private ProgressDialog savingDialog = null;
+       
+       private Bitmap targetBitmap = null;
+
+       /**
+        *   コンストラクタ
+        */
+    public ViewCaptureExporter(Context context, ExternalStorageFileUtility utility,  ICaptureExporter resultReceiver)
+    {
+       receiver = resultReceiver;
+       fileUtility = utility;
+
+        //  プログレスダイアログ(「保存中...」)を表示する。
+       savingDialog = new ProgressDialog(context);
+       savingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+       savingDialog.setMessage(context.getString(R.string.dataSaving));
+       savingDialog.setIndeterminate(true);
+       savingDialog.setCancelable(false);
+       savingDialog.show();
+
+       /** ファイルをバックアップするディレクトリを作成する **/
+       File dir = new File(fileUtility.getGokigenDirectory() + "/exported");
+       dir.mkdir();
+    }
+       
+    /**
+     *  非同期処理実施前の前処理
+     * 
+     */
+    @Override
+    protected void onPreExecute()
+    {
+       try
+       {
+               targetBitmap = null;
+            if (receiver != null)
+            {
+               // 画面のキャプチャを実施する
+               View targetView = receiver.getCaptureTargetView();
+               targetView.setDrawingCacheEnabled(false);
+               targetView.setDrawingCacheEnabled(true);
+               targetBitmap = Bitmap.createBitmap(targetView.getDrawingCache());
+               targetView.setDrawingCacheEnabled(false);
+            }
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "ViewCaptureExporter::onPreExecute() : " + ex.toString());
+       }
+    }
+    
+    /**
+     *    ビットマップデータを(PNG形式で)保管する。
+     * 
+     * @param fileName
+     * @param objectHolder
+     * @return
+     */
+    private String exportToFile(String fileName)
+    {
+       String resultMessage = "";
+        try
+        {
+               if (targetBitmap == null)
+               {
+                       // ビットマップが取れないため、ここで折り返す。
+                       return ("SCREEN DATA GET FAILURE...");
+               }
+               
+               // エクスポートするファイル名を決定する
+            Calendar calendar = Calendar.getInstance();
+            SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+            exportedFileName = fileName + "_" + outFormat.format(calendar.getTime()) + ".png";
+
+            // PNG形式でファイル出力を行う。
+            OutputStream out = new FileOutputStream(exportedFileName);
+            targetBitmap.compress(CompressFormat.PNG, 100, out);
+            out.flush();
+            out.close();            
+        }
+        catch (Exception e)
+        {
+               resultMessage = " ERR(png)>" + e.toString();
+            Log.v(Main.APP_IDENTIFIER, resultMessage);
+            e.printStackTrace();
+        } 
+        return (resultMessage);
+    }
+
+    /**
+     *  非同期処理
+     *  (バックグラウンドで実行する(このメソッドは、UIスレッドと別のところで実行する))
+     * 
+     */
+    @Override
+    protected String doInBackground(String... datas)
+    {
+        // ファイル名の設定 ... (拡張子なし)
+       String fileName = fileUtility.getGokigenDirectory() + "/exported/" + datas[0];
+
+       // データを保管する
+        String result = exportToFile(fileName);
+
+        System.gc();
+
+               return (result);
+    }
+
+    /**
+     *  非同期処理の進捗状況の更新
+     * 
+     */
+       @Override
+       protected void onProgressUpdate(Integer... values)
+       {
+        // 今回は何もしない
+       }
+
+    /**
+     *  非同期処理の後処理
+     *  (結果を応答する)
+     */
+    @Override
+    protected void onPostExecute(String result)
+    {
+       try
+       {
+            if (receiver != null)
+            {
+               receiver.onCaptureExportedResult(exportedFileName, result);
+            }
+       }
+       catch (Exception ex)
+       {
+               Log.v(Main.APP_IDENTIFIER, "ViewCaptureExporter::onPostExecute() : " + ex.toString());
+       }
+       // プログレスダイアログを消す
+       if (savingDialog != null)
+       {
+            savingDialog.dismiss();
+       }
+       return;
+    }     
+    /**
+     *    結果報告用のインタフェース
+     *    
+     * @author MRSa
+     *
+     */
+    public interface ICaptureExporter
+    {
+       /** データをキャプチャする Viewを取得する **/
+       public abstract View getCaptureTargetView();
+       
+        /**  保存結果の報告 **/
+        public abstract void onCaptureExportedResult(String exportedFileName, String detail);
+    }
+}
diff --git a/app/src/main/res/drawable-hdpi/icon.png b/app/src/main/res/drawable-hdpi/icon.png
new file mode 100644 (file)
index 0000000..efe5aff
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon.png differ
diff --git a/app/src/main/res/drawable-hdpi/icon0.png b/app/src/main/res/drawable-hdpi/icon0.png
new file mode 100644 (file)
index 0000000..b7c7f76
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon0.png differ
diff --git a/app/src/main/res/drawable-ldpi/icon0.png b/app/src/main/res/drawable-ldpi/icon0.png
new file mode 100644 (file)
index 0000000..ae64f39
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/icon0.png differ
diff --git a/app/src/main/res/drawable-mdpi/icon0.png b/app/src/main/res/drawable-mdpi/icon0.png
new file mode 100644 (file)
index 0000000..e5d23ad
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon0.png differ
diff --git a/app/src/main/res/drawable/btn_arrow_down.png b/app/src/main/res/drawable/btn_arrow_down.png
new file mode 100644 (file)
index 0000000..af4825c
Binary files /dev/null and b/app/src/main/res/drawable/btn_arrow_down.png differ
diff --git a/app/src/main/res/drawable/btn_arrow_left.png b/app/src/main/res/drawable/btn_arrow_left.png
new file mode 100644 (file)
index 0000000..2c725b1
Binary files /dev/null and b/app/src/main/res/drawable/btn_arrow_left.png differ
diff --git a/app/src/main/res/drawable/btn_arrow_right.png b/app/src/main/res/drawable/btn_arrow_right.png
new file mode 100644 (file)
index 0000000..567d6da
Binary files /dev/null and b/app/src/main/res/drawable/btn_arrow_right.png differ
diff --git a/app/src/main/res/drawable/btn_arrow_up.png b/app/src/main/res/drawable/btn_arrow_up.png
new file mode 100644 (file)
index 0000000..d9d6b5d
Binary files /dev/null and b/app/src/main/res/drawable/btn_arrow_up.png differ
diff --git a/app/src/main/res/drawable/btn_checked.png b/app/src/main/res/drawable/btn_checked.png
new file mode 100644 (file)
index 0000000..ff6fb82
Binary files /dev/null and b/app/src/main/res/drawable/btn_checked.png differ
diff --git a/app/src/main/res/drawable/btn_circle.png b/app/src/main/res/drawable/btn_circle.png
new file mode 100644 (file)
index 0000000..d7b730b
Binary files /dev/null and b/app/src/main/res/drawable/btn_circle.png differ
diff --git a/app/src/main/res/drawable/btn_circle_normal.png b/app/src/main/res/drawable/btn_circle_normal.png
new file mode 100644 (file)
index 0000000..fc5af1c
Binary files /dev/null and b/app/src/main/res/drawable/btn_circle_normal.png differ
diff --git a/app/src/main/res/drawable/btn_circle_pressed.png b/app/src/main/res/drawable/btn_circle_pressed.png
new file mode 100644 (file)
index 0000000..8f40afd
Binary files /dev/null and b/app/src/main/res/drawable/btn_circle_pressed.png differ
diff --git a/app/src/main/res/drawable/btn_circle_selected.png b/app/src/main/res/drawable/btn_circle_selected.png
new file mode 100644 (file)
index 0000000..c74fac2
Binary files /dev/null and b/app/src/main/res/drawable/btn_circle_selected.png differ
diff --git a/app/src/main/res/drawable/btn_create.png b/app/src/main/res/drawable/btn_create.png
new file mode 100644 (file)
index 0000000..fe65d4e
Binary files /dev/null and b/app/src/main/res/drawable/btn_create.png differ
diff --git a/app/src/main/res/drawable/btn_curve.png b/app/src/main/res/drawable/btn_curve.png
new file mode 100644 (file)
index 0000000..98c12fd
Binary files /dev/null and b/app/src/main/res/drawable/btn_curve.png differ
diff --git a/app/src/main/res/drawable/btn_curve_dash.png b/app/src/main/res/drawable/btn_curve_dash.png
new file mode 100644 (file)
index 0000000..b0cc1e2
Binary files /dev/null and b/app/src/main/res/drawable/btn_curve_dash.png differ
diff --git a/app/src/main/res/drawable/btn_curve_larrow.png b/app/src/main/res/drawable/btn_curve_larrow.png
new file mode 100644 (file)
index 0000000..203b13b
Binary files /dev/null and b/app/src/main/res/drawable/btn_curve_larrow.png differ
diff --git a/app/src/main/res/drawable/btn_curve_larrow_dash.png b/app/src/main/res/drawable/btn_curve_larrow_dash.png
new file mode 100644 (file)
index 0000000..7a43864
Binary files /dev/null and b/app/src/main/res/drawable/btn_curve_larrow_dash.png differ
diff --git a/app/src/main/res/drawable/btn_curve_rarrow.png b/app/src/main/res/drawable/btn_curve_rarrow.png
new file mode 100644 (file)
index 0000000..7152033
Binary files /dev/null and b/app/src/main/res/drawable/btn_curve_rarrow.png differ
diff --git a/app/src/main/res/drawable/btn_curve_rarrow_dash.png b/app/src/main/res/drawable/btn_curve_rarrow_dash.png
new file mode 100644 (file)
index 0000000..9f53eaf
Binary files /dev/null and b/app/src/main/res/drawable/btn_curve_rarrow_dash.png differ
diff --git a/app/src/main/res/drawable/btn_delete.png b/app/src/main/res/drawable/btn_delete.png
new file mode 100644 (file)
index 0000000..03f64d8
Binary files /dev/null and b/app/src/main/res/drawable/btn_delete.png differ
diff --git a/app/src/main/res/drawable/btn_diamond.png b/app/src/main/res/drawable/btn_diamond.png
new file mode 100644 (file)
index 0000000..9faf360
Binary files /dev/null and b/app/src/main/res/drawable/btn_diamond.png differ
diff --git a/app/src/main/res/drawable/btn_double.png b/app/src/main/res/drawable/btn_double.png
new file mode 100644 (file)
index 0000000..ce4759d
Binary files /dev/null and b/app/src/main/res/drawable/btn_double.png differ
diff --git a/app/src/main/res/drawable/btn_double_dash.png b/app/src/main/res/drawable/btn_double_dash.png
new file mode 100644 (file)
index 0000000..01014f2
Binary files /dev/null and b/app/src/main/res/drawable/btn_double_dash.png differ
diff --git a/app/src/main/res/drawable/btn_drum.png b/app/src/main/res/drawable/btn_drum.png
new file mode 100644 (file)
index 0000000..05d3873
Binary files /dev/null and b/app/src/main/res/drawable/btn_drum.png differ
diff --git a/app/src/main/res/drawable/btn_expand.png b/app/src/main/res/drawable/btn_expand.png
new file mode 100644 (file)
index 0000000..5eb341e
Binary files /dev/null and b/app/src/main/res/drawable/btn_expand.png differ
diff --git a/app/src/main/res/drawable/btn_explode.png b/app/src/main/res/drawable/btn_explode.png
new file mode 100644 (file)
index 0000000..1a5431f
Binary files /dev/null and b/app/src/main/res/drawable/btn_explode.png differ
diff --git a/app/src/main/res/drawable/btn_filter.png b/app/src/main/res/drawable/btn_filter.png
new file mode 100644 (file)
index 0000000..2a57b57
Binary files /dev/null and b/app/src/main/res/drawable/btn_filter.png differ
diff --git a/app/src/main/res/drawable/btn_hexagonal.png b/app/src/main/res/drawable/btn_hexagonal.png
new file mode 100644 (file)
index 0000000..0871174
Binary files /dev/null and b/app/src/main/res/drawable/btn_hexagonal.png differ
diff --git a/app/src/main/res/drawable/btn_keyboard.png b/app/src/main/res/drawable/btn_keyboard.png
new file mode 100644 (file)
index 0000000..e65463e
Binary files /dev/null and b/app/src/main/res/drawable/btn_keyboard.png differ
diff --git a/app/src/main/res/drawable/btn_line_dash_heavy.png b/app/src/main/res/drawable/btn_line_dash_heavy.png
new file mode 100644 (file)
index 0000000..244571e
Binary files /dev/null and b/app/src/main/res/drawable/btn_line_dash_heavy.png differ
diff --git a/app/src/main/res/drawable/btn_line_dash_middle.png b/app/src/main/res/drawable/btn_line_dash_middle.png
new file mode 100644 (file)
index 0000000..a676bf3
Binary files /dev/null and b/app/src/main/res/drawable/btn_line_dash_middle.png differ
diff --git a/app/src/main/res/drawable/btn_line_dash_thin.png b/app/src/main/res/drawable/btn_line_dash_thin.png
new file mode 100644 (file)
index 0000000..048b2f0
Binary files /dev/null and b/app/src/main/res/drawable/btn_line_dash_thin.png differ
diff --git a/app/src/main/res/drawable/btn_line_heavy.png b/app/src/main/res/drawable/btn_line_heavy.png
new file mode 100644 (file)
index 0000000..a5f8fec
Binary files /dev/null and b/app/src/main/res/drawable/btn_line_heavy.png differ
diff --git a/app/src/main/res/drawable/btn_line_middle.png b/app/src/main/res/drawable/btn_line_middle.png
new file mode 100644 (file)
index 0000000..188155f
Binary files /dev/null and b/app/src/main/res/drawable/btn_line_middle.png differ
diff --git a/app/src/main/res/drawable/btn_line_thin.png b/app/src/main/res/drawable/btn_line_thin.png
new file mode 100644 (file)
index 0000000..0b14955
Binary files /dev/null and b/app/src/main/res/drawable/btn_line_thin.png differ
diff --git a/app/src/main/res/drawable/btn_move.png b/app/src/main/res/drawable/btn_move.png
new file mode 100644 (file)
index 0000000..aaa63fb
Binary files /dev/null and b/app/src/main/res/drawable/btn_move.png differ
diff --git a/app/src/main/res/drawable/btn_noregion.png b/app/src/main/res/drawable/btn_noregion.png
new file mode 100644 (file)
index 0000000..357b2d3
Binary files /dev/null and b/app/src/main/res/drawable/btn_noregion.png differ
diff --git a/app/src/main/res/drawable/btn_notchecked.png b/app/src/main/res/drawable/btn_notchecked.png
new file mode 100644 (file)
index 0000000..71b2c77
Binary files /dev/null and b/app/src/main/res/drawable/btn_notchecked.png differ
diff --git a/app/src/main/res/drawable/btn_oval.png b/app/src/main/res/drawable/btn_oval.png
new file mode 100644 (file)
index 0000000..7507639
Binary files /dev/null and b/app/src/main/res/drawable/btn_oval.png differ
diff --git a/app/src/main/res/drawable/btn_paper.png b/app/src/main/res/drawable/btn_paper.png
new file mode 100644 (file)
index 0000000..7b6ded4
Binary files /dev/null and b/app/src/main/res/drawable/btn_paper.png differ
diff --git a/app/src/main/res/drawable/btn_parallelogram.png b/app/src/main/res/drawable/btn_parallelogram.png
new file mode 100644 (file)
index 0000000..ce08a05
Binary files /dev/null and b/app/src/main/res/drawable/btn_parallelogram.png differ
diff --git a/app/src/main/res/drawable/btn_rectangle.png b/app/src/main/res/drawable/btn_rectangle.png
new file mode 100644 (file)
index 0000000..e392d2d
Binary files /dev/null and b/app/src/main/res/drawable/btn_rectangle.png differ
diff --git a/app/src/main/res/drawable/btn_roundrect.png b/app/src/main/res/drawable/btn_roundrect.png
new file mode 100644 (file)
index 0000000..34fac60
Binary files /dev/null and b/app/src/main/res/drawable/btn_roundrect.png differ
diff --git a/app/src/main/res/drawable/btn_save_normal.png b/app/src/main/res/drawable/btn_save_normal.png
new file mode 100644 (file)
index 0000000..991d138
Binary files /dev/null and b/app/src/main/res/drawable/btn_save_normal.png differ
diff --git a/app/src/main/res/drawable/btn_save_pressed.png b/app/src/main/res/drawable/btn_save_pressed.png
new file mode 100644 (file)
index 0000000..0dc81e9
Binary files /dev/null and b/app/src/main/res/drawable/btn_save_pressed.png differ
diff --git a/app/src/main/res/drawable/btn_save_selected.png b/app/src/main/res/drawable/btn_save_selected.png
new file mode 100644 (file)
index 0000000..623ab11
Binary files /dev/null and b/app/src/main/res/drawable/btn_save_selected.png differ
diff --git a/app/src/main/res/drawable/btn_sheet.png b/app/src/main/res/drawable/btn_sheet.png
new file mode 100644 (file)
index 0000000..ef15e94
Binary files /dev/null and b/app/src/main/res/drawable/btn_sheet.png differ
diff --git a/app/src/main/res/drawable/btn_straight.png b/app/src/main/res/drawable/btn_straight.png
new file mode 100644 (file)
index 0000000..e7ba65f
Binary files /dev/null and b/app/src/main/res/drawable/btn_straight.png differ
diff --git a/app/src/main/res/drawable/btn_straight_dash.png b/app/src/main/res/drawable/btn_straight_dash.png
new file mode 100644 (file)
index 0000000..e7ea9bf
Binary files /dev/null and b/app/src/main/res/drawable/btn_straight_dash.png differ
diff --git a/app/src/main/res/drawable/btn_straight_larrow.png b/app/src/main/res/drawable/btn_straight_larrow.png
new file mode 100644 (file)
index 0000000..2b4562c
Binary files /dev/null and b/app/src/main/res/drawable/btn_straight_larrow.png differ
diff --git a/app/src/main/res/drawable/btn_straight_larrow_dash.png b/app/src/main/res/drawable/btn_straight_larrow_dash.png
new file mode 100644 (file)
index 0000000..d1621cf
Binary files /dev/null and b/app/src/main/res/drawable/btn_straight_larrow_dash.png differ
diff --git a/app/src/main/res/drawable/btn_straight_rarrow.png b/app/src/main/res/drawable/btn_straight_rarrow.png
new file mode 100644 (file)
index 0000000..e706e4e
Binary files /dev/null and b/app/src/main/res/drawable/btn_straight_rarrow.png differ
diff --git a/app/src/main/res/drawable/btn_straight_rarrow_dash.png b/app/src/main/res/drawable/btn_straight_rarrow_dash.png
new file mode 100644 (file)
index 0000000..cc141a6
Binary files /dev/null and b/app/src/main/res/drawable/btn_straight_rarrow_dash.png differ
diff --git a/app/src/main/res/drawable/btn_trapezoidy_down.png b/app/src/main/res/drawable/btn_trapezoidy_down.png
new file mode 100644 (file)
index 0000000..2a8280d
Binary files /dev/null and b/app/src/main/res/drawable/btn_trapezoidy_down.png differ
diff --git a/app/src/main/res/drawable/btn_trapezoidy_up.png b/app/src/main/res/drawable/btn_trapezoidy_up.png
new file mode 100644 (file)
index 0000000..88c1722
Binary files /dev/null and b/app/src/main/res/drawable/btn_trapezoidy_up.png differ
diff --git a/app/src/main/res/drawable/btn_tree.png b/app/src/main/res/drawable/btn_tree.png
new file mode 100644 (file)
index 0000000..095b745
Binary files /dev/null and b/app/src/main/res/drawable/btn_tree.png differ
diff --git a/app/src/main/res/drawable/btn_tree_dash.png b/app/src/main/res/drawable/btn_tree_dash.png
new file mode 100644 (file)
index 0000000..20192d1
Binary files /dev/null and b/app/src/main/res/drawable/btn_tree_dash.png differ
diff --git a/app/src/main/res/drawable/btn_tree_larrow.png b/app/src/main/res/drawable/btn_tree_larrow.png
new file mode 100644 (file)
index 0000000..3f89606
Binary files /dev/null and b/app/src/main/res/drawable/btn_tree_larrow.png differ
diff --git a/app/src/main/res/drawable/btn_tree_larrow_dash.png b/app/src/main/res/drawable/btn_tree_larrow_dash.png
new file mode 100644 (file)
index 0000000..eb2b832
Binary files /dev/null and b/app/src/main/res/drawable/btn_tree_larrow_dash.png differ
diff --git a/app/src/main/res/drawable/btn_tree_rarrow.png b/app/src/main/res/drawable/btn_tree_rarrow.png
new file mode 100644 (file)
index 0000000..8a1286c
Binary files /dev/null and b/app/src/main/res/drawable/btn_tree_rarrow.png differ
diff --git a/app/src/main/res/drawable/btn_tree_rarrow_dash.png b/app/src/main/res/drawable/btn_tree_rarrow_dash.png
new file mode 100644 (file)
index 0000000..49806e7
Binary files /dev/null and b/app/src/main/res/drawable/btn_tree_rarrow_dash.png differ
diff --git a/app/src/main/res/drawable/circle_go.png b/app/src/main/res/drawable/circle_go.png
new file mode 100644 (file)
index 0000000..7723127
Binary files /dev/null and b/app/src/main/res/drawable/circle_go.png differ
diff --git a/app/src/main/res/drawable/home.png b/app/src/main/res/drawable/home.png
new file mode 100644 (file)
index 0000000..7915c7a
Binary files /dev/null and b/app/src/main/res/drawable/home.png differ
diff --git a/app/src/main/res/drawable/icon.png b/app/src/main/res/drawable/icon.png
new file mode 100644 (file)
index 0000000..efe5aff
Binary files /dev/null and b/app/src/main/res/drawable/icon.png differ
diff --git a/app/src/main/res/drawable/icon1.png b/app/src/main/res/drawable/icon1.png
new file mode 100644 (file)
index 0000000..6b6ddda
Binary files /dev/null and b/app/src/main/res/drawable/icon1.png differ
diff --git a/app/src/main/res/drawable/icon2.png b/app/src/main/res/drawable/icon2.png
new file mode 100644 (file)
index 0000000..2e73556
Binary files /dev/null and b/app/src/main/res/drawable/icon2.png differ
diff --git a/app/src/main/res/layout/confirmationdialog.xml b/app/src/main/res/layout/confirmationdialog.xml
new file mode 100644 (file)
index 0000000..8a44a8f
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/confirmation"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    >
+  <TextView  
+    android:id="@+id/confirm_message"
+    android:textSize="9pt"
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:gravity="top"
+    android:text="@string/blank"
+  />
+</LinearLayout>
diff --git a/app/src/main/res/layout/creditdialog.xml b/app/src/main/res/layout/creditdialog.xml
new file mode 100644 (file)
index 0000000..7517c9a
--- /dev/null
@@ -0,0 +1,17 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:id="@+id/info_about_gokigen"
+              android:orientation="horizontal"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent"
+              android:padding="10dp"
+              android:background="@color/color_black"
+              >
+
+    <TextView android:id="@+id/creditmessage"
+              android:layout_width="wrap_content"
+              android:layout_height="fill_parent"
+              android:autoLink="all"
+              android:linksClickable="true"
+              android:textColor="#FFF"
+              />
+</LinearLayout>
diff --git a/app/src/main/res/layout/extensionview.xml b/app/src/main/res/layout/extensionview.xml
new file mode 100644 (file)
index 0000000..85d5bf2
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:background="@color/mybackground_color"
+    android:id="@+id/gokigenGraphView"
+    >
+
+<TextView  
+    android:id="@+id/GokigenExtensionHeader"
+    android:textSize="8pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentTop="true"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/SetFilterButton"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentBottom="true"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true"
+    android:contentDescription="@string/blank"
+    android:background="@drawable/btn_filter"
+    android:text="@string/blank"
+    android:visibility="invisible"
+    >
+</ImageButton>
+
+<TextView  
+    android:id="@+id/SetFilterDetail"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignBottom="@id/SetFilterButton"
+    android:layout_toRightOf="@id/SetFilterButton"
+    android:layout_toEndOf="@id/SetFilterButton"
+    android:text="@string/blank"
+    />
+
+<ListView android:id="@+id/ExtensionView"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content" 
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true"
+    android:layout_below="@id/GokigenExtensionHeader"
+    android:layout_above="@id/SetFilterButton"
+    >
+</ListView>
+
+<!-- 
+<jp.sourceforge.gokigen.memoma.GokigenSurfaceView
+    android:id="@+id/ExtensionView"
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/GokigenExtensionHeader"
+    android:layout_above="@id/GokigenExtensionFooter"
+    />
+ -->
+
+</RelativeLayout>
diff --git a/app/src/main/res/layout/lineselection.xml b/app/src/main/res/layout/lineselection.xml
new file mode 100644 (file)
index 0000000..495f276
--- /dev/null
@@ -0,0 +1,560 @@
+<?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:id="@+id/selectline_dialog"
+    >
+<!-- android:background="#000040"  -->
+    
+<ScrollView
+    android:id="@+id/lineSelectView"
+    android:layout_width="wrap_content"
+    android:layout_height="fill_parent"
+    >
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView  
+    android:id="@+id/lineThicknessLabel"
+    android:textSize="8pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true"
+    android:layout_alignParentTop="true"
+    android:text="@string/labelLineThickness"
+    android:visibility="visible"
+    />
+<ImageButton
+    android:id="@+id/btnLineThicknessThin"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true"
+    android:contentDescription="@string/blank"
+    android:layout_below="@id/lineThicknessLabel"
+    android:background="@drawable/btn_line_thin"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineThicknessMiddle"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineThicknessThin"
+    android:layout_toEndOf="@id/btnLineThicknessThin"
+    android:layout_below="@id/lineThicknessLabel"
+    android:contentDescription="@string/blank"
+    android:background="@drawable/btn_line_middle"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineThicknessHeavy"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineThicknessMiddle"
+    android:layout_toEndOf="@id/btnLineThicknessMiddle"
+    android:layout_below="@id/lineThicknessLabel"
+    android:contentDescription="@string/blank"
+    android:background="@drawable/btn_line_heavy"
+    android:text="@string/blank"
+    />
+<ImageView
+    android:id="@+id/spacerLineSelection"
+    android:layout_width="12dp" 
+    android:layout_height="12dp" 
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true"
+    android:contentDescription="@string/blank"
+    android:layout_below="@id/btnLineThicknessThin"
+     >
+</ImageView>
+<TextView  
+    android:id="@+id/lineShapeSelectionLabel"
+    android:textSize="8pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/spacerLineSelection"
+    android:text="@string/labelLineShapeSelection"
+    android:visibility="visible"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeStraight"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/lineShapeSelectionLabel"
+    android:background="@drawable/btn_straight"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeTree"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeStraight"
+    android:layout_below="@id/lineShapeSelectionLabel"
+    android:background="@drawable/btn_tree"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeCurve"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeTree"
+    android:layout_below="@id/lineShapeSelectionLabel"
+    android:background="@drawable/btn_curve"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeStraightDash"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeCurve"
+    android:layout_below="@id/lineShapeSelectionLabel"
+    android:background="@drawable/btn_straight_dash"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeTreeDash"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeStraightDash"
+    android:layout_below="@id/lineShapeSelectionLabel"
+    android:background="@drawable/btn_tree_dash"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeCurveDash"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeTreeDash"
+    android:layout_below="@id/lineShapeSelectionLabel"
+    android:background="@drawable/btn_curve_dash"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnLineShapeStraightRarrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/btnLineShapeStraight"
+    android:background="@drawable/btn_straight_rarrow"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeTreeRarrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeStraightRarrow"
+    android:layout_below="@id/btnLineShapeStraight"
+    android:background="@drawable/btn_tree_rarrow"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeCurveRarrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeTreeRarrow"
+    android:layout_below="@id/btnLineShapeStraight"
+    android:background="@drawable/btn_curve_rarrow"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeStraightRarrowDash"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeCurveRarrow"
+    android:layout_below="@id/btnLineShapeStraight"
+    android:background="@drawable/btn_straight_rarrow_dash"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeTreeRarrowDash"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeStraightRarrowDash"
+    android:layout_toEndOf="@id/btnLineShapeStraightRarrowDash"
+    android:layout_below="@id/btnLineShapeStraight"
+    android:contentDescription="@string/blank"
+    android:background="@drawable/btn_tree_rarrow_dash"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnLineShapeCurveRarrowDash"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnLineShapeTreeRarrowDash"
+    android:layout_toEndOf="@id/btnLineShapeTreeRarrowDash"
+    android:contentDescription="@string/blank"
+    android:layout_below="@id/btnLineShapeStraight"
+    android:background="@drawable/btn_curve_rarrow_dash"
+    android:text="@string/blank"
+    />
+
+<!--
+<TextView  
+    android:id="@+id/setTextColorLabel"
+    android:textSize="8pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/descriptionInputArea"
+    android:text="@string/labelTextColor"
+    android:visibility="visible"
+    />
+
+<TextView
+    android:id="@+id/textColorArea"
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/setTextColorLabel"
+    android:layout_alignTop="@id/setTextColorLabel"
+    android:background="#ffffff" 
+    android:maxHeight="32dp"
+    android:maxWidth="32dp"
+    android:layout_width="32dp" 
+    android:layout_height="32dp" 
+    >
+</TextView>
+
+<SeekBar
+    android:id="@+id/textColorSelectionBar"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:max="63"
+    android:progress="63"
+    android:layout_alignTop="@id/textColorArea"
+    android:layout_toRightOf="@id/textColorArea"
+    />
+-->
+<!--
+<TextView  
+    android:id="@+id/setBorderColorLabel"
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_gravity="center_vertical"
+    android:textSize="7pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="32dp" 
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentTop="true"
+    android:text="@string/labelBorderColor"
+    android:background="@xml/bordershape"
+    android:maxHeight="32dp"
+    android:visibility="visible"
+    />
+
+<TextView
+    android:id="@+id/borderColorArea"
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/setBorderColorLabel"
+    android:layout_alignTop="@id/setBorderColorLabel"
+    android:background="#004000"
+    android:maxHeight="32dp"
+    android:maxWidth="32dp"
+    android:layout_width="32dp" 
+    android:layout_height="32dp" 
+    android:gravity="center"
+    >
+</TextView>
+
+<SeekBar
+    android:id="@+id/borderColorSelectionBar"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:max="63"
+    android:progress="63"
+    android:layout_alignTop="@id/borderColorArea"
+    android:layout_toRightOf="@id/borderColorArea"
+    />
+
+<CheckBox
+    android:id="@+id/checkBoldText"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/labelBoldText"
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/borderColorArea"
+    />
+
+<ImageView
+    android:id="@+id/spacerCheck"
+    android:layout_width="12dp" 
+    android:layout_height="12dp" 
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_toRightOf="@id/checkBoldText"
+    android:layout_below="@id/borderColorArea"
+     >
+</ImageView>
+
+<CheckBox
+    android:id="@+id/checkFillObject"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/labelFillBorder"
+    android:layout_toRightOf="@id/spacerCheck"
+    android:layout_below="@id/borderColorArea"
+    />
+
+<ImageView
+    android:id="@+id/spacerCheck2"
+    android:layout_width="12dp" 
+    android:layout_height="12dp" 
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_toRightOf="@id/checkFillObject"
+    android:layout_below="@id/borderColorArea"
+     >
+</ImageView>
+
+<CheckBox
+    android:id="@+id/checkUserCheckbox"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/userCheckboxString"
+    android:layout_toRightOf="@id/spacerCheck2"
+    android:layout_below="@id/borderColorArea"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectRectangle"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_rectangle"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectRoundRect"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectRectangle"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_roundrect"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectCircle"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectRoundRect"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_circle"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectOval"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectCircle"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_oval"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectDiamond"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectOval"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_diamond"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectHexagonal"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectDiamond"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_hexagonal"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectLoopStart"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectHexagonal"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_trapezoidy_up"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnObjectLoopEnd"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectLoopStart"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_trapezoidy_down"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectParallelogram"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_parallelogram"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectKeyboard"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectParallelogram"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_keyboard"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectPaper"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectKeyboard"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_paper"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectDrum"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectPaper"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_drum"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectNoRegion"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectDrum"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_noregion"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectLeftArrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectNoRegion"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_arrow_left"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnObjectDownArrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectLeftArrow"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_arrow_down"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnObjectUpArrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectDownArrow"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_arrow_up"
+    android:text="@string/blank"
+    />    
+<ImageButton
+    android:id="@+id/btnObjectRightArrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectUpArrow"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_arrow_right"
+    android:text="@string/blank"
+    />    
+-->
+</RelativeLayout>
+</ScrollView>
+</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..af7b3e5
--- /dev/null
@@ -0,0 +1,55 @@
+<?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"
+    >
+    <LinearLayout
+        android:id="@+id/ListArrayItemsLayout"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        >
+        <ImageView
+            android:id="@+id/ObjectStyleIcons"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:scaleType="fitCenter"
+            android:tag="icon"
+            android:layout_gravity="center_vertical"
+            android:contentDescription="@string/blank"
+            android:maxHeight="40dp"
+            android:minWidth="40dp">
+        </ImageView>
+        <ImageView
+            android:id="@+id/UserCheckedIcons"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:scaleType="fitCenter"
+            android:tag="subIcon"
+            android:layout_gravity="center_vertical"
+            android:contentDescription="@string/blank"
+            android:maxHeight="40dp"
+            android:minWidth="40dp">
+        </ImageView>
+        <TextView
+            android:textSize="8pt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/ObjectDataTitle"
+            android:tag="title"
+            android:maxWidth="230dp"
+            android:minWidth="230dp"
+            android:layout_gravity="left">
+        </TextView>
+        <TextView
+            android:textSize="6pt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/ObjectDataDetail"
+            android:tag="detail"
+            android:autoLink="all"
+            android:linksClickable="true"
+            android:layout_gravity="center_vertical">
+        </TextView>
+    </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/listdialog.xml b/app/src/main/res/layout/listdialog.xml
new file mode 100644 (file)
index 0000000..66a74a3
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/listdialog"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    >
+    <ListView android:id="@+id/ListDataFileName"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent" 
+     />
+</LinearLayout>
diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml
new file mode 100644 (file)
index 0000000..0d5903e
--- /dev/null
@@ -0,0 +1,193 @@
+<?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:layout_alignParentLeft="true"
+    android:layout_alignParentStart="true"
+    android:layout_alignParentTop="true"
+    android:background="#000040"
+    android:orientation="vertical">
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/gokigenMeMoMaView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:background="@color/mybackground_color">
+
+        <TextView
+            android:id="@+id/MeMoMaInfo"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true"
+            android:text="@string/blank"
+            android:textSize="9pt"
+            android:visibility="gone" />
+        <!--
+<ImageButton
+    android:id="@+id/SelectButton"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentBottom="true"
+    android:layout_alignParentLeft="true"
+    android:background="@xml/circlebuttonstyle"
+    android:text="@string/blank"
+    android:visibility="gone"
+    >
+</ImageButton>
+-->
+        <ImageButton
+            android:id="@+id/HomeButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:background="@drawable/home"
+            android:contentDescription="@string/blank"
+            android:text="@string/blank"
+            android:textSize="9pt"
+            android:visibility="visible"></ImageButton>
+        <!--
+<ImageView
+    android:id="@+id/spacerMain1"
+    android:layout_width="12dp" 
+    android:layout_height="12dp" 
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_toRightOf="@id/HomeButton"
+    android:layout_alignTop="@id/HomeButton"
+     >
+</ImageView>
+-->
+        <ImageButton
+            android:id="@+id/CreateObjectButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@id/HomeButton"
+            android:layout_toRightOf="@id/HomeButton"
+            android:background="@drawable/btn_create"
+            android:visibility="visible"></ImageButton>
+        <!--
+<ImageView
+    android:id="@+id/spacerMain2"
+    android:layout_width="12dp" 
+    android:layout_height="12dp" 
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_toRightOf="@id/CreateObjectButton"
+    android:layout_alignTop="@id/HomeButton"
+     >
+</ImageView>
+-->
+        <ImageButton
+            android:id="@+id/DeleteObjectButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@id/HomeButton"
+            android:layout_toRightOf="@id/CreateObjectButton"
+            android:background="@drawable/btn_delete"
+            android:visibility="visible"></ImageButton>
+        <!--
+<Button
+    android:id="@+id/ModeButton"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_toRightOf="@id/HomeButton"
+    android:layout_alignTop="@id/HomeButton"
+    android:background="@drawable/btn_noregion"
+    android:text="@string/blank"
+    android:visibility="visible"
+    >
+</Button>
+
+<ImageButton
+    android:id="@+id/ObjectStyleButton"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:background="@drawable/btn_noregion"
+    android:layout_toRightOf="@id/ModeButton"
+    android:layout_alignTop="@id/HomeButton"
+    android:visibility="visible"
+    >
+</ImageButton>
+-->
+        <!--
+<ImageView
+    android:id="@+id/spacerMain3"
+    android:layout_width="12dp" 
+    android:layout_height="12dp" 
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_toRightOf="@id/DeleteObjectButton"
+    android:layout_alignTop="@id/HomeButton"
+     >
+</ImageView>
+-->
+        <ImageButton
+            android:id="@+id/LineStyleButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@id/HomeButton"
+            android:layout_toRightOf="@id/DeleteObjectButton"
+            android:background="@drawable/btn_straight"
+            android:visibility="visible"></ImageButton>
+
+        <ImageButton
+            android:id="@+id/ExpandButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@id/HomeButton"
+            android:layout_toRightOf="@id/LineStyleButton"
+            android:background="@drawable/btn_sheet"
+            android:visibility="visible"></ImageButton>
+
+        <ImageButton
+            android:id="@+id/SaveButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:layout_alignParentRight="true"
+            android:background="@xml/savebuttonstyle"
+            android:text="@string/blank"
+            android:textSize="9pt"
+            android:visibility="visible"></ImageButton>
+
+        <TextView
+            android:id="@+id/ZoomRate"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignBottom="@id/SaveButton"
+            android:layout_toLeftOf="@id/SaveButton"
+            android:text="@string/defaultZoom"
+            android:textSize="9pt"
+            android:visibility="visible" />
+
+        <SeekBar
+            android:id="@+id/ZoomInOut"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@id/ExpandButton"
+            android:layout_toLeftOf="@id/ZoomRate"
+            android:layout_toStartOf="@id/ZoomRate"
+            android:layout_toRightOf="@id/ExpandButton"
+            android:layout_toEndOf="@id/ExpandButton"
+            android:max="100"
+            android:progress="50" />
+
+        <jp.sourceforge.gokigen.memoma.GokigenSurfaceView
+            android:id="@+id/GraphicView"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_above="@id/SaveButton"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:layout_below="@id/MeMoMaInfo" />
+    </RelativeLayout>
+</LinearLayout>
+
diff --git a/app/src/main/res/layout/messagedialog.xml b/app/src/main/res/layout/messagedialog.xml
new file mode 100644 (file)
index 0000000..89fe33e
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/layout_root"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    >
+    <EditText
+        android:id="@+id/editTextArea"
+        android:layout_width="fill_parent" 
+        android:layout_height="wrap_content" 
+        android:tag="revisedText"
+        android:hint="@string/blank"
+        android:gravity="top"
+        android:lines="10"
+    />
+</LinearLayout>
diff --git a/app/src/main/res/layout/objectinput.xml b/app/src/main/res/layout/objectinput.xml
new file mode 100644 (file)
index 0000000..d08df7c
--- /dev/null
@@ -0,0 +1,418 @@
+<?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:id="@+id/objectinput_dialog"
+    >
+<!-- android:background="#000040"  -->
+    
+<ScrollView
+    android:id="@+id/objectInputView"
+    android:layout_width="wrap_content"
+    android:layout_height="fill_parent"
+    >
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<!--
+<Button
+    android:id="@+id/objectInputCancel"
+    android:textSize="11pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentRight="true"
+    android:layout_alignParentBottom="true"
+    android:text="@string/confirmNo"
+    >
+</Button>
+
+<Button
+    android:id="@+id/objectInputAccept"
+    android:textSize="11pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_toLeftOf="@id/objectInputCancel"
+    android:layout_alignParentBottom="true"
+    android:text="@string/confirmYes"
+    >
+</Button>
+-->
+
+<ImageView
+    android:id="@+id/iconArea"
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_gravity="center_vertical"
+    android:layout_alignParentLeft="true"
+    android:maxHeight="48dp"
+    android:maxWidth="48dp"
+    android:layout_width="36dp" 
+    android:layout_height="36dp" 
+    >
+</ImageView>
+    
+<EditText
+    android:id="@+id/labelInputArea"
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:layout_toRightOf="@id/iconArea"
+    android:layout_alignTop="@id/iconArea"
+    android:hint="@string/hintMessageLabel"
+    android:singleLine="true"
+    android:gravity="top"
+    android:lines="1"
+/>
+
+<ImageView
+    android:id="@+id/cameraView"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_below="@id/labelInputArea"
+    android:layout_alignParentLeft="true"
+    >
+</ImageView>
+
+<EditText
+    android:id="@+id/descriptionInputArea"
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/cameraView"
+    android:hint="@string/hintMessageInput"
+    android:gravity="top"
+    android:lines="5"
+/>
+<!--
+<TextView  
+    android:id="@+id/setTextColorLabel"
+    android:textSize="8pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/descriptionInputArea"
+    android:text="@string/labelTextColor"
+    android:visibility="visible"
+    />
+
+<TextView
+    android:id="@+id/textColorArea"
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/setTextColorLabel"
+    android:layout_alignTop="@id/setTextColorLabel"
+    android:background="#ffffff" 
+    android:maxHeight="32dp"
+    android:maxWidth="32dp"
+    android:layout_width="32dp" 
+    android:layout_height="32dp" 
+    >
+</TextView>
+
+<SeekBar
+    android:id="@+id/textColorSelectionBar"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:max="63"
+    android:progress="63"
+    android:layout_alignTop="@id/textColorArea"
+    android:layout_toRightOf="@id/textColorArea"
+    />
+-->
+<TextView  
+    android:id="@+id/setBorderColorLabel"
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_gravity="center_vertical"
+    android:textSize="7pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="32dp" 
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/descriptionInputArea"
+    android:text="@string/labelBorderColor"
+    android:background="@xml/bordershape"
+    android:maxHeight="32dp"
+    android:visibility="visible"
+    />
+
+<TextView
+    android:id="@+id/borderColorArea"
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/setBorderColorLabel"
+    android:layout_alignTop="@id/setBorderColorLabel"
+    android:background="#004000"
+    android:maxHeight="32dp"
+    android:maxWidth="32dp"
+    android:layout_width="32dp" 
+    android:layout_height="32dp" 
+    android:gravity="center"
+    >
+</TextView>
+
+<SeekBar
+    android:id="@+id/borderColorSelectionBar"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:max="63"
+    android:progress="63"
+    android:layout_alignTop="@id/borderColorArea"
+    android:layout_toRightOf="@id/borderColorArea"
+    />
+
+<CheckBox
+    android:id="@+id/checkBoldText"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/labelBoldText"
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/borderColorArea"
+    />
+
+<ImageView
+    android:id="@+id/spacerCheck"
+    android:layout_width="12dp" 
+    android:layout_height="12dp" 
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_toRightOf="@id/checkBoldText"
+    android:layout_below="@id/borderColorArea"
+     >
+</ImageView>
+
+<CheckBox
+    android:id="@+id/checkFillObject"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/labelFillBorder"
+    android:layout_toRightOf="@id/spacerCheck"
+    android:layout_below="@id/borderColorArea"
+    />
+
+<ImageView
+    android:id="@+id/spacerCheck2"
+    android:layout_width="12dp" 
+    android:layout_height="12dp" 
+    android:adjustViewBounds = "true"
+    android:scaleType="fitCenter"
+    android:layout_toRightOf="@id/checkFillObject"
+    android:layout_below="@id/borderColorArea"
+     >
+</ImageView>
+
+<CheckBox
+    android:id="@+id/checkUserCheckbox"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/userCheckboxString"
+    android:layout_toRightOf="@id/spacerCheck2"
+    android:layout_below="@id/borderColorArea"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectRectangle"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_rectangle"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectRoundRect"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectRectangle"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_roundrect"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectCircle"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectRoundRect"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_circle"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectOval"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectCircle"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_oval"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectDiamond"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectOval"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_diamond"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectHexagonal"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectDiamond"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_hexagonal"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectLoopStart"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectHexagonal"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_trapezoidy_up"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnObjectLoopEnd"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectLoopStart"
+    android:layout_below="@id/checkBoldText"
+    android:background="@drawable/btn_trapezoidy_down"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectParallelogram"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_alignParentLeft="true"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_parallelogram"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectKeyboard"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectParallelogram"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_keyboard"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectPaper"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectKeyboard"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_paper"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectDrum"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectPaper"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_drum"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectNoRegion"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectDrum"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_noregion"
+    android:text="@string/blank"
+    />
+
+<ImageButton
+    android:id="@+id/btnObjectLeftArrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectNoRegion"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_arrow_left"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnObjectDownArrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectLeftArrow"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_arrow_down"
+    android:text="@string/blank"
+    />
+<ImageButton
+    android:id="@+id/btnObjectUpArrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectDownArrow"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_arrow_up"
+    android:text="@string/blank"
+    />    
+<ImageButton
+    android:id="@+id/btnObjectRightArrow"
+    android:textSize="9pt"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:layout_gravity="center_vertical"
+    android:layout_toRightOf="@id/btnObjectUpArrow"
+    android:layout_below="@id/btnObjectRectangle"
+    android:background="@drawable/btn_arrow_right"
+    android:text="@string/blank"
+    />    
+</RelativeLayout>
+</ScrollView>
+</LinearLayout>
diff --git a/app/src/main/res/layout/preference.xml b/app/src/main/res/layout/preference.xml
new file mode 100644 (file)
index 0000000..102e56b
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+    <PreferenceCategory android:title="@string/userCheckbox">
+        <EditTextPreference
+            android:key="userCheckboxString"
+            android:title="@string/userCheckboxTitle"
+            android:summary="@string/userCheckboxSummary"
+            android:dialogTitle="@string/userCheckboxTitle"
+        />
+    </PreferenceCategory>
+    <PreferenceCategory android:title="@string/backgroundPreferences">
+        <EditTextPreference
+            android:key="backgroundUri"
+            android:title="@string/backgroundViewTitle"
+            android:summary="@string/backgroundViewSummary"
+            android:dialogTitle="@string/backgroundViewTitle"
+        />
+        <EditTextPreference
+            android:key="backgroundColor"
+            android:title="@string/backgroundColorTitle"
+            android:summary="@string/backgroundColorSummary"
+            android:dialogTitle="@string/backgroundColorTitle"
+        />
+    </PreferenceCategory>
+    <PreferenceCategory android:title="@string/parameterTitle">
+        <ListPreference
+            android:key="objectPrintData"
+            android:title="@string/objectPrintData_title"
+            android:summary="@string/objectPrintData_summary"
+            android:dialogTitle="@string/objectPrintData_title"
+            android:entries="@array/printData_entries"
+            android:entryValues="@array/printData_entryvalues" />
+        <ListPreference
+            android:key="operationMode"
+            android:title="@string/operationMode_title"
+            android:summary="@string/operationMode_summary"
+            android:dialogTitle="@string/operationMode_title"
+            android:entries="@array/operationMode_entries"
+            android:entryValues="@array/operationMode_entryvalues" />
+    </PreferenceCategory>
+</PreferenceScreen>
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..c03600e
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+   <string-array name="printData_entries">
+        <item>中心(長いと省略)</item>
+        <item>すべて表示</item>
+    </string-array>
+    <string-array name="printData_entryvalues">
+        <item>0</item>
+        <item>1</item>
+    </string-array>
+    <string-array name="operationMode_entries">
+        <item>作成</item>
+        <item>削除</item>
+        <item>移動</item>
+    </string-array>
+    <string-array name="operationMode_entryvalues">
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+    </string-array>
+    <string-array name="drawStyle_entries">
+        <item>四角形</item>
+        <item>角丸四角形</item>
+        <item>楕円形</item>
+        <item>菱形</item>
+        <item>三角形</item>
+        <item>(枠なし)</item>
+    </string-array>
+    <string-array name="drawStyle_entryvalues">
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+        <item>5</item>
+    </string-array>
+    <string-array name="lineStyle_entries">
+        <item>直線形式</item>
+        <item>ツリー形式</item>
+    </string-array>
+    <string-array name="lineStyle_entryvalues">
+        <item>0</item>
+        <item>1</item>
+    </string-array>
+</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..1e1af1d
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="blank"> </string>
+    <string name="app_credit">An idea planner\n http://sourceforge.jp/projects/gokigen/wiki/MeMoMa</string>
+    <string name="app_name">めもま</string>
+    <string name="extent_name">その他</string>
+    <string name="createnew">新規作成</string>
+    <string name="createnew_title">破棄確認</string>
+    <string name="createnew_message">現在までの変更を破棄して、初期状態に戻します。よろしいですか?</string>
+    <string name="deleteconfirm_title">削除確認</string>
+    <string name="deleteconfirm_message">削除します。よろしいですか?</string>
+    <string name="extend_menu">その他&#8230;</string>
+    <string name="rename_title">タイトル変更&#8230;</string>
+    <string name="load_data">読込&#8230;</string>
+    <string name="save_data">保存&#8230;</string>
+    <string name="align_data">整列&#8230;</string>
+    <string name="capture_data">キャプチャ&#8230;</string>
+    <string name="export_csv">CSV形式で保存&#8230;</string>
+    <string name="import_csv">CSVファイルから追加&#8230;</string>
+    <string name="background_data">背景画像&#8230;</string>
+   <string name="dialogtitle_selectcsv">追加するCSVファイルを選択</string>
+    <string name="about_gokigen">情報</string>
+    <string name="shareContent">共有</string>
+    <string name="dataTitle">タイトル</string>
+    <string name="hintFileName">ファイル名を入力</string>
+    <string name="hintMessageLabel">見出しを入力</string>
+    <string name="hintMessageInput">詳細情報を入力</string>
+    <string name="labelTextColorSample">ab</string>
+    <string name="labelBorderColor">色</string>
+    <string name="labelBoldText">強調表示</string>
+    <string name="labelFillBorder">塗りつぶし</string>
+    <string name="dataLoading">ロード中&#8230;</string>
+    <string name="dataSaving">保存中&#8230;</string>
+    <string name="dataAligning">整列中&#8230;</string>
+    <string name="dataImporting">データインポート中&#8230;</string>
+    <string name="info_default">(Gokigen)</string>
+    <string name="defaultZoom">x1.0</string>
+    <string name="preference_name">設定</string>
+    <string name="userCheckbox">ユーザ定義データ</string>
+    <string name="useUserCheckboxTitle">ユーザ定義チェックボックス</string>
+    <string name="useUserCheckboxSummary">ユーザ定義チェックボックスを使う</string>
+    <string name="userCheckboxTitle">ユーザ定義チェックボックスのタイトル</string>
+    <string name="userCheckboxSummary">チェック時に表示する文字列</string>
+    <string name="userCheckboxString"> </string>
+    <string name="parameterTitle">設定項目</string>
+    <string name="backgroundPreferences">背景の設定</string>
+    <string name="backgroundViewTitle">背景画像(URI)</string>
+    <string name="backgroundViewSummary">背景画像のURI</string>
+    <string name="backgroundColorTitle">背景色</string>
+    <string name="backgroundColorSummary">背景色を文字列で指定(背景画像設定時には無効)</string>
+    <string name="operationMode_title">操作モード</string>
+    <string name="operationMode_summary">現在の操作モード</string>
+    <string name="drawStyle_title">オブジェクト形状</string>
+    <string name="drawStyle_summary">表示するオブジェクトの形状</string>
+    <string name="lineStyle_title">ライン形状</string>
+    <string name="lineStyle_summary">オブジェクトを接続するラインの形状</string>
+    <string name="objectPrintData_title">オブジェクトの見出し</string>
+    <string name="objectPrintData_summary">オブジェクト見出しの表示方法</string>
+    <string name="object_operation">操作</string>
+    <string name="object_delete">削除</string>
+    <string name="object_duplicate">複製</string>
+    <string name="object_bigger">サイズ拡大</string>
+    <string name="object_smaller">サイズ縮小</string>
+    <string name="object_bringtop">最前面にする</string>
+    <string name="object_small_limit">これ以上縮小できません</string>
+    <string name="object_bigger_limit">これ以上拡大できません</string>
+    <string name="confirmYes">OK</string>
+    <string name="confirmNo">Cancel</string>
+    <string name="dummyData"> </string>
+    <string name="no_name">(無題)</string>
+    <string name="labelLineThickness">太さ</string>
+    <string name="labelLineShapeSelection">形状</string>
+    <string name="Title_SelectLineShape">接続線の設定</string>
+</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..d20473f
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+   <string-array name="printData_entries">
+        <item>Title - Summary</item>
+        <item>Title - All</item>
+    </string-array>
+    <string-array name="printData_entryvalues">
+        <item>0</item>
+        <item>1</item>
+    </string-array>
+    <string-array name="operationMode_entries">
+        <item>Create</item>
+        <item>Delete</item>
+        <item>Move</item>
+    </string-array>
+    <string-array name="operationMode_entryvalues">
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+    </string-array>
+    <string-array name="drawStyle_entries">
+        <item>Rectangle</item>
+        <item>RoundRect</item>
+        <item>Oval</item>
+        <item>Diamond</item>
+        <item>Triangle</item>
+        <item>(no region)</item>
+    </string-array>
+    <string-array name="drawStyle_entryvalues">
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+        <item>5</item>
+    </string-array>
+    <string-array name="lineStyle_entries">
+        <item>Straight</item>
+        <item>Tree</item>
+    </string-array>
+    <string-array name="lineStyle_entryvalues">
+        <item>0</item>
+        <item>1</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..d8ef861
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources> 
+    <drawable name="mybackground_color">#004000</drawable>
+    <drawable name="color_black">#000000</drawable>
+
+    <color name="mybackground_color">#004000</color>
+    <color name="color_black">#000000</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..e488800
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="blank"> </string>
+    <string name="app_credit">An idea planner\n web site: "http://bit.ly/A8c8yv"</string>
+    <string name="app_name">MeMoMa</string>
+    <string name="extent_name">Etc</string>
+    <string name="createnew">New</string>
+    <string name="createnew_title">Discard confirmation</string>
+    <string name="createnew_message">Discard all changes, OK?</string>
+    <string name="deleteconfirm_title">Deleting confirmation</string>
+    <string name="deleteconfirm_message">Delete OK?</string>
+    <string name="extend_menu">Etc&#8230;</string>
+    <string name="rename_title">Rename Title&#8230;</string>
+    <string name="load_data">Load&#8230;</string>
+    <string name="save_data">Save&#8230;</string>
+    <string name="align_data">Align&#8230;</string>
+    <string name="capture_data">Capture&#8230;</string>
+    <string name="export_csv">Export as CSV&#8230;</string>
+    <string name="import_csv">Append from CSV&#8230;</string>
+    <string name="background_data">Select Background&#8230;</string>
+    <string name="dialogtitle_selectcsv">Select a CSV to append</string>
+    <string name="about_gokigen">About</string>
+    <string name="shareContent">Share</string>
+    <string name="dataTitle">Title</string>
+    <string name="hintFileName">Input File Name</string>
+    <string name="hintMessageLabel">Input Label</string>
+    <string name="hintMessageInput">Input Detail</string>
+    <string name="labelTextColorSample">ab</string>
+    <string name="labelBorderColor">Color</string>
+    <string name="labelBoldText">Bold</string>
+    <string name="labelFillBorder">Fill </string>
+    <string name="dataLoading">Loading&#8230;</string>
+    <string name="dataSaving">Saving&#8230;</string>
+    <string name="dataAligning">Aligning&#8230;</string>
+    <string name="dataImporting">Importing&#8230;</string>
+    <string name="info_default">(Gokigen)</string>
+    <string name="defaultZoom">x1.0</string>
+    <string name="preference_name">Preferences</string>
+    <string name="parameterTitle">preferences</string>
+    <string name="backgroundPreferences">Background Settings</string>
+    <string name="userCheckbox">Custom data</string>
+    <string name="useUserCheckboxTitle">use user check box</string>
+    <string name="useUserCheckboxSummary"> </string>
+    <string name="userCheckboxTitle">user check box title</string>
+    <string name="userCheckboxSummary"> </string>
+    <string name="userCheckboxString"> </string>
+    <string name="backgroundViewTitle">background URI</string>
+    <string name="backgroundViewSummary">Set background picture URI.</string>
+    <string name="backgroundColorTitle">background color</string>
+    <string name="backgroundColorSummary">Set background color.</string>
+    <string name="operationMode_title">Operation Mode</string>
+    <string name="operationMode_summary"> </string>
+    <string name="drawStyle_title">Object Style</string>
+    <string name="drawStyle_summary"> </string>
+    <string name="lineStyle_title">Line Style</string>
+    <string name="lineStyle_summary"> </string>
+    <string name="objectPrintData_title">Object label</string>
+    <string name="objectPrintData_summary"> </string>
+    <string name="object_operation">Operations</string>
+    <string name="object_delete">Delete</string>
+    <string name="object_duplicate">Duplicate</string>
+    <string name="object_bigger">Expand</string>
+    <string name="object_smaller">Shrink</string>
+    <string name="object_bringtop">Bring to top</string>
+    <string name="object_small_limit">Cannot shrink</string>
+    <string name="object_bigger_limit">Cannot expand</string>
+    <string name="confirmYes">OK</string>
+    <string name="confirmNo">Cancel</string>
+    <string name="dummyData"> </string>
+    <string name="no_name">(no name)</string>
+    <string name="labelLineThickness">Line Thickness</string>
+    <string name="labelLineShapeSelection">Line Shape</string>
+    <string name="Title_SelectLineShape">Select a line style</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..00e52ab
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+<!-- アプリケーションのウィンドウタイトルのスタイルを設定する  -->
+<style name="WindowTitle">  
+    <item name="android:singleLine">true</item>
+</style>
+
+</resources>
diff --git a/app/src/main/res/xml/bordershape.xml b/app/src/main/res/xml/bordershape.xml
new file mode 100644 (file)
index 0000000..eb15c63
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">  
+    <stroke android:width="1px" android:color="#ffffff" />  
+    <padding android:left="3dp" android:top="3dp"  
+            android:right="3dp" android:bottom="3dp" />
+</shape>
diff --git a/app/src/main/res/xml/circlebuttonstyle.xml b/app/src/main/res/xml/circlebuttonstyle.xml
new file mode 100644 (file)
index 0000000..d4f6ef7
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/btn_circle_pressed"
+    />
+    <item
+        android:state_focused="true"
+        android:drawable="@drawable/btn_circle_selected"
+    />
+    <item
+        android:drawable="@drawable/btn_circle_normal"
+    />
+</selector>
diff --git a/app/src/main/res/xml/savebuttonstyle.xml b/app/src/main/res/xml/savebuttonstyle.xml
new file mode 100644 (file)
index 0000000..2593900
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/btn_save_pressed"
+    />
+    <item
+        android:state_focused="true"
+        android:drawable="@drawable/btn_save_selected"
+    />
+    <item
+        android:drawable="@drawable/btn_save_normal"
+    />
+</selector>
diff --git a/build.gradle b/build.gradle
new file mode 100644 (file)
index 0000000..09eedbb
--- /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()
+        google()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.1.3'
+    }
+}
+
+allprojects {
+    repositories {
+        jcenter()
+        maven {
+            url "https://maven.google.com"
+        }
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/settings.gradle b/settings.gradle
new file mode 100644 (file)
index 0000000..e7b4def
--- /dev/null
@@ -0,0 +1 @@
+include ':app'