From 78a45f1e13bad67de00596480766b252db07a057 Mon Sep 17 00:00:00 2001 From: Kirill Biakov Date: Wed, 31 Aug 2016 01:25:21 +0300 Subject: [PATCH] Added diff view as footer example --- .../io/github/kbiakov/codeview/CodeView.kt | 7 +++ .../codeview/adapters/AbstractCodeAdapter.kt | 7 +-- .../codeview/adapters/CodeWithDiffsAdapter.kt | 29 +++++++++ .../codeview/adapters/CodeWithNotesAdapter.kt | 4 +- .../kbiakov/codeview/views/LineDiffView.kt | 63 +++++++++++++++++++ .../kbiakov/codeview/views/LineNoteView.kt | 12 +++- .../src/main/res/layout/item_code_diff.xml | 29 +++++++++ .../src/main/res/layout/item_code_line.xml | 10 +-- codeview/src/main/res/values/colors.xml | 3 + codeview/src/main/res/values/dimens.xml | 6 ++ .../codeviewexample/CustomAdapter.java | 2 +- .../codeviewexample/ListingsActivity.java | 14 +++++ example/src/main/res/values/strings.xml | 60 ++++++++++-------- 13 files changed, 208 insertions(+), 38 deletions(-) create mode 100644 codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithDiffsAdapter.kt create mode 100644 codeview/src/main/java/io/github/kbiakov/codeview/views/LineDiffView.kt create mode 100644 codeview/src/main/res/layout/item_code_diff.xml create mode 100644 codeview/src/main/res/values/dimens.xml diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt b/codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt index 343fa0c..0fa470c 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt @@ -195,6 +195,13 @@ class CodeView : RelativeLayout { adapter.codeListener = listener } + /** + * Remove code listener. + */ + fun removeCodeListener() = addTask { + adapter.codeListener = null + } + /** * Control shadows visibility to provide more sensitive UI. * diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/adapters/AbstractCodeAdapter.kt b/codeview/src/main/java/io/github/kbiakov/codeview/adapters/AbstractCodeAdapter.kt index 34bbe04..640b722 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/adapters/AbstractCodeAdapter.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/adapters/AbstractCodeAdapter.kt @@ -161,9 +161,10 @@ abstract class AbstractCodeAdapter : RecyclerView.Adapter : RecyclerView.Adapter - val footerView = createFooter(mContext, entity) - val dp8 = dpToPx(mContext, 8) - footerView.setPadding(dpToPx(mContext, 46), if (isFirst) dp8 else 0, dp8, dp8) + val footerView = createFooter(mContext, entity, isFirst) holder.llLineFooter.addView(footerView) diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithDiffsAdapter.kt b/codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithDiffsAdapter.kt new file mode 100644 index 0000000..51c5056 --- /dev/null +++ b/codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithDiffsAdapter.kt @@ -0,0 +1,29 @@ +package io.github.kbiakov.codeview.adapters + +import android.content.Context +import io.github.kbiakov.codeview.views.DiffModel +import io.github.kbiakov.codeview.views.LineDiffView + +/** + * @class CodeWithDiffsAdapter + * + * Code content adapter with ability to add diffs (additions & deletions) in footer. + * + * @author Kirill Biakov + */ +class CodeWithDiffsAdapter : AbstractCodeAdapter { + /** + * Default constructor. + */ + constructor(context: Context, content: String) : super(context, content) + + /** + * Create footer view. + * + * @param context Context + * @param entity Note content + * @param isFirst Is first footer + */ + override fun createFooter(context: Context, entity: DiffModel, isFirst: Boolean) = + LineDiffView.create(context, entity) +} diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithNotesAdapter.kt b/codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithNotesAdapter.kt index a53d7fb..8b9e703 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithNotesAdapter.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithNotesAdapter.kt @@ -22,10 +22,12 @@ class CodeWithNotesAdapter : AbstractCodeAdapter { * * @param context Context * @param entity Note content + * @param isFirst Is first footer view */ - override fun createFooter(context: Context, entity: String) = + override fun createFooter(context: Context, entity: String, isFirst: Boolean) = LineNoteView.create(context, text = entity, + isFirst = isFirst, bgColor = colorTheme.bgNum.color(), textColor = colorTheme.noteColor.color()) } diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/views/LineDiffView.kt b/codeview/src/main/java/io/github/kbiakov/codeview/views/LineDiffView.kt new file mode 100644 index 0000000..d496c73 --- /dev/null +++ b/codeview/src/main/java/io/github/kbiakov/codeview/views/LineDiffView.kt @@ -0,0 +1,63 @@ +package io.github.kbiakov.codeview.views + +import android.content.Context +import android.support.v4.content.ContextCompat +import android.view.LayoutInflater +import android.widget.RelativeLayout +import android.widget.TextView +import io.github.kbiakov.codeview.R +import io.github.kbiakov.codeview.highlight.MonoFontCache + +/** + * @class CodeDiffView + * + * View to present code difference (additions & deletions). + * + * @author Kirill Biakov + */ +class LineDiffView : RelativeLayout { + + private val tvLineDiff: TextView + private val tvLineContent: TextView + + /** + * Default constructor. + */ + constructor(context: Context) : super(context) { + val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater + inflater.inflate(R.layout.item_code_diff, this, true) + + tvLineDiff = findViewById(R.id.tv_line_diff) as TextView + tvLineContent = findViewById(R.id.tv_line_content) as TextView + } + + companion object Factory { + /** + * Simple factory method to create code diff view. + * + * @param context Context + * @param model Diff model + * @return Created line diff view + */ + fun create(context: Context, model: DiffModel): LineDiffView { + val diffView = LineDiffView(context) + diffView.tvLineDiff.text = if (model.isAddition) "+" else "-" + diffView.tvLineContent.text = model.content + diffView.tvLineContent.typeface = MonoFontCache.getInstance(context).typeface + + diffView.setBackgroundColor(ContextCompat.getColor(context, + if (model.isAddition) + R.color.diff_add_background + else R.color.diff_del_background)) + + return diffView + } + } +} + +/** + * Model to provide code difference (additions & deletions). + * + * @author Kirill Biako + */ +data class DiffModel(val content: String, val isAddition: Boolean = true) diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/views/LineNoteView.kt b/codeview/src/main/java/io/github/kbiakov/codeview/views/LineNoteView.kt index 609d294..9a23369 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/views/LineNoteView.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/views/LineNoteView.kt @@ -2,6 +2,8 @@ package io.github.kbiakov.codeview.views import android.content.Context import android.widget.TextView +import io.github.kbiakov.codeview.R +import io.github.kbiakov.codeview.dpToPx /** * @class LineNoteView @@ -18,17 +20,25 @@ class LineNoteView(context: Context?) : TextView(context) { * * @param context Context * @param text Note text + * @param isFirst Is first footer view * @param bgColor Background color * @param textColor Text Color * @return Created line note view */ - fun create(context: Context, text: String, bgColor: Int, textColor: Int): LineNoteView { + fun create(context: Context, text: String, isFirst: Boolean, bgColor: Int, textColor: Int): LineNoteView { val noteView = LineNoteView(context) noteView.textSize = 12f noteView.text = text noteView.setTextColor(textColor) noteView.setBackgroundColor(bgColor) + val dp8 = dpToPx(context, 8) + + val leftPadding = context.resources.getDimension( + R.dimen.line_num_width).toInt() + dpToPx(context, 14) + + noteView.setPadding(leftPadding, if (isFirst) dp8 else 0, dp8, dp8) + return noteView } } diff --git a/codeview/src/main/res/layout/item_code_diff.xml b/codeview/src/main/res/layout/item_code_diff.xml new file mode 100644 index 0000000..7aa1549 --- /dev/null +++ b/codeview/src/main/res/layout/item_code_diff.xml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/codeview/src/main/res/layout/item_code_line.xml b/codeview/src/main/res/layout/item_code_line.xml index b25e845..d4f1ef2 100644 --- a/codeview/src/main/res/layout/item_code_line.xml +++ b/codeview/src/main/res/layout/item_code_line.xml @@ -6,24 +6,24 @@ #2c2d30 #e9edf4 #4c5d6e + + #EAFFEA + #FFECEC diff --git a/codeview/src/main/res/values/dimens.xml b/codeview/src/main/res/values/dimens.xml new file mode 100644 index 0000000..aa53e29 --- /dev/null +++ b/codeview/src/main/res/values/dimens.xml @@ -0,0 +1,6 @@ + + + 32dp + 24dp + 12sp + \ No newline at end of file diff --git a/example/src/main/java/io/github/kbiakov/codeviewexample/CustomAdapter.java b/example/src/main/java/io/github/kbiakov/codeviewexample/CustomAdapter.java index 4336de2..daa5704 100644 --- a/example/src/main/java/io/github/kbiakov/codeviewexample/CustomAdapter.java +++ b/example/src/main/java/io/github/kbiakov/codeviewexample/CustomAdapter.java @@ -17,7 +17,7 @@ public CustomAdapter(@NotNull Context context, @NotNull String content) { @NotNull @Override - public View createFooter(@NotNull Context context, CustomModel entity) { + public View createFooter(@NotNull Context context, CustomModel entity, boolean isFirst) { View footerView = LayoutInflater.from(context).inflate(R.layout.custom_footer, null); ((TextView) footerView.findViewById(R.id.tv_footer_title)).setText(entity.firstName); ((TextView) footerView.findViewById(R.id.tv_footer_description)).setText(entity.lastName); diff --git a/example/src/main/java/io/github/kbiakov/codeviewexample/ListingsActivity.java b/example/src/main/java/io/github/kbiakov/codeviewexample/ListingsActivity.java index 4a9a48f..50f831e 100644 --- a/example/src/main/java/io/github/kbiakov/codeviewexample/ListingsActivity.java +++ b/example/src/main/java/io/github/kbiakov/codeviewexample/ListingsActivity.java @@ -8,10 +8,12 @@ import org.jetbrains.annotations.NotNull; +import io.github.kbiakov.codeview.adapters.CodeWithDiffsAdapter; import io.github.kbiakov.codeview.adapters.CodeWithNotesAdapter; import io.github.kbiakov.codeview.highlight.ColorTheme; import io.github.kbiakov.codeview.CodeView; import io.github.kbiakov.codeview.OnCodeLineClickListener; +import io.github.kbiakov.codeview.views.DiffModel; public class ListingsActivity extends AppCompatActivity { @@ -64,5 +66,17 @@ public void onCodeLineClicked(int n, @NotNull String line) { adapter.addFooterEntity(n, new CustomAdapter.CustomModel("Line " + (n + 1), line)); } }); + + /** + * 4: diff adapter with footer views + */ + + final CodeWithDiffsAdapter diffsAdapter = new CodeWithDiffsAdapter(this, getString(R.string.listing_py)); + codeView.setAdapter(diffsAdapter); + codeView.highlightCode("python"); + codeView.removeCodeListener(); + + diffsAdapter.addFooterEntity(15, new DiffModel(getString(R.string.py_addition_16), true)); + diffsAdapter.addFooterEntity(10, new DiffModel(getString(R.string.py_deletion_11), false)); } } diff --git a/example/src/main/res/values/strings.xml b/example/src/main/res/values/strings.xml index f32c3a3..531af17 100644 --- a/example/src/main/res/values/strings.xml +++ b/example/src/main/res/values/strings.xml @@ -41,32 +41,6 @@ <SCRIPT language=\"JavaScript\">fulltime();</SCRIPT> - - from timeit import Timer\n - \n - tmp = \"Python 3.2.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32.\"\n - \n - def case1(): # А. инкрементальные конкатенации в цикле\n - s = \"\"\n - for i in range(10000):\n - s += tmp\n - - def case2(): # Б. через промежуточный список и метод join\n - s = []\n - for i in range(10000):\n - s.append(tmp)\n - s = \"\".join(s)\n - \n - def case3(): # В. списковое выражение и метод join\n - return \"\".join([tmp for i in range(10000)])\n - \n - def case4(): # Г. генераторное выражение и метод join\n - return \"\".join(tmp for i in range(10000))\n - \n - for v in range(1,5):\n - print (Timer(\"func()\",\"from __main__ import case%s as func\" % v).timeit(200))\n - - 3. CodeView and related adapter.\n \n @@ -119,4 +93,38 @@ } + + from timeit import Timer\n + \n + tmp = \"Python 3.2.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32.\"\n + \n + def case1(): # А. инкрементальные конкатенации в цикле\n + s = \"\"\n + for i in range(10000):\n + s += tmp\n + + def case2(): # Б. через промежуточный список и метод join\n + s = []\n + for i in range(10000):\n + s.append(tmp)\n + s = \"\".join(s)\n + \n + def case3(): # В. списковое выражение и метод join\n + return \"\".join([tmp for i in range(10000)])\n + \n + def case4(): # Г. генераторное выражение и метод join\n + return \"\".join(tmp for i in range(10000))\n + \n + for v in range(1,5):\n + print (Timer(\"func()\",\"from __main__ import case%s as func\" % v).timeit(200))\n + + + + return \"\".join([tmp for i in range(10000)]) + + + + for i in range(100500): + +