From de94001d2333eb11c90dd9811230a806c2b22d3c Mon Sep 17 00:00:00 2001 From: Kirill Biakov Date: Wed, 24 Aug 2016 01:32:58 +0300 Subject: [PATCH 1/2] Extended docs, wrapped some placeholder logic --- .../kbiakov/codeview/CodeContentAdapter.kt | 3 ++ .../io/github/kbiakov/codeview/CodeView.kt | 34 +++++++++++++++++-- .../codeview/classifier/CodeClassifier.kt | 5 +++ .../codeview/highlight/CodeHighlighter.kt | 15 ++++++-- .../src/main/res/layout/item_code_line.xml | 3 +- .../src/main/res/layout/layout_code_view.xml | 5 +-- .../src/main/res/layout/activity_listings.xml | 10 ++++-- 7 files changed, 65 insertions(+), 10 deletions(-) diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/CodeContentAdapter.kt b/codeview/src/main/java/io/github/kbiakov/codeview/CodeContentAdapter.kt index 7d9b907..8a89324 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/CodeContentAdapter.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/CodeContentAdapter.kt @@ -76,6 +76,9 @@ class CodeContentAdapter : RecyclerView.Adapter { /** * Split code content by lines. If listing must not be shown full it shows * only necessary lines & rest are dropped (and stores in named variable). + * + * @param isShowFull Show full listing? + * @param shortcutNote Note will shown below code for listing shortcut */ private fun initCodeContent(isShowFull: Boolean, shortcutNote: String = mContext.getString(R.string.show_all)) { 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 c081ef5..0b3a55d 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt @@ -13,6 +13,7 @@ import android.view.ViewPropertyAnimator import android.widget.RelativeLayout import io.github.kbiakov.codeview.highlight.ColorTheme import io.github.kbiakov.codeview.highlight.ColorThemeData +import io.github.kbiakov.codeview.highlight.color import java.util.* /** @@ -34,6 +35,7 @@ import java.util.* */ class CodeView : RelativeLayout { + private val vRoot: View private val vPlaceholder: View private val vShadowRight: View private val vShadowBottomLine: View @@ -59,6 +61,7 @@ class CodeView : RelativeLayout { val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater inflater.inflate(R.layout.layout_code_view, this, true) + vRoot = findViewById(R.id.v_root) vPlaceholder = findViewById(R.id.v_placeholder) vShadowRight = findViewById(R.id.v_shadow_right) vShadowBottomLine = findViewById(R.id.v_shadow_bottom_line) @@ -135,21 +138,27 @@ class CodeView : RelativeLayout { /** * Specify color theme: syntax colors (need to highlighting) & related to * code view (numeration color & background, content backgrounds). + * + * @param colorTheme Default or custom color theme */ // default color theme provided by enum fun setColorTheme(colorTheme: ColorTheme) = addTask { adapter.colorTheme = colorTheme.with() + fillBackground(colorTheme.bgContent) } // custom color theme provided by user fun setColorTheme(colorTheme: ColorThemeData) = addTask { adapter.colorTheme = colorTheme + fillBackground(colorTheme.bgContent) } /** * Highlight code by defined programming language. * It holds the placeholder on the view until code is highlighted. + * + * @param language Language to highlight */ fun highlightCode(language: String) = addTask { adapter.highlightCode(language) @@ -166,8 +175,10 @@ class CodeView : RelativeLayout { } /** - * Useful in some cases if you want to listen user line selection. - * (May be you want to show alert when user click on code line, who knows?) ¯\_(ツ)_/¯ + * Useful in some cases if you want to listen user line clicks. + * (May be you want to show alert, who knows?) ¯\_(ツ)_/¯ + * + * @param listener Code line click listener */ fun setCodeListener(listener: OnCodeLineClickListener) = addTask { adapter.codeListener = listener @@ -175,6 +186,8 @@ class CodeView : RelativeLayout { /** * Control shadows visibility to provide more sensitive UI. + * + * @param isVisible Shadows visibility */ fun setShadowsVisible(isVisible: Boolean = true) = addTask { val visibility = if (isVisible) View.VISIBLE else GONE @@ -185,6 +198,8 @@ class CodeView : RelativeLayout { /** * Update code content if view was built or, finally, build code view. + * + * @param content Code content */ fun setCodeContent(content: String) { when (state) { @@ -216,6 +231,7 @@ class CodeView : RelativeLayout { Thread.delayed { rvCodeContent.adapter = CodeContentAdapter(context, content) processBuildTasks() + //fillBackground() setupShadows() hidePlaceholder() state = ViewState.PRESENTED @@ -230,9 +246,19 @@ class CodeView : RelativeLayout { */ private fun setupShadows() = setShadowsVisible(!adapter.isFullShowing) + /** + * Fill background to color accordingly to color theme. + * + * @color Background color + */ + private fun fillBackground(color: Int = adapter.colorTheme.bgContent) = + vRoot.setBackgroundColor(color.color()) + /** * Placeholder fills space at start and stretched to marked up view size * (by extracting code lines) because at this point it's not built yet. + * + * @param linesCount Count of lines to measure space for placeholder */ private fun measurePlaceholder(linesCount: Int) { val lineHeight = dpToPx(context, 24) @@ -270,11 +296,15 @@ interface OnCodeLineClickListener { /** * Extension for delayed block call. + * + * @param body Operation body */ fun Thread.delayed(body: () -> Unit) = Handler().postDelayed(body, 150) /** * More readable form for animation listener (hi, iOS & Cocoa Touch!). + * + * @param handler Handler body */ fun ViewPropertyAnimator.didAnimated(handler: () -> Unit) = setListener(object : AnimatorListenerAdapter() { diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/classifier/CodeClassifier.kt b/codeview/src/main/java/io/github/kbiakov/codeview/classifier/CodeClassifier.kt index 49e60d7..4033268 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/classifier/CodeClassifier.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/classifier/CodeClassifier.kt @@ -40,6 +40,8 @@ object CodeClassifier { * At this point all files with code listings prepared to process * by classifier. This operation often is very expensive & should * be performed asynchronously when app starts. + * + * @param context Context */ fun train(context: Context) { Files.ls(context, TRAINING_SET_FOLDER).forEach { language -> @@ -53,6 +55,9 @@ object CodeClassifier { /** * Try to define what language is used in code snippet. + * + * @param snippet Code snippet + * @return Code language */ fun classify(snippet: String): String { val feature = classifier.classify(spaceSplit(snippet)) diff --git a/codeview/src/main/java/io/github/kbiakov/codeview/highlight/CodeHighlighter.kt b/codeview/src/main/java/io/github/kbiakov/codeview/highlight/CodeHighlighter.kt index 93db535..ca8fcc9 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/highlight/CodeHighlighter.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/highlight/CodeHighlighter.kt @@ -25,7 +25,7 @@ object CodeHighlighter { * @param codeLanguage Programming language * @param rawSource Code source by one string * @param colorTheme Color theme (see below) - * @return Highlighted code. String with necessary inserted color tags. + * @return Highlighted code, string with necessary inserted color tags */ fun highlight(codeLanguage: String, rawSource: String, colorTheme: ColorThemeData): String { val source = rawSource.escapeLT() @@ -46,6 +46,10 @@ object CodeHighlighter { /** * Parse user input by extracting highlighted content. + * + * @param codeContent Code content + * @param result Syntax unit + * @return Parsed content to highlight */ private fun parseContent(codeContent: String, result: ParseResult): String { val length = result.offset + result.length @@ -55,12 +59,19 @@ object CodeHighlighter { /** * Color accessor from built color map for selected color theme. + * + * @param colorsMap Colors map built from color theme + * @param result Syntax unit + * @return Color for syntax unit */ private fun getColor(colorsMap: HashMap, result: ParseResult) = colorsMap[result.styleKeys[0]] ?: colorsMap["pln"] /** * Build fast accessor (as map) for selected color theme. + * + * @param colorTheme Color theme + * @return Colors map built from color theme */ private fun buildColorsMap(colorTheme: ColorThemeData) = object : HashMap() { @@ -155,7 +166,7 @@ data class ColorThemeData( val noteColor: Int) /** - * Colors for highlighting code spots. + * Colors for highlighting code units. */ data class SyntaxColors( val type: Int = 0x859900, diff --git a/codeview/src/main/res/layout/item_code_line.xml b/codeview/src/main/res/layout/item_code_line.xml index 74eeb6d..9dc6622 100644 --- a/codeview/src/main/res/layout/item_code_line.xml +++ b/codeview/src/main/res/layout/item_code_line.xml @@ -17,10 +17,9 @@ android:id="@+id/tv_line_content" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_centerVertical="true" - android:layout_toRightOf="@+id/tv_line_num" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" + android:layout_toRightOf="@+id/tv_line_num" android:gravity="center_vertical" android:fontFamily="monospace" android:singleLine="true" diff --git a/codeview/src/main/res/layout/layout_code_view.xml b/codeview/src/main/res/layout/layout_code_view.xml index 2cd67e4..4d9e744 100644 --- a/codeview/src/main/res/layout/layout_code_view.xml +++ b/codeview/src/main/res/layout/layout_code_view.xml @@ -3,7 +3,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:id="@+id/v_root"> diff --git a/example/src/main/res/layout/activity_listings.xml b/example/src/main/res/layout/activity_listings.xml index 1a97ef1..25704fc 100644 --- a/example/src/main/res/layout/activity_listings.xml +++ b/example/src/main/res/layout/activity_listings.xml @@ -8,7 +8,13 @@ + android:layout_width="match_parent" + android:layout_height="120dp"/> + + From 1aae68113b5fcca5187764df00f5b452398fcf02 Mon Sep 17 00:00:00 2001 From: Kirill Biakov Date: Wed, 24 Aug 2016 14:12:19 +0300 Subject: [PATCH 2/2] Fixed view size stretching --- .../io/github/kbiakov/codeview/CodeView.kt | 41 +++++++++++-------- .../src/main/res/layout/layout_code_view.xml | 17 ++++---- .../codeviewexample/ListingsActivity.java | 3 +- .../src/main/res/layout/activity_listings.xml | 8 +--- 4 files changed, 34 insertions(+), 35 deletions(-) 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 0b3a55d..dbde06e 100644 --- a/codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt +++ b/codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt @@ -35,7 +35,6 @@ import java.util.* */ class CodeView : RelativeLayout { - private val vRoot: View private val vPlaceholder: View private val vShadowRight: View private val vShadowBottomLine: View @@ -61,7 +60,6 @@ class CodeView : RelativeLayout { val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater inflater.inflate(R.layout.layout_code_view, this, true) - vRoot = findViewById(R.id.v_root) vPlaceholder = findViewById(R.id.v_placeholder) vShadowRight = findViewById(R.id.v_shadow_right) vShadowBottomLine = findViewById(R.id.v_shadow_bottom_line) @@ -145,13 +143,11 @@ class CodeView : RelativeLayout { // default color theme provided by enum fun setColorTheme(colorTheme: ColorTheme) = addTask { adapter.colorTheme = colorTheme.with() - fillBackground(colorTheme.bgContent) } // custom color theme provided by user fun setColorTheme(colorTheme: ColorThemeData) = addTask { adapter.colorTheme = colorTheme - fillBackground(colorTheme.bgContent) } /** @@ -207,10 +203,10 @@ class CodeView : RelativeLayout { build(content) ViewState.PREPARE -> Thread.delayed { - adapter.updateCodeContent(content) + update(content) } ViewState.PRESENTED -> - adapter.updateCodeContent(content) + update(content) } } @@ -231,13 +227,25 @@ class CodeView : RelativeLayout { Thread.delayed { rvCodeContent.adapter = CodeContentAdapter(context, content) processBuildTasks() - //fillBackground() setupShadows() hidePlaceholder() state = ViewState.PRESENTED } } + /** + * Hot view updating. + * + * @param content Code content + */ + private fun update(content: String) { + state = ViewState.PREPARE + measurePlaceholder(extractLines(content).size) + adapter.updateCodeContent(content) + hidePlaceholder() + state = ViewState.PRESENTED + } + // - Setup actions /** @@ -246,27 +254,24 @@ class CodeView : RelativeLayout { */ private fun setupShadows() = setShadowsVisible(!adapter.isFullShowing) - /** - * Fill background to color accordingly to color theme. - * - * @color Background color - */ - private fun fillBackground(color: Int = adapter.colorTheme.bgContent) = - vRoot.setBackgroundColor(color.color()) - /** * Placeholder fills space at start and stretched to marked up view size - * (by extracting code lines) because at this point it's not built yet. + * (by code lines count) because at this point it's not built yet. * * @param linesCount Count of lines to measure space for placeholder */ private fun measurePlaceholder(linesCount: Int) { val lineHeight = dpToPx(context, 24) - val topMargin = dpToPx(context, 8) - val height = linesCount * lineHeight + 2 * topMargin + val topPadding = dpToPx(context, 8) + + // double padding (top & bottom) for big view, one is enough for small + val padding = (if (linesCount > 1) 2 else 1) * topPadding + + val height = linesCount * lineHeight + padding vPlaceholder.layoutParams = RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, height) + vPlaceholder.visibility = View.VISIBLE } // - Animations diff --git a/codeview/src/main/res/layout/layout_code_view.xml b/codeview/src/main/res/layout/layout_code_view.xml index 4d9e744..ee66263 100644 --- a/codeview/src/main/res/layout/layout_code_view.xml +++ b/codeview/src/main/res/layout/layout_code_view.xml @@ -3,13 +3,13 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:id="@+id/v_root"> + android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:fillViewport="true"> + android:visibility="gone"/> + android:orientation="horizontal" + android:visibility="gone"> + android:background="@drawable/shadow_bottom_line"/> + android:background="@drawable/shadow_bottom_content"/> 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 83c2974..036c3fa 100644 --- a/example/src/main/java/io/github/kbiakov/codeviewexample/ListingsActivity.java +++ b/example/src/main/java/io/github/kbiakov/codeviewexample/ListingsActivity.java @@ -22,12 +22,13 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { // use chaining to build view codeView.highlightCode("js") - //.setColorTheme(ColorTheme.SOLARIZED_LIGHT.withBgContent(myColor)) + .setColorTheme(ColorTheme.SOLARIZED_LIGHT) .setCodeContent(getString(R.string.listing_js)); // do not use chaining for built view // (you can, but follow it should be performed sequentially) codeView.setCodeContent(getString(R.string.listing_java)); + codeView.setColorTheme(ColorTheme.DEFAULT); codeView.highlightCode("java"); } } diff --git a/example/src/main/res/layout/activity_listings.xml b/example/src/main/res/layout/activity_listings.xml index 25704fc..7878e56 100644 --- a/example/src/main/res/layout/activity_listings.xml +++ b/example/src/main/res/layout/activity_listings.xml @@ -9,12 +9,6 @@ - - + android:layout_height="wrap_content"/>