فهرست منبع

Merge remote-tracking branch 'origin/master'

cooperku_kdanmobile 6 سال پیش
والد
کامیت
b2dd097b3b
30فایلهای تغییر یافته به همراه822 افزوده شده و 76 حذف شده
  1. 6 2
      src/main/AndroidManifest.xml
  2. 124 0
      src/main/java/com/bomostory/sceneeditmodule/ChooseThemeActivity.kt
  3. 3 0
      src/main/java/com/bomostory/sceneeditmodule/Config.kt
  4. 1 0
      src/main/java/com/bomostory/sceneeditmodule/SceneDrawer.kt
  5. 74 10
      src/main/java/com/bomostory/sceneeditmodule/SceneEditActivity.kt
  6. 8 0
      src/main/java/com/bomostory/sceneeditmodule/basicdata/OtherThemes.kt
  7. 1 1
      src/main/java/com/bomostory/sceneeditmodule/basicdata/Project.kt
  8. 9 0
      src/main/java/com/bomostory/sceneeditmodule/basicdata/Theme.kt
  9. 5 0
      src/main/java/com/bomostory/sceneeditmodule/basicdata/ThemeActorResource.kt
  10. 9 0
      src/main/java/com/bomostory/sceneeditmodule/cover/CoverColorSelectorView.kt
  11. 49 1
      src/main/java/com/bomostory/sceneeditmodule/cover/CoverEditorDialog.kt
  12. 14 0
      src/main/java/com/bomostory/sceneeditmodule/cover/FrontCoverEditorView.kt
  13. 172 0
      src/main/java/com/bomostory/sceneeditmodule/cover/FrontCoverSceneChooserView.kt
  14. 5 51
      src/main/java/com/bomostory/sceneeditmodule/navigationbar/actor/ActorAdapter.kt
  15. 3 3
      src/main/java/com/bomostory/sceneeditmodule/navigationbar/actor/ActorPoseAdapter.kt
  16. 4 2
      src/main/java/com/bomostory/sceneeditmodule/navigationbar/scene/SceneAdapter.kt
  17. 53 0
      src/main/java/com/bomostory/sceneeditmodule/screen/movie/MovieEditActivity.kt
  18. 24 0
      src/main/java/com/bomostory/sceneeditmodule/screen/movie/MovieEditViewModel.kt
  19. 5 1
      src/main/java/com/bomostory/sceneeditmodule/screen/view/MovieSelectView.kt
  20. 6 1
      src/main/java/com/bomostory/sceneeditmodule/utils/FileUtils.kt
  21. 2 2
      src/main/java/com/bomostory/sceneeditmodule/utils/Utils.kt
  22. 32 0
      src/main/res/layout/activity_choose_theme.xml
  23. 10 0
      src/main/res/layout/dialog_cover_editor.xml
  24. 1 1
      src/main/res/layout/dialog_export_pdf.xml
  25. 1 1
      src/main/res/layout/item_actor.xml
  26. 41 0
      src/main/res/layout/item_front_cover_scene_chooser.xml
  27. 21 0
      src/main/res/layout/theme_page_view.xml
  28. 1 0
      src/main/res/layout/view_front_cover_editor.xml
  29. 134 0
      src/main/res/layout/view_front_cover_scene_chooser.xml
  30. 4 0
      src/main/res/values/strings.xml

+ 6 - 2
src/main/AndroidManifest.xml

@@ -12,12 +12,16 @@
         android:theme="@style/AppTheme">
         <activity
             android:name=".SceneEditActivity"
-            android:screenOrientation="landscape"></activity>
+            android:screenOrientation="landscape" />
         <activity
             android:name="com.bomostory.sceneeditmodule.screen.movie.MovieEditActivity"
             android:configChanges="orientation|keyboardHidden|screenSize"
+            android:label="@string/title_activity_movie_edit"
+            android:screenOrientation="landscape" />
+        <activity
+            android:name="com.bomostory.sceneeditmodule.ChooseThemeActivity">
             android:screenOrientation="landscape"
-            android:label="@string/title_activity_movie_edit" />
+        </activity>
     </application>
 
 </manifest>

+ 124 - 0
src/main/java/com/bomostory/sceneeditmodule/ChooseThemeActivity.kt

@@ -0,0 +1,124 @@
+package com.bomostory.sceneeditmodule
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.drawable.Drawable
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+import android.support.v4.view.PagerAdapter
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import com.bomostory.sceneeditmodule.basicdata.OtherThemes
+import com.example.tfat.myapplication.R
+import com.google.gson.Gson
+import kotlinx.android.synthetic.main.activity_choose_theme.*
+import android.widget.LinearLayout
+import kotlinx.android.synthetic.main.theme_page_view.view.*
+import android.view.ViewGroup
+import com.bomostory.sceneeditmodule.basicdata.ThemeActorResource
+import com.example.tfat.myapplication.SceneEditActivity
+
+
+class ChooseThemeActivity : AppCompatActivity() {
+
+    private lateinit var otherThemes: OtherThemes
+    private var pageList = ArrayList<ThemePageView>()
+    private var resourceObjectPath = ArrayList<String>()
+    private var resourceActorPath = ThemeActorResource()
+    private var coverPath = ArrayList<String>()
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_choose_theme)
+        otherThemes = Gson().fromJson<OtherThemes>(intent.getStringExtra("other_theme"), OtherThemes::class.java)
+        for (i in 0 until otherThemes.themes.size) {
+            var theme = otherThemes.themes[i]
+            val path = "${theme.assetFolder.path}/${theme.themeAssetIndex.largeFile}"
+            coverPath.add(path)
+        }
+        for (i in 0 until coverPath.size)  {
+            var themePageView = ThemePageView(this).apply {
+                iv_themePageView_cover.setImageDrawable(Drawable.createFromPath(coverPath[i]))
+                iv_themePageView_cover.setOnClickListener {
+                    resourceActorPath.actorPath = ArrayList<ArrayList<String>>().apply {
+                        otherThemes.themes[i].themeAssetIndex.contains.actor.forEach {
+                            add(ArrayList<String>().apply {
+                                it.value.values.forEach {
+                                    val path = "${otherThemes.themes[i].assetFolder.path}/${it.smallFile}"
+                                    add(path)
+                                }
+                            })
+                        }
+                    }
+                    resourceObjectPath = java.util.ArrayList<String>().apply {
+                        otherThemes.themes[i].themeAssetIndex.contains.obj.values.forEach {
+                            val path = "${otherThemes.themes[i].assetFolder.path}/${it.smallFile}"
+                            add(path)
+                        }
+                    }
+                    val intent = Intent(this@ChooseThemeActivity, SceneEditActivity::class.java).apply {
+                        putExtra("project", intent.getStringExtra("project"))
+                        putExtra("other_theme", Gson().toJson(otherThemes))
+                        putExtra("resource_actor", Gson().toJson(resourceActorPath))
+                        putStringArrayListExtra("resource_object", resourceObjectPath)
+                    }
+                    startActivity(intent)
+                    finish()
+                }
+            }
+            pageList.add(themePageView)
+        }
+        viewPager_newStory.adapter =  SamplePagerAdapter(pageList)
+    }
+    override fun onResume() {
+        super.onResume()
+        window.decorView.apply {
+            systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    or View.SYSTEM_UI_FLAG_FULLSCREEN
+                    or View.SYSTEM_UI_FLAG_LOW_PROFILE
+                    or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+        }
+    }
+
+    private class SamplePagerAdapter(pageList: ArrayList<ThemePageView>) : PagerAdapter() {
+        var pageList = pageList
+
+        override fun getCount(): Int {
+            return pageList.size
+        }
+        override fun isViewFromObject(p0: View, p1: Any): Boolean {
+            return p1 == p0
+        }
+
+        override fun instantiateItem(container: ViewGroup, position: Int): Any {
+            container.addView(pageList[position])
+            return pageList[position]
+        }
+
+        override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
+            container.removeView(`object` as View)
+        }
+    }
+    private class ThemePageView : LinearLayout {
+
+        constructor(context: Context) : super(context) {
+            initView()
+        }
+
+        constructor(context: Context, attrs: AttributeSet): super(context, attrs) {
+            initView()
+        }
+
+        constructor(context: Context, attrs: AttributeSet, defStyle: Int): super(context, attrs, defStyle) {
+            initView()
+        }
+
+        private fun initView() {
+            val inflater = LayoutInflater.from(context)
+            inflater.inflate(R.layout.theme_page_view, this, true)
+        }
+    }
+}

