Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code cleanup, new languages + AndroidX #60

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# CodeView (Android)

[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-codeview--android-blue.svg)](https://android-arsenal.com/details/1/4216)
[![Release](https://jitpack.io/v/kbiakov/CodeView-android.svg)](https://jitpack.io/#kbiakov/CodeView-Android)
[![Release](https://jitpack.io/v/kbiakov/CodeView-Android.svg)](https://jitpack.io/#kbiakov/CodeView-Android)
[![Build Status](https://travis-ci.org/kbiakov/CodeView-android.svg?branch=master)](https://travis-ci.org/kbiakov/CodeView-Android)
<a href="http://www.methodscount.com/?lib=com.github.kbiakov%3ACodeView-android%3A1.3.0"><img src="https://img.shields.io/badge/Methods and size-core: 969 | 1396 KB-e91e63.svg"/></a>

Expand Down Expand Up @@ -226,11 +226,11 @@ List of apps on Play Store where this library used. Ping me if you want to be he
Icon | Application
------------ | -------------
<img src="https://goo.gl/ijEiBp" width="48" height="48" /> | [GeekBrains]
<img src="https://goo.gl/4VhHbn" width="48" height="48" /> | [Awesome Android - UI Libraries]
<img src="https://goo.gl/1AGK1b" width="48" height="48" /> | [Codify - Codes On The Go]
<img src="https://goo.gl/jcGMmS" width="48" height="48" /> | [C Programming - 200+ Offline Tutorial and Examples]
<img src="https://goo.gl/4VhHbn" width="48" height="48" /> | [Awesome Android - UI Libraries]
<img src="https://goo.gl/UPsE9F" width="48" height="48" /> | [GitJourney for GitHub]
<img src="https://goo.gl/kNqAc7" width="48" height="48" /> | [Source Code - Lập Trình]
<img src="https://goo.gl/jcGMmS" width="48" height="48" /> | [C Programming - CodeSpot]

## Contribute
1. You can add your theme (see [ColorTheme](https://github.com/Softwee/codeview-android/blob/master/codeview/src/main/java/io/github/kbiakov/codeview/highlight/CodeHighlighter.kt) class). Try to add some classic color themes or create your own if it looks cool. You can find many of them in different open-source text editors.<br>
Expand Down Expand Up @@ -264,8 +264,8 @@ SOFTWARE.
```

[GeekBrains]:https://play.google.com/store/apps/details?id=ru.geekbrains
[Codify - Codes On The Go]:https://play.google.com/store/apps/details?id=com.femindharamshi.spa
[C Programming - 200+ Offline Tutorial and Examples]:https://play.google.com/store/apps/details?id=com.rsd.cprogramming
[Awesome Android - UI Libraries]:https://play.google.com/store/apps/details?id=in.sumeetlubal.aweandroid.aweandroid
[GitJourney for GitHub]:https://play.google.com/store/apps/details?id=com.oklab.githubjourney
[Codify - Codes On The Go]:https://play.google.com/store/apps/details?id=com.femindharamshi.spa
[Source Code - Lập Trình]:https://play.google.com/store/apps/details?id=com.noah.truongpq.codeview
[C Programming - CodeSpot]:https://play.google.com/store/apps/details?id=com.rsd.cprogramming
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlinVersion = '1.3.11'
ext.kotlinVersion = '1.3.21'
ext.minSdk = 15
ext.compileSdk = 28
ext.buildTools = '28.0.3'
ext.supportLibrary = '28.0.0'
ext.androidxLibrary = '1.1.0-alpha02'

repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.0'
classpath 'com.android.tools.build:gradle:3.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
}
Expand Down
4 changes: 2 additions & 2 deletions codeview/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ android {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation "com.android.support:appcompat-v7:$supportLibrary"
implementation "com.android.support:recyclerview-v7:$supportLibrary"
implementation "androidx.appcompat:appcompat:$androidxLibrary"
implementation "androidx.recyclerview:recyclerview:$androidxLibrary"
}
147 changes: 66 additions & 81 deletions codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package io.github.kbiakov.codeview
import android.content.Context
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.util.AttributeSet
import android.view.View
import android.widget.RelativeLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.github.kbiakov.codeview.Thread.delayed
import io.github.kbiakov.codeview.adapters.AbstractCodeAdapter
import io.github.kbiakov.codeview.adapters.CodeWithNotesAdapter
Expand All @@ -18,7 +18,7 @@ import io.github.kbiakov.codeview.highlight.color
/**
* @class CodeView
*
* View for showing code content with syntax highlighting.
* Display code with syntax highlighting.
*
* @author Kirill Biakov
*/
Expand All @@ -28,8 +28,9 @@ class CodeView @JvmOverloads constructor(
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr) {

private val vCodeList: RecyclerView
private val vShadows: Map<ShadowPosition, View>
private val rvContent: RecyclerView
private val shadows: Map<ShadowPosition, View>
private val adapter get() = rvContent.adapter as? AbstractCodeAdapter<*>

/**
* Primary constructor.
Expand All @@ -38,12 +39,12 @@ class CodeView @JvmOverloads constructor(
inflate(context, R.layout.layout_code_view, this)
attrs?.let(::checkStartAnimation)

vCodeList = findViewById<RecyclerView>(R.id.rv_code_content).apply {
rvContent = findViewById<RecyclerView>(R.id.rv_content).apply {
layoutManager = LinearLayoutManager(context)
isNestedScrollingEnabled = true
}

vShadows = mapOf(
shadows = mapOf(
ShadowPosition.RightBorder to R.id.shadow_right_border,
ShadowPosition.NumBottom to R.id.shadow_num_bottom,
ShadowPosition.ContentBottom to R.id.shadow_content_bottom
Expand Down Expand Up @@ -78,39 +79,27 @@ class CodeView @JvmOverloads constructor(
}
}

/**
* Highlight code with defined programming language.
* It holds the placeholder on view until code is not highlighted.
*/
private fun highlight() {
getAdapter()?.apply {
highlight {
checkHighlightAnimation(::notifyDataSetChanged)
}
}
}

/**
* Border shadows will shown if full listing presented.
* It helps to see what part of code is scrolled & hidden.
* It helps to see which part of code is scrolled & hidden.
*
* @param isVisible Is shadows visible
*/
fun setupShadows(isVisible: Boolean) {
val visibility = if (isVisible) VISIBLE else GONE
val theme = getOptionsOrDefault().theme
vShadows.forEach { (pos, view) ->
val theme = optionsOrDefault.theme
shadows.forEach { (pos, view) ->
view.visibility = visibility
view.setSafeBackground(pos.createShadow(theme))
}
}

// - Initialization
// - Options

/**
* Prepare view with default adapter & options.
* View options accessor.
*/
private fun prepare() = setAdapter(CodeWithNotesAdapter(context))
private val optionsOrDefault get() = adapter?.options ?: Options(context)

/**
* Initialize with options.
Expand All @@ -119,102 +108,98 @@ class CodeView @JvmOverloads constructor(
*/
fun setOptions(options: Options) = setAdapter(CodeWithNotesAdapter(context, options))

/**
* Initialize with adapter.
*
* @param adapter Adapter
*/
fun setAdapter(adapter: AbstractCodeAdapter<*>) {
vCodeList.adapter = adapter
highlight()
}

// - Options

/**
* View options accessor.
*/
fun getOptions() = getAdapter()?.options
fun getOptionsOrDefault() = getOptions() ?: Options(context)

/**
* Update options or initialize if needed.
*
* @param options Options
*/
fun updateOptions(options: Options) {
getAdapter() ?: setOptions(options)
getAdapter()?.options = options
adapter
?.let { it.options = options }
?: setOptions(options)

setupShadows(options.shadows)
}

fun updateOptions(body: Options.() -> Unit) {
val options = getOptions() ?: getOptionsOrDefault()
updateOptions(options.apply(body))
}
/**
* Update options or initialize if needed.
*
* @param body Options mutator
*/
fun updateOptions(body: Options.() -> Unit) =
optionsOrDefault
.apply(body)
.apply(::updateOptions)

// - Adapter

/**
* Code adapter accessor.
* Initialize with adapter.
*
* Highlight code with defined programming language.
* It holds the placeholder on view until code is not highlighted.
*
* @param adapter Adapter
*/
fun getAdapter() = vCodeList.adapter as? AbstractCodeAdapter<*>
fun setAdapter(adapter: AbstractCodeAdapter<*>) {
rvContent.adapter = adapter.apply {
highlight { checkHighlightAnimation(::notifyDataSetChanged) }
}
}

/**
* Update adapter or initialize if needed.
*
* @param adapter Adapter
* @param isUseCurrent Use options that are already set or default
*/
fun updateAdapter(adapter: AbstractCodeAdapter<*>) {
adapter.options = getOptionsOrDefault()
setAdapter(adapter)
fun updateAdapter(adapter: AbstractCodeAdapter<*>, isUseCurrent: Boolean) {
setAdapter(adapter.apply {
if (isUseCurrent) {
options = optionsOrDefault
}
})
}

// - Set code

/**
* Set code content.
*
* There are two ways before code will be highlighted:
* 1) view is not initialized (adapter or options are not set),
* Set code content. View is:
* 1) not initialized (adapter or options is not set):
* prepare with default params & try to classify language
* 2) view initialized with some params, language:
* a) is set: used defined programming language
* 2) initialized (with some params), language is:
* a) set: use defined
* b) not set: try to classify
*
* @param code Code content
*/
fun setCode(code: String) {
getAdapter() ?: prepare()
getAdapter()?.updateCode(code)
}
fun setCode(code: String) = setCode(code, null)

/**
* Set code content.
*
* There are two ways before code will be highlighted:
* 1) view is not initialized, prepare with default params
* 2) view initialized with some params, set new language
* Set code content. View is:
* 1) not initialized: prepare with default params
* 2) initialized (with some params): set new language
*
* @param code Code content
* @param language Programming language
*/
fun setCode(code: String, language: String) {
val options = getOptionsOrDefault()
updateOptions(options.withLanguage(language))
getAdapter()?.updateCode(code)
fun setCode(code: String, language: String? = null) {
val options = optionsOrDefault.apply {
this.language = language
}
(adapter ?: CodeWithNotesAdapter(context, options)
.apply(::setAdapter))
.updateCode(code)
}

companion object {

private fun AttributeSet.isAnimateOnStart(context: Context): Boolean {
context.theme.obtainStyledAttributes(this, R.styleable.CodeView, 0, 0).apply {
val flag = getBoolean(R.styleable.CodeView_animateOnStart, false)
recycle()
return@isAnimateOnStart flag
}
return false
}
private fun AttributeSet.isAnimateOnStart(context: Context) =
context.theme.obtainStyledAttributes(this, R.styleable.CodeView, 0, 0).run {
val isAnimate = getBoolean(R.styleable.CodeView_animateOnStart, false)
recycle()
isAnimate
}

private fun View.setSafeBackground(newBackground: Drawable) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
Expand Down
8 changes: 8 additions & 0 deletions codeview/src/main/java/io/github/kbiakov/codeview/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ object Thread {
Handler(Looper.getMainLooper()).post(body)
}

/**
* Perform async and UI operations sequentially.
*
* @param asyncBody Async operation body
* @param uiBody UI operation body
*/
fun <T> asyncUi(asyncBody: () -> T, uiBody: (T) -> Unit) = async { asyncBody().also { ui { uiBody(it)} } }

/**
* Delayed block call.
*
Expand Down
Loading