+ 3 - 0
src/main/java/com/bomostory/sceneeditmodule/Config.kt

@@ -15,4 +15,7 @@ object Config {
     val PDF_FOLDER = File(ROOT, "pdf")
 
     const val VIDEO_FILE_NAME = "video.mp4"
+    const val PROJECT_WHITE_FILE_NAME = "/white.png"
+
+    const val COVER_FILE_NAME = "cover.png"
 }

+ 1 - 0
src/main/java/com/bomostory/sceneeditmodule/SceneDrawer.kt

@@ -16,6 +16,7 @@ object SceneDrawer {
         scene?.apply {
             sceneBitmap = BitmapFactory.decodeFile(backgroundPath)
             sceneBitmap = Bitmap.createScaledBitmap(sceneBitmap, scaleWidth, scaleHeight, true)
+            sceneBitmap = sceneBitmap?.copy(Bitmap.Config.ARGB_4444, true)
 
             val canvas = Canvas(sceneBitmap)
             for (layer in layers) {

+ 74 - 10
src/main/java/com/bomostory/sceneeditmodule/SceneEditActivity.kt

@@ -6,6 +6,7 @@ import android.content.Context
 import android.content.DialogInterface
 import android.content.Intent
 import android.graphics.Bitmap
+import android.graphics.Paint
 import android.os.Bundle
 import android.support.v7.app.AppCompatActivity
 import android.support.v7.widget.LinearLayoutManager
@@ -63,6 +64,7 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
         BrushView.OnSelectBrush {
 
     private lateinit var project: Project
+    private lateinit var otherThemes: OtherThemes
     private var currentSceneIndex = 0
     private var currentLayerIndex = 6
     private var startRecordTime = 0L
@@ -91,7 +93,6 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
         const val ACTOR_INIT_POSITION_Y = 200
         const val BACKGROUND_MOVE_RATE = 32
         const val BRUSH_SIZE = 16
-        const val INIT_SCENE_NUMBER = 11
         const val TIME_STEP_FOR_FPS = 33L
         val listeners = CopyOnWriteArrayList<Runnable>()
     }
@@ -104,13 +105,26 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
         actionBar?.hide()
         supportActionBar?.hide()
         project = Gson().fromJson<Project>(intent.getStringExtra("project"), Project::class.java)
+        otherThemes = when(intent.getStringExtra("other_theme")){
+            null -> OtherThemes()
+            else -> Gson().fromJson<OtherThemes>(intent.getStringExtra("other_theme"), OtherThemes::class.java)
+        }
         resourceThemeBitmap = project.sceneResource as ArrayList<String>
-        resourceActorBitmap = project.actorResource as ArrayList<ArrayList<String>>
-        resourceObjectPath = ArrayList<String>().apply {
-            project.themeAssetIndex.contains.obj.values.forEach {
-                val path = "${project.assetFolder.path}/${it.smallFile}"
-                add(path)
+        resourceThemeBitmap.add(File(Config.ASSETS_FOLDER, Config.PROJECT_WHITE_FILE_NAME).path)
+        resourceActorBitmap = when(intent.getStringExtra("resource_actor")) {
+            null -> { project.actorResource as ArrayList<ArrayList<String>>}
+            else -> { Gson().fromJson<ThemeActorResource>(intent.getStringExtra("resource_actor"), ThemeActorResource::class.java).actorPath}
+        }
+        resourceObjectPath = when(intent.getStringArrayListExtra("resource_object")) {
+            null -> {
+                ArrayList<String>().apply {
+                    project.themeAssetIndex.contains.obj.values.forEach {
+                        val path = "${project.assetFolder.path}/${it.smallFile}"
+                        add(path)
+                    }
+                }
             }
+            else -> {intent.getStringArrayListExtra("resource_object")}
         }
         windowManager.defaultDisplay.getMetrics(monitorSize)
         var layoutPrams = sceneEditView.layoutParams
@@ -205,7 +219,11 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
     private fun initNavigationBarView(position: Int) {
         project.story?.let {
             it.scenes?.let {
-                if (position != currentSceneIndex) {
+                var isSceneRecorded =  when(it[currentSceneIndex].record){
+                                           null -> false
+                                           else -> true
+                                       }
+                if (position != currentSceneIndex && !isSceneRecorded) {
                     initNavigationFunction()
                 } else {
                     navigationBar.removeAllViews()
@@ -213,7 +231,7 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
                     navigationBar.addView(editSceneView)
                     setControlSceneView()
                     editSceneView.setOnClickDoneListener(View.OnClickListener {
-                        initNavigationFunction()
+                        if (!isSceneRecorded) initNavigationFunction()
                     })
                     editSceneView.setOnClickStartOverListener(View.OnClickListener {
                         project.story?.let {
@@ -411,6 +429,15 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
                 initActorRecyclerView()
             }
         }
+        selectActorView.btn_choose_theme.setOnClickListener {
+            if (!otherThemes.themes.isEmpty()) {
+                var intent = Intent(this, ChooseThemeActivity::class.java)
+                intent.putExtra("project", Gson().toJson(project))
+                intent.putExtra("other_theme", Gson().toJson(otherThemes))
+                startActivity(intent)
+                finish()
+        }
+        }
     }
     private fun initDialogueView(){
         if (viewContainer.getChildAt(0) is DialogueView) {
@@ -474,7 +501,41 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
         controlSceneView.setonClickDuplicateBtn(View.OnClickListener {
             project.story?.let {
                 it.scenes?.let {
-                    it.add(currentSceneIndex + 1, it[currentSceneIndex])
+                    var scene = Scene().apply {
+                        backgroundName = it[currentSceneIndex].backgroundName
+                        backgroundPath = it[currentSceneIndex].backgroundPath
+                        record = it[currentSceneIndex].record
+                        sceneWidth = it[currentSceneIndex].sceneWidth
+                        recordPath = it[currentSceneIndex].recordPath
+                        for (layer in it[currentSceneIndex].layers) {
+                            var newLayer = Layer()
+                            newLayer.id = layer.id
+                            newLayer.name = layer.name
+                            for(actor in layer.actors) {
+                                var newActor = Actor()
+                                newActor.resourcePath = actor.resourcePath
+                                newActor.positionX = actor.positionX
+                                newActor.positionY = actor.positionY
+                                newActor.positionZ = actor.positionZ
+                                newActor.sideLength = actor.sideLength
+                                newActor.sideHeight = actor.sideHeight
+                                newActor.isSelect = actor.isSelect
+                                newActor.parentLayerIndex = actor.parentLayerIndex
+                                newActor.isMovable = actor.isMovable
+                                newActor.text = actor.text
+                                newActor.textColor = actor.textColor
+                                newActor.textAlign = actor.textAlign
+                                newActor.isDialogue = actor.isDialogue
+                                newActor.isMirror = actor.isMirror
+                                newActor.opacity = actor.opacity
+                                newActor.dialogColor = actor.dialogColor
+                                newActor.dialogType = actor.dialogType
+                                newLayer.actors.add(newActor)
+                            }
+                            layers.add(newLayer)
+                        }
+                    }
+                    it.add(currentSceneIndex + 1, scene)
                 }
             }
             var sceneAdapter = controlSceneView.findViewById<RecyclerView>(R.id.scene_recycler_view).adapter as SceneAdapter
@@ -485,10 +546,11 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
                     for (i in 0 until it.size) {
                         onSceneSelectedArrayList.add(switchScene(i))
                         projectBitmaps.add(SceneDrawer.drawScene(this,it[i],0,200,100))
+                        recordTimeArrayList.add(it[i].record?.period)
                     }
                 }
             }
-            sceneAdapter.update(projectBitmaps, onSceneSelectedArrayList)
+            sceneAdapter.update(projectBitmaps, onSceneSelectedArrayList,recordTimeArrayList)
         })
         val layoutManager = LinearLayoutManager(this)
         layoutManager.orientation = LinearLayoutManager.HORIZONTAL
@@ -827,6 +889,7 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
             }
         }
         viewContainer.removeAllViews()
+        startRecord.visibility = View.VISIBLE
         sceneEditView.setLayerVisible(currentLayerIndex)
     }
 
@@ -853,6 +916,7 @@ class SceneEditActivity : AppCompatActivity(), ActorAdapter.OnActorDragListener,
             }
         }
         sceneEditView.setLayerVisible(currentLayerIndex)
+        startRecord.visibility = View.VISIBLE
         viewContainer.removeAllViews()
     }
     private fun addDialogue(positionX: Int, positionY: Int, resource: Int) {

+ 8 - 0
src/main/java/com/bomostory/sceneeditmodule/basicdata/OtherThemes.kt

@@ -0,0 +1,8 @@
+package com.bomostory.sceneeditmodule.basicdata
+
+import com.example.bomocloud.theme.ThemeAssetIndex
+import java.io.File
+
+class OtherThemes (
+        var themes: ArrayList<Theme> = ArrayList()
+)

+ 1 - 1
src/main/java/com/bomostory/sceneeditmodule/basicdata/Project.kt

@@ -11,7 +11,7 @@ data class Project (
         val projectFolder: File,
         val scene1File: File,
         val scene2File: File,
-        val coverFile: File,
+        var coverFile: File?,
         var assetFolder: File,
         var name: String? = null,
         var author: String? = null,

+ 9 - 0
src/main/java/com/bomostory/sceneeditmodule/basicdata/Theme.kt

@@ -0,0 +1,9 @@
+package com.bomostory.sceneeditmodule.basicdata
+
+import com.example.bomocloud.theme.ThemeAssetIndex
+import java.io.File
+
+data class Theme (
+        val themeAssetIndex: ThemeAssetIndex,
+        var assetFolder: File
+)

+ 5 - 0
src/main/java/com/bomostory/sceneeditmodule/basicdata/ThemeActorResource.kt

@@ -0,0 +1,5 @@
+package com.bomostory.sceneeditmodule.basicdata
+
+class ThemeActorResource {
+    var actorPath = ArrayList<ArrayList<String>>()
+}

+ 9 - 0
src/main/java/com/bomostory/sceneeditmodule/cover/CoverColorSelectorView.kt

@@ -58,8 +58,10 @@ class CoverColorSelectorView @JvmOverloads constructor(
             onChangeListener?.onChange()
         }
     var onChangeListener: OnChangeListener? = null
+    var hasSelected = false
 
     private fun select(coverColor: CoverColor) {
+        hasSelected = true
         colorToViewMap[coverColor]?.let {
             val v = findViewById<View>(it)
             colorViewList.forEach {
@@ -72,6 +74,13 @@ class CoverColorSelectorView @JvmOverloads constructor(
         }
     }
 
+    fun deselect() {
+        hasSelected = false
+        colorViewList.forEach {
+            it.setToNonCheckState()
+        }
+    }
+
     private fun View.setToNonCheckState() {
         setPadding(0)
     }

+ 49 - 1
src/main/java/com/bomostory/sceneeditmodule/cover/CoverEditorDialog.kt

@@ -1,5 +1,7 @@
 package com.bomostory.sceneeditmodule.cover
 
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
 import android.os.Bundle
 import android.support.design.widget.TabLayout
 import android.support.v4.app.DialogFragment
@@ -8,9 +10,14 @@ import android.support.v4.view.PagerAdapter
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import com.bomostory.sceneeditmodule.SceneDrawer
+import com.bomostory.sceneeditmodule.basicdata.Project
+import com.bomostory.sceneeditmodule.utils.FileUtils
 import com.example.tfat.myapplication.R
 import kotlinx.android.synthetic.main.dialog_cover_editor.*
 import kotlinx.android.synthetic.main.dialog_cover_editor.view.*
+import java.io.File
+import java.io.FileOutputStream
 
 class CoverEditorDialog : DialogFragment() {
     companion object {
@@ -72,11 +79,21 @@ class CoverEditorDialog : DialogFragment() {
         set(value) {
             frontCoverEditorView_coverEditorDialog.category = value
         }
+    var project: Project? = null
+    var coverFile: File? = null
+        set(value) {
+            field = value
+            if (value != null) {
+                val bitmap = BitmapFactory.decodeFile(value.absolutePath)
+                frontCoverEditorView_coverEditorDialog.sceneCover = bitmap
+            }
+        }
 
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         return inflater.inflate(R.layout.dialog_cover_editor, container, false).apply {
             val viewPager = viewPager_coverEditorDialog_content
             val tabLayout = tabLayout_coverEditorDialog_header
+            val frontCoverEditorView = frontCoverEditorView_coverEditorDialog
             viewPager.adapter = object : PagerAdapter() {
                 override fun instantiateItem(container: ViewGroup, position: Int): Any {
                     return container.getChildAt(position)
@@ -106,9 +123,40 @@ class CoverEditorDialog : DialogFragment() {
                     }
                 })
             }
-            frontCoverEditorView_coverEditorDialog.apply {
+            frontCoverEditorView.apply {
+                this.onColorSelectedListenr = Runnable {
+                    coverFile = null
+                }
                 this.onSave = this@CoverEditorDialog.onSave
                 this.onCancel = this@CoverEditorDialog.onCancel
+                this.onChooseScene = View.OnClickListener {
+                    val project = this@CoverEditorDialog.project ?: return@OnClickListener
+                    this@CoverEditorDialog.frontCoverSceneChooser_frontCoverEditor.setProjectAndSelected(project, 0)
+                    this@CoverEditorDialog.frontCoverSceneChooser_frontCoverEditor.title = storyName
+                    this@CoverEditorDialog.frontCoverSceneChooser_frontCoverEditor.author = author
+                    this@CoverEditorDialog.frontCoverSceneChooser_frontCoverEditor.visibility = View.VISIBLE
+                }
+            }
+            frontCoverSceneChooser_frontCoverEditor.apply {
+                this.onApply = View.OnClickListener {
+                    this@CoverEditorDialog.frontCoverSceneChooser_frontCoverEditor.visibility = View.GONE
+                    val selectedSceneIndex = this@CoverEditorDialog.frontCoverSceneChooser_frontCoverEditor.selected
+                    val scenes = this@CoverEditorDialog.project?.story?.scenes ?: return@OnClickListener
+                    val scene = scenes[selectedSceneIndex]
+                    val width = context.resources.getDimension(R.dimen.share_dialog_screenshot_width).toInt()
+                    val height = context.resources.getDimension(R.dimen.share_dialog_screenshot_height).toInt()
+                    val bitmap = SceneDrawer.drawScene(context, scene, 0, width, height) ?: return@OnClickListener
+                    val file = FileUtils.getCoverFile(project!!)
+                    val fos = FileOutputStream(file)
+                    bitmap.compress(Bitmap.CompressFormat.PNG, 0, fos)
+                    fos.flush()
+                    fos.close()
+                    frontCoverEditorView.sceneCover = bitmap
+                    coverFile = file
+                }
+                this.onDiscard = View.OnClickListener {
+                    this@CoverEditorDialog.frontCoverSceneChooser_frontCoverEditor.visibility = View.GONE
+                }
             }
             backCoverEditorView_coverEditorDialog.apply {
                 this.onSave = this@CoverEditorDialog.onSave

+ 14 - 0
src/main/java/com/bomostory/sceneeditmodule/cover/FrontCoverEditorView.kt

@@ -1,6 +1,7 @@
 package com.bomostory.sceneeditmodule.cover
 
 import android.content.Context
+import android.graphics.Bitmap
 import android.text.Editable
 import android.text.TextWatcher
 import android.util.AttributeSet
@@ -17,6 +18,8 @@ class FrontCoverEditorView @JvmOverloads constructor(
 
     var onCancel: View.OnClickListener? = null
     var onSave: View.OnClickListener? = null
+    var onChooseScene: View.OnClickListener? = null
+    var onColorSelectedListenr = Runnable {  }
     var selectedColor: CoverColor
         get() {
             return coverColorSelectorView_frontCoverEditor.selectedColor
@@ -47,18 +50,29 @@ class FrontCoverEditorView @JvmOverloads constructor(
             val position = value.ordinal
             spinner_frontCoverEditor_category.setSelection(position)
         }
+    var sceneCover: Bitmap? = null
+        set(value) {
+            field = value
+            if (value != null) {
+                iv_frontCoverEditor_cover.setImageBitmap(value)
+                coverColorSelectorView_frontCoverEditor.deselect()
+            }
+        }
 
     init {
         View.inflate(context, R.layout.view_front_cover_editor, this)
         coverColorSelectorView_frontCoverEditor.apply {
             onChangeListener = object : CoverColorSelectorView.OnChangeListener {
                 override fun onChange() {
+                    sceneCover = null
                     setCoverColor(selectedColor, this@FrontCoverEditorView.iv_frontCoverEditor_cover)
+                    onColorSelectedListenr.run()
                 }
             }
         }
         btn_frontCoverEditor_save.setOnClickListener { onSave?.onClick(it) }
         btn_frontCoverEditor_cancel.setOnClickListener { onCancel?.onClick(it) }
+        btn_frontCoverEditor_chooseScene.setOnClickListener { onChooseScene?.onClick(it) }
 
         // category spinner
         val itemLayoutResId = android.R.layout.simple_dropdown_item_1line

+ 172 - 0
src/main/java/com/bomostory/sceneeditmodule/cover/FrontCoverSceneChooserView.kt

@@ -0,0 +1,172 @@
+package com.bomostory.sceneeditmodule.cover
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.support.constraint.ConstraintLayout
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.RadioButton
+import com.bomostory.sceneeditmodule.SceneDrawer
+import com.bomostory.sceneeditmodule.basicdata.Project
+import com.bomostory.sceneeditmodule.basicdata.Scene
+import com.bomostory.sceneeditmodule.utils.Utils
+import com.example.tfat.myapplication.R
+import kotlinx.android.synthetic.main.item_front_cover_scene_chooser.view.*
+import kotlinx.android.synthetic.main.view_front_cover_scene_chooser.view.*
+
+class FrontCoverSceneChooserView @JvmOverloads constructor(
+        context: Context,
+        attrs: AttributeSet? = null,
+        defStyleAttr: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr) {
+
+    var selected: Int = 0
+        private set
+    private var project: Project? = null
+        set(value) {
+            field = value
+            update()
+        }
+    var title: String = ""
+        set(value) {
+            tv_frontCoverSceneChooserDialog_coverTitle.text = value
+        }
+    var author: String = ""
+        set(value) {
+            tv_frontCoverSceneChooserDialog_coverAuthor.text = value
+        }
+    var onApply: View.OnClickListener? = null
+    var onDiscard: View.OnClickListener? = null
+
+    private val dataList = ArrayList<Data>()
+    private val adapter = Adapter(dataList)
+    private var lastSelectedData: Data? = null
+
+    init {
+        inflate(context, R.layout.view_front_cover_scene_chooser, this)
+        setOnClickListener {
+            // do nothing
+        }
+        btn_frontCoverSceneChooserDialog_apply.setOnClickListener { onApply?.onClick(it) }
+        btn_frontCoverSceneChooserDialog_discard.setOnClickListener { onDiscard?.onClick(it) }
+        recyclerView_frontCoverSceneChooserDialog_sceneList.layoutManager = LinearLayoutManager(context).apply {
+            orientation = LinearLayoutManager.VERTICAL
+        }
+        recyclerView_frontCoverSceneChooserDialog_sceneList.adapter = adapter
+    }
+
+    fun setProjectAndSelected(project: Project, selected: Int) {
+        this.selected = selected
+        this.project = project
+    }
+
+    private fun update() {
+        val p = project ?: return
+        dataList.clear()
+        var i = 0
+        p.story?.scenes?.forEach { scene ->
+            val width = context.resources.getDimension(R.dimen.share_dialog_screenshot_width).toInt()
+            val height = context.resources.getDimension(R.dimen.share_dialog_screenshot_height).toInt()
+            val bitmap = SceneDrawer.drawScene(context, scene, 0, width, height) ?: return@forEach
+            val isSelected = i == selected
+            val name = Utils.generateSceneName(i)
+            val onSelectedListener = object : OnSelectedListener {
+                override fun onSelected(data: Data) {
+                    lastSelectedData?.isSelected = false
+                    lastSelectedData = data
+                    lastSelectedData?.isSelected = true
+                    project?.story?.scenes?.also { scenes ->
+                        selected = dataList.indexOf(data)
+                        val s = scenes[selected]
+                        onSceneSelected(s)
+                    }
+                }
+            }
+            val data = Data(isSelected, bitmap, name, onSelectedListener)
+            dataList.add(data)
+            if (isSelected) {
+                onSceneSelected(scene)
+            }
+            i++
+        }
+        adapter.notifyDataSetChanged()
+    }
+
+    private fun onSceneSelected(scene: Scene) {
+        val width = context.resources.getDimension(R.dimen.share_dialog_screenshot_width).toInt()
+        val height = context.resources.getDimension(R.dimen.share_dialog_screenshot_height).toInt()
+        val bitmap = SceneDrawer.drawScene(context, scene, 0, width, height) ?: return
+        iv_frontCoverSceneChooserDialog_cover.setImageBitmap(bitmap)
+    }
+
+    private inner class Adapter(private val dataList: List<Data>) : RecyclerView.Adapter<ViewHolder>() {
+
+        private var lastCheckedRadioButton: RadioButton? = null
+
+        private val onSelectedListener = object : ViewHolder.OnSelectedListener {
+            override fun onSelected(radioButton: RadioButton) {
+                lastCheckedRadioButton?.isChecked = false
+                lastCheckedRadioButton = radioButton
+                lastCheckedRadioButton?.isChecked = true
+            }
+        }
+
+        override fun onCreateViewHolder(parent: ViewGroup, type: Int): ViewHolder {
+            val v1 = LayoutInflater.from(parent.context).inflate(R.layout.item_front_cover_scene_chooser, parent, false)
+            return ViewHolder(v1)
+        }
+
+        override fun getItemCount(): Int {
+            return dataList.size
+        }
+
+        override fun onBindViewHolder(p0: ViewHolder, p1: Int) {
+            val data = dataList[p1]
+            p0.bind(data, onSelectedListener)
+        }
+
+        override fun onViewRecycled(holder: ViewHolder) {
+            super.onViewRecycled(holder)
+            holder.itemView.rb_frontCoverSceneChooserItem.setOnCheckedChangeListener(null)
+        }
+    }
+
+    private class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
+        fun bind(data: Data, onSelectedListener: OnSelectedListener) {
+            if (data.isSelected) {
+                onSelectedListener.onSelected(itemView.rb_frontCoverSceneChooserItem)
+            }
+            itemView.rb_frontCoverSceneChooserItem.setOnCheckedChangeListener { _, b ->
+                if (b) {
+                    onSelectedListener.onSelected(itemView.rb_frontCoverSceneChooserItem)
+                    data.onSelectedListener.onSelected(data)
+                }
+            }
+            itemView.iv_frontCoverSceneChooserItem_screenShot.setImageBitmap(data.screenshot)
+            itemView.tv_frontCoverSceneChooserItem_name.text = data.name
+            itemView.setOnClickListener {
+                itemView.rb_frontCoverSceneChooserItem.isChecked = true
+            }
+            itemView.rb_frontCoverSceneChooserItem.isChecked = data.isSelected
+        }
+
+        interface OnSelectedListener {
+            fun onSelected(radioButton: RadioButton)
+        }
+    }
+
+    private data class Data(
+            var isSelected: Boolean,
+            val screenshot: Bitmap,
+            val name: String,
+            val onSelectedListener: OnSelectedListener
+    )
+
+    private interface OnSelectedListener {
+        fun onSelected(data: Data)
+    }
+}

+ 5 - 51
src/main/java/com/bomostory/sceneeditmodule/navigationbar/actor/ActorAdapter.kt

@@ -80,65 +80,19 @@ class ActorAdapter(var context : Context, var data: ArrayList<ArrayList<String>>
         fun bind(path: String?, position: Int, data: ArrayList<String>) {
             itemView.findViewById<ImageView>(R.id.actor_image).setImageDrawable(Drawable.createFromPath(path))
             itemView.findViewById<ImageView>(R.id.actor_image).setOnTouchListener(boMoOnTouchListener(position,0))
-            //itemView.findViewById<LinearLayout>(R.id.actor_rotate).removeAllViews()
             itemView.actor_rotate.apply {
-//                var onClickListeners = ArrayList<View.OnClickListener>()
-//                for (i in 0 until data.size) {
-//                    onClickListeners.add(View.OnClickListener {
-//                        itemView.findViewById<ImageView>(R.id.actor_image).setImageDrawable(Drawable.createFromPath(data[i]))
-//                        itemView.findViewById<ImageView>(R.id.actor_image).setOnTouchListener(boMoOnTouchListener(position,i))
-//                    })
-//                }
-                var onTouchListeners =  ArrayList<View.OnTouchListener>()
+                var onClickListeners = ArrayList<View.OnClickListener>()
                 for (i in 0 until data.size) {
-                    var positionX = 0
-                    var positionY = 0
-                    var clickPeriod = 0L
-                    var mx: Int
-                    onTouchListeners.add(View.OnTouchListener { v, event ->
-                        when(event.action){
-                            MotionEvent.ACTION_DOWN -> {
-                                clickPeriod = System.currentTimeMillis()
-                                positionX = event.x.toInt()
-                                Log.d("TEST12345", "xQQ = " + positionX)
-                                positionY = event.y.toInt()
-                            }
-                            MotionEvent.ACTION_MOVE -> {
-//                                if (!(Math.abs(event.x - positionX) < 1 && Math.abs(event.y - positionY) < 1)) {
-                                    mx = event.x.toInt() - positionX
-                                    this.smoothScrollBy(-mx *5,0)
-
-                                Log.d("TEST12345", "xKK = " + event.x.toInt())
-//                                }
-                            }
-                            MotionEvent.ACTION_UP -> {
-                                Log.d("TEST12345", "xJJ = " + event.x)
-                                if ((Math.abs(event.x - positionX) < 1 && Math.abs(event.y - positionY) < 1)) {
-                                    itemView.findViewById<ImageView>(R.id.actor_image).setImageDrawable(Drawable.createFromPath(data[i]))
-                                    itemView.findViewById<ImageView>(R.id.actor_image).setOnTouchListener(boMoOnTouchListener(position,i))
-                                }
-                            }
-                        }
-                        return@OnTouchListener true
+                    onClickListeners.add(View.OnClickListener {
+                        itemView.findViewById<ImageView>(R.id.actor_image).setImageDrawable(Drawable.createFromPath(data[i]))
+                        itemView.findViewById<ImageView>(R.id.actor_image).setOnTouchListener(boMoOnTouchListener(position,i))
                     })
                 }
-                adapter = ActorPoseAdapter(data, onTouchListeners)
+                adapter = ActorPoseAdapter(data, onClickListeners)
                 layoutManager = LinearLayoutManager(context).apply {
                     orientation = LinearLayoutManager.HORIZONTAL
                 }
-                isNestedScrollingEnabled = false
-
             }
-//            for (i in 0 until data.size) {
-//                itemView.findViewById<LinearLayout>(R.id.actor_rotate).addView(data[i])
-//                data[i].setOnClickListener(View.OnClickListener {
-//                    itemView.findViewById<ImageView>(R.id.actor_image).setImageDrawable(data[i].drawable)
-//                    itemView.findViewById<ImageView>(R.id.actor_image).setOnTouchListener(boMoOnTouchListener(position,i))
-//                })
-//                var lParams = data[i].layoutParams
-//                lParams.height = 100
-//                lParams.width = 100
-//                data[i].layoutParams = lParams //           }
         }
         private fun boMoOnTouchListener(position: Int, index: Int) : View.OnTouchListener {
             return View.OnTouchListener {view, motionEvent ->

+ 3 - 3
src/main/java/com/bomostory/sceneeditmodule/navigationbar/actor/ActorPoseAdapter.kt

@@ -9,7 +9,7 @@ import com.example.tfat.myapplication.R
 import kotlinx.android.synthetic.main.actor_pose_item.view.*
 import kotlinx.android.synthetic.main.item_actor.view.*
 
-class ActorPoseAdapter(var data: ArrayList<String>, var onClickListeners: ArrayList<View.OnTouchListener>): RecyclerView.Adapter<ActorPoseAdapter.ViewHolder>() {
+class ActorPoseAdapter(var data: ArrayList<String>, var onClickListeners: ArrayList<View.OnClickListener>): RecyclerView.Adapter<ActorPoseAdapter.ViewHolder>() {
 
 
     override fun getItemCount(): Int {
@@ -26,9 +26,9 @@ class ActorPoseAdapter(var data: ArrayList<String>, var onClickListeners: ArrayL
     }
 
     class ViewHolder (view : View) : RecyclerView.ViewHolder(view) {
-        fun bind(ObjectResource: String, onClickListener: View.OnTouchListener) {
+        fun bind(ObjectResource: String, onClickListener: View.OnClickListener) {
             itemView.iv_actor_pose_image.setImageDrawable(Drawable.createFromPath(ObjectResource))
-            itemView.layout_actor_pose.setOnTouchListener(onClickListener)
+            itemView.layout_actor_pose.setOnClickListener(onClickListener)
         }
     }
 }

+ 4 - 2
src/main/java/com/bomostory/sceneeditmodule/navigationbar/scene/SceneAdapter.kt

@@ -7,6 +7,7 @@ import android.support.v7.widget.RecyclerView
 import android.view.*
 import android.widget.ImageView
 import android.widget.TextView
+import com.bomostory.sceneeditmodule.utils.Utils
 import com.example.tfat.myapplication.R
 import kotlinx.android.synthetic.main.item_scene.view.*
 import kotlin.collections.ArrayList
@@ -33,7 +34,7 @@ class SceneAdapter(var context : Context, var data: ArrayList<Bitmap?>, onClickL
         fun bind(bitmap: Bitmap?, position : Int, onClickListenerList: ArrayList<View.OnClickListener>, sceneIndex: Int, recordTime: Long?) {
             itemView.findViewById<ImageView>(R.id.scene_image).setImageBitmap(bitmap)
             itemView.findViewById<ImageView>(R.id.scene_image).setOnClickListener(onClickListenerList[position])
-            itemView.findViewById<TextView>(R.id.scene_number).text = position.toString()
+            itemView.findViewById<TextView>(R.id.scene_number).text = Utils.generateSceneName(position)
             when (recordTime != null) {
                 true -> {itemView.scene_record_time.text = recordTime?.div(1000)?.div(60).toString() + ":" +
                         recordTime?.div(1000)?.rem(60)?.div(10) + recordTime?.div(1000)?.rem(60)?.rem(10).toString()}
@@ -47,9 +48,10 @@ class SceneAdapter(var context : Context, var data: ArrayList<Bitmap?>, onClickL
         }
     }
 
-    fun update(data : ArrayList<Bitmap?>, onClickListenerList: ArrayList<View.OnClickListener>) {
+    fun update(data : ArrayList<Bitmap?>, onClickListenerList: ArrayList<View.OnClickListener>, recordTimeArrayList: ArrayList<Long?>) {
         this.data = data
         this.onClickListenerList = onClickListenerList
+        this.recordTimeArrayList = recordTimeArrayList
         this.notifyDataSetChanged()
     }
 }

+ 53 - 0
src/main/java/com/bomostory/sceneeditmodule/screen/movie/MovieEditActivity.kt

@@ -23,6 +23,7 @@ import com.bomostory.sceneeditmodule.SuperMovieMaker
 import com.bomostory.sceneeditmodule.basicdata.Music
 import com.bomostory.sceneeditmodule.basicdata.Project
 import com.bomostory.sceneeditmodule.basicdata.Scene
+import com.bomostory.sceneeditmodule.cover.CoverEditorDialog
 import com.bomostory.sceneeditmodule.screen.movie.music.MusicEditDialog
 import com.bomostory.sceneeditmodule.screen.movie.music.MusicSelectDialog
 import com.bomostory.sceneeditmodule.screen.movie.music.MusicSelectFragment
@@ -379,9 +380,61 @@ class MovieEditActivity : AppCompatActivity(),
             }
             onClickExportPdf = Runnable { onClickExportPdf() }
             onClickPrint = Runnable { onClickPrint() }
+            onClickEditCover = Runnable { onClickEditCover(project) }
         }.show(supportFragmentManager)
     }
 
+    private fun onClickEditCover(project: Project) {
+        val dialog = CoverEditorDialog()
+        dialog.project = project
+        dialog.onViewCreated = Runnable {
+            dialog.apply {
+                val oldName = project.name ?: ""
+                onSave = View.OnClickListener { it ->
+                    if (storyName == "") {
+                        showEmptyProjectNameMsg()
+                    /** TODO: 目前不支援 rename **/
+                    /**
+                    } else if (storyName != oldName && viewModel.isProjectNameExist(storyName)) {
+                        showDuplicatedProjectNameMsg()
+                    **/
+                    } else {
+                        if (coverFile == null) {
+                            project.coverFile = null
+                        } else {
+                            project.coverFile = coverFile
+                        }
+                        project.name = storyName
+                        project.author = author
+                        project.frontCoverColor = frontCoverColor
+                        project.backCoverColor = backCoverColor
+                        project.category = category
+
+                        val context = this@MovieEditActivity
+                        val pd = ProgressDialog(context)
+                        viewModel.saveProject(context, project, oldName)
+                                .doOnSubscribe { pd.show() }
+                                .doFinally { pd.dismiss() }
+                                .subscribe {
+//                                    projectManager.reloadProjects()
+                                    dismiss()
+                                }
+                    }
+                }
+                coverFile = project.coverFile
+                onCancel = View.OnClickListener { this.dismiss() }
+                storyName = project.name ?: ""
+                author = project.author ?: ""
+                category = project.category
+                if (project.coverFile == null) {
+                    frontCoverColor = project.frontCoverColor
+                }
+                backCoverColor = project.backCoverColor
+            }
+        }
+        dialog.show(supportFragmentManager)
+    }
+
     private fun onClickPrint() {
         ExportPdfDialog().also { exportPdfDialog ->
             exportPdfDialog.project = viewModel.project!!

+ 24 - 0
src/main/java/com/bomostory/sceneeditmodule/screen/movie/MovieEditViewModel.kt

@@ -6,20 +6,29 @@ import android.content.ContentResolver
 import android.content.Context
 import android.media.MediaMetadataRetriever
 import com.bomostory.sceneeditmodule.basicdata.*
+import com.bomostory.sceneeditmodule.utils.FileUtils
 import com.bomostory.sceneeditmodule.utils.TimeUtils
 import com.example.bomocloud.BoMoCloud
 import com.example.bomocloud.video.UploadVideoData
 import com.example.exportmedia.MediaHelper
 import com.example.exportmedia.audio.AudioEditor
 import com.example.tfat.myapplication.R
+import io.reactivex.Completable
 import io.reactivex.Observable
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
 import okhttp3.MediaType
 import okhttp3.MultipartBody
 import okhttp3.RequestBody
 import java.io.File
+import java.util.concurrent.CopyOnWriteArrayList
 
 class MovieEditViewModel : ViewModel() {
 
+    companion object {
+        val onProjectSavedListeners = CopyOnWriteArrayList<Runnable>()
+    }
+
     val storyLiveData = MutableLiveData<Story>()
 
     val storyPeriodLiveData = MutableLiveData<Long>()
@@ -116,4 +125,19 @@ class MovieEditViewModel : ViewModel() {
                 .uploadVideo(author, name, category, filePart)
     }
 
+    fun saveProject(context: Context, project: Project, oldName: String): Completable {
+        project.name?.let { projectName ->
+            if (projectName != oldName) {
+                com.bomostory.sceneeditmodule.utils.FileUtils.changeProjectName(oldName, projectName)
+            }
+        }
+        return FileUtils.saveProject(context, project, 1920, 1080)
+                .andThen {
+                    onProjectSavedListeners.forEach { it.run() }
+                    it.onComplete()
+                }
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+    }
+
 }

+ 5 - 1
src/main/java/com/bomostory/sceneeditmodule/screen/view/MovieSelectView.kt

@@ -10,6 +10,7 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.view.animation.Animation
+import com.bomostory.sceneeditmodule.SceneDrawer
 import com.bomostory.sceneeditmodule.basicdata.Scene
 import com.bomostory.sceneeditmodule.basicdata.Story
 import com.bomostory.sceneeditmodule.utils.AnimationUtils
@@ -109,7 +110,10 @@ class MovieSelectView : ConstraintLayout {
                 itemView.apply {
                     story?.apply {
                         number.text = "$p1"
-                        screenshot.setImageDrawable(Drawable.createFromPath(this.scenes[p1].backgroundPath))
+                        val width = context.resources.getDimension(R.dimen.export_pdf_screenshot_width).toInt()
+                        val height = context.resources.getDimension(R.dimen.export_pdf_screenshot_height).toInt()
+                        val bitmap = SceneDrawer.drawScene(context, scenes[p1], 0, width, height)
+                        screenshot.setImageBitmap(bitmap)
                         this.scenes[p1].record?.let {
                             period.text = TimeUtils.getPlayMovieTimeFormat(it.period)
                         }

+ 6 - 1
src/main/java/com/bomostory/sceneeditmodule/utils/FileUtils.kt

@@ -28,6 +28,11 @@ object FileUtils {
         return File(projectFolder, Config.VIDEO_FILE_NAME)
     }
 
+    fun getCoverFile(project: Project): File {
+        val projectFolder = File(Config.PROJECTS_FOLDER, project.name)
+        return File(projectFolder, Config.COVER_FILE_NAME)
+    }
+
     fun getRealPathFromURI(context: Context, uri: Uri): String? {
         val isKitKat = Build.VERSION.SDK_INT >= 19
 
@@ -255,7 +260,7 @@ object FileUtils {
                     changeFilePath(oldProject.projectFolder),
                     changeFilePath(oldProject.scene1File),
                     changeFilePath(oldProject.scene2File),
-                    changeFilePath(oldProject.coverFile),
+                    if (oldProject.coverFile != null) changeFilePath(oldProject.coverFile!!) else null,
                     changeFilePath(oldProject.assetFolder),
                     newName,
                     oldProject.author,

+ 2 - 2
src/main/java/com/bomostory/sceneeditmodule/utils/Utils.kt

@@ -11,8 +11,8 @@ import java.io.File
 object Utils {
 
     fun generateSceneName(index: Int): String {
-        val book = ('A'.toInt() + ((index + 1) / 22)).toChar()
-        val num = (index + 1) % 22
+        val book = ('A'.toInt() + ((index) / 12)).toChar()
+        val num = (index) % 12 + 1
         return "$book$num"
     }
 

+ 32 - 0
src/main/res/layout/activity_choose_theme.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+xmlns:app="http://schemas.android.com/apk/res-auto"
+xmlns:tools="http://schemas.android.com/tools"
+android:layout_width="match_parent"
+android:layout_height="match_parent"
+tools:context="com.bomostory.sceneeditmodule.ChooseThemeActivity">
+<ImageView
+    android:id="@+id/go_back_view"
+    android:layout_width="match_parent"
+    android:layout_height="114dp"
+    app:layout_constraintTop_toTopOf="parent"/>
+<TextView
+    android:id="@+id/tv_newStory_themeName"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    app:layout_constraintTop_toBottomOf="@+id/go_back_view"
+    android:textSize="34sp"/>
+<android.support.v4.view.ViewPager
+    android:id="@+id/viewPager_newStory"
+    android:clipToPadding="false"
+    android:paddingRight="208dp"
+    android:paddingLeft="208dp"
+    android:layout_width="0dp"
+    android:layout_height="0dp"
+    app:layout_constraintBottom_toBottomOf="parent"
+    app:layout_constraintLeft_toLeftOf="parent"
+    app:layout_constraintRight_toRightOf="parent"
+    app:layout_constraintTop_toBottomOf="@+id/tv_newStory_themeName">
+</android.support.v4.view.ViewPager>
+</android.support.constraint.ConstraintLayout>

+ 10 - 0
src/main/res/layout/dialog_cover_editor.xml

@@ -35,4 +35,14 @@
             android:layout_height="wrap_content" />
     </android.support.v4.view.ViewPager>
 
+    <com.bomostory.sceneeditmodule.cover.FrontCoverSceneChooserView
+        android:visibility="gone"
+        android:id="@+id/frontCoverSceneChooser_frontCoverEditor"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        />
 </android.support.constraint.ConstraintLayout>

+ 1 - 1
src/main/res/layout/dialog_export_pdf.xml

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="800dp"
     android:layout_height="544dp"
     android:background="@drawable/bg_rounded_8dp"
@@ -83,7 +84,6 @@
         android:id="@+id/rb_exportPdfDialog_foldableBooklet"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="52dp"
         android:layout_marginTop="136dp"
         android:buttonTint="@color/cocoa"
         app:layout_constraintLeft_toLeftOf="parent"

+ 1 - 1
src/main/res/layout/item_actor.xml

@@ -16,7 +16,7 @@
         <android.support.v7.widget.RecyclerView
             android:id="@+id/actor_rotate"
             android:nestedScrollingEnabled="false"
-            android:layout_width="200dp"
+            android:layout_width="wrap_content"
             android:layout_height="159dp"
             android:orientation="horizontal">
         </android.support.v7.widget.RecyclerView>

+ 41 - 0
src/main/res/layout/item_front_cover_scene_chooser.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="80dp"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <RadioButton
+        android:id="@+id/rb_frontCoverSceneChooserItem"
+        android:buttonTint="@color/cocoa"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toLeftOf="@id/iv_frontCoverSceneChooserItem_screenShot"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        android:gravity="center"
+        android:padding="12dp"
+        android:layout_width="48dp"
+        android:layout_height="48dp" />
+    
+    <ImageView
+        tools:src="#2300AA"
+        android:id="@+id/iv_frontCoverSceneChooserItem_screenShot"
+        app:layout_constraintLeft_toRightOf="@id/rb_frontCoverSceneChooserItem"
+        app:layout_constraintRight_toLeftOf="@id/tv_frontCoverSceneChooserItem_name"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        android:layout_marginLeft="28dp"
+        android:layout_width="144dp"
+        android:layout_height="72dp" />
+
+    <TextView
+        tools:text="QQQQQQQQQQQQ"
+        android:id="@+id/tv_frontCoverSceneChooserItem_name"
+        app:layout_constraintLeft_toRightOf="@id/iv_frontCoverSceneChooserItem_screenShot"
+        app:layout_constraintTop_toTopOf="@id/iv_frontCoverSceneChooserItem_screenShot"
+        app:layout_constraintBottom_toBottomOf="@id/iv_frontCoverSceneChooserItem_screenShot"
+        android:layout_marginLeft="16dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</android.support.constraint.ConstraintLayout>

+ 21 - 0
src/main/res/layout/theme_page_view.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/iv_themePageView_cover"
+        android:layout_width="480dp"
+        android:layout_height="480dp"
+        android:layout_marginTop="36dp"
+        android:background="@color/white"
+        android:elevation="12dp"
+        android:padding="4dp"
+        android:scaleType="centerCrop"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+</android.support.constraint.ConstraintLayout>

+ 1 - 0
src/main/res/layout/view_front_cover_editor.xml

@@ -8,6 +8,7 @@
 
     <ImageView
         android:id="@+id/iv_frontCoverEditor_cover"
+        android:scaleType="centerCrop"
         android:layout_width="360dp"
         android:layout_height="360dp"
         android:layout_marginLeft="40dp"

+ 134 - 0
src/main/res/layout/view_front_cover_scene_chooser.xml

@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout
+    tools:parentTag="android.support.constraint.ConstraintLayout"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="800dp"
+    android:layout_height="544dp"
+    xmlns:tools="http://schemas.android.com/tools"
+    >
+
+    <View
+        android:background="#ffffff"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        />
+
+    <TextView
+        android:id="@+id/tv_frontCoverSceneChooserDialog_title"
+        android:text="@string/front_cover_scene_choose_dialog_title"
+        android:fontFamily="sans-serif"
+        android:gravity="center"
+        android:textColor="#de000000"
+        android:textSize="20sp"
+        android:textStyle="normal"
+        android:layout_width="800dp"
+        android:layout_height="64dp"
+        android:background="@color/pale_peach"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ImageView
+        tools:src="#AA0033"
+        android:id="@+id/iv_frontCoverSceneChooserDialog_cover"
+        android:scaleType="centerCrop"
+        app:layout_constraintTop_toBottomOf="@id/tv_frontCoverSceneChooserDialog_title"
+        app:layout_constraintLeft_toLeftOf="parent"
+        android:layout_marginTop="24dp"
+        android:layout_marginLeft="40dp"
+        android:layout_width="360dp"
+        android:layout_height="360dp" />
+
+    <ImageView
+        android:id="@+id/iv_frontCoverSceneChooserDialog_coverMask"
+        android:layout_width="0dp"
+        android:layout_height="112dp"
+        android:layout_marginBottom="16dp"
+        android:src="#66ffffff"
+        app:layout_constraintBottom_toBottomOf="@id/iv_frontCoverSceneChooserDialog_cover"
+        app:layout_constraintLeft_toLeftOf="@id/iv_frontCoverSceneChooserDialog_cover"
+        app:layout_constraintRight_toRightOf="@id/iv_frontCoverSceneChooserDialog_cover" />
+
+    <TextView
+        android:id="@+id/tv_frontCoverSceneChooserDialog_coverTitle"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:ellipsize="middle"
+        android:fontFamily="sans-serif-medium"
+        android:gravity="center"
+        android:singleLine="true"
+        android:textColor="#ffffff"
+        android:textSize="40sp"
+        app:layout_constraintLeft_toLeftOf="@id/iv_frontCoverSceneChooserDialog_coverMask"
+        app:layout_constraintRight_toRightOf="@id/iv_frontCoverSceneChooserDialog_coverMask"
+        app:layout_constraintTop_toTopOf="@id/iv_frontCoverSceneChooserDialog_coverMask"
+        tools:text="Story Name" />
+
+    <TextView
+        android:id="@+id/tv_frontCoverSceneChooserDialog_coverAuthor"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="9dp"
+        android:ellipsize="middle"
+        android:fontFamily="sans-serif-medium"
+        android:gravity="center"
+        android:singleLine="true"
+        android:textColor="#ffffff"
+        android:textSize="20sp"
+        app:layout_constraintLeft_toLeftOf="@id/iv_frontCoverSceneChooserDialog_coverMask"
+        app:layout_constraintRight_toRightOf="@id/iv_frontCoverSceneChooserDialog_coverMask"
+        app:layout_constraintTop_toBottomOf="@id/tv_frontCoverSceneChooserDialog_coverTitle"
+        tools:text="Author" />
+
+    <!-- Remove visibility="gone" when implemented it -->
+    <Spinner
+        android:visibility="invisible"
+        android:id="@+id/spinner_frontCoverSceneChooserDialog_align"
+        android:foreground="@drawable/bg_bomo_spinner"
+        app:layout_constraintTop_toTopOf="@id/iv_frontCoverSceneChooserDialog_cover"
+        app:layout_constraintLeft_toRightOf="@id/iv_frontCoverSceneChooserDialog_cover"
+        android:layout_marginLeft="40dp"
+        android:layout_width="320dp"
+        android:layout_height="56dp" />
+
+    <android.support.v7.widget.RecyclerView
+        tools:background="#33AA00"
+        android:id="@+id/recyclerView_frontCoverSceneChooserDialog_sceneList"
+        app:layout_constraintTop_toBottomOf="@id/spinner_frontCoverSceneChooserDialog_align"
+        app:layout_constraintBottom_toBottomOf="@id/iv_frontCoverSceneChooserDialog_cover"
+        app:layout_constraintLeft_toLeftOf="@id/spinner_frontCoverSceneChooserDialog_align"
+        app:layout_constraintRight_toRightOf="@id/spinner_frontCoverSceneChooserDialog_align"
+        android:layout_marginTop="10dp"
+        android:layout_width="0dp"
+        android:layout_height="0dp" />
+
+    <Button
+        android:id="@+id/btn_frontCoverSceneChooserDialog_apply"
+        style="@style/Widget.AppCompat.Button.Borderless.Colored"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="28dp"
+        android:layout_marginBottom="24dp"
+        android:text="@string/front_cover_scene_choose_dialog_btn_apply"
+        android:textColor="@color/cocoa"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintRight_toRightOf="@id/recyclerView_frontCoverSceneChooserDialog_sceneList"
+        app:layout_constraintTop_toBottomOf="@id/recyclerView_frontCoverSceneChooserDialog_sceneList" />
+
+    <Button
+        android:id="@+id/btn_frontCoverSceneChooserDialog_discard"
+        style="@style/Widget.AppCompat.Button.Borderless.Colored"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/front_cover_scene_choose_dialog_btn_discard"
+        android:textColor="@color/cocoa"
+        app:layout_constraintBottom_toBottomOf="@id/btn_frontCoverSceneChooserDialog_apply"
+        app:layout_constraintRight_toLeftOf="@id/btn_frontCoverSceneChooserDialog_apply"
+        app:layout_constraintTop_toTopOf="@id/btn_frontCoverSceneChooserDialog_apply" />
+</android.support.constraint.ConstraintLayout>

+ 4 - 0
src/main/res/values/strings.xml

@@ -52,4 +52,8 @@
     <string name="export_pdf_complete_dialog_msg">Complete</string>
     <string name="export_pdf_complete_dialog_positive">View</string>
     <string name="share_pdf_failed_no_app">No app can view pdf file.</string>
+
+    <string name="front_cover_scene_choose_dialog_title">Choose a scene as the front cover</string>
+    <string name="front_cover_scene_choose_dialog_btn_apply">Apply</string>
+    <string name="front_cover_scene_choose_dialog_btn_discard">Discard</string>
 </resources>