@@ -9,115 +9,68 @@ import android.widget.RelativeLayout
99import io.github.kbiakov.codeview.Thread.delayed
1010import io.github.kbiakov.codeview.adapters.AbstractCodeAdapter
1111import io.github.kbiakov.codeview.adapters.CodeWithNotesAdapter
12+ import io.github.kbiakov.codeview.adapters.Options
1213
1314/* *
1415 * @class CodeView
1516 *
16- * Presents your code content.
17- *
18- * Before view built or started to, as the first step, placeholder
19- * measures & prepare place for code view. Amount of view params is
20- * not big, view has mutable state & non-standard initialization behavior.
21- * That is why there is no usual & well-known Builder pattern implementation.
22- *
23- * To control interaction state, being & built, was selected tasks queue.
24- * If user has already built view his task performs immediately, otherwise
25- * it puts in queue to awaiting adapter creation & processing by build flow.
26- * This helps to avoid errors & solve the init tasks in more elegant way.
17+ * View for showing code content with syntax highlighting.
2718 *
2819 * @author Kirill Biakov
2920 */
30- open class CodeView : RelativeLayout {
21+ class CodeView ( context : Context , attrs : AttributeSet ) : RelativeLayout(context, attrs) {
3122
3223 private val vShadowRight: View
3324 private val vShadowBottomLine: View
3425 private val vShadowBottomContent: View
3526
36- /* *
37- * Core view to draw code by lines.
38- */
3927 private val vCodeList: RecyclerView
4028
41- fun getRecyclerView (): RecyclerView {
42- return vCodeList
43- }
44-
4529 /* *
46- * Default constructor.
30+ * Primary constructor.
4731 */
48- constructor (context: Context , attrs: AttributeSet ) : super (context, attrs) {
49- val defaultAlpha = 0.7531f
50- var animateOnStart = true
51-
52- val a = context.theme.obtainStyledAttributes(attrs, R .styleable.CodeView , 0 , 0 )
53- try {
54- animateOnStart = a.getBoolean(R .styleable.CodeView_animateOnStart , animateOnStart)
55- } finally {
56- a.recycle()
57- }
58- animateOnStart = animateOnStart && visibility == View .VISIBLE
32+ init {
33+ val isAnimateOnStart = visibility == VISIBLE && { ctx: Context , ats: AttributeSet ->
34+ val a = ctx.theme.obtainStyledAttributes(ats, R .styleable.CodeView , 0 , 0 )
35+
36+ try {
37+ a.getBoolean(R .styleable.CodeView_animateOnStart , true )
38+ } finally {
39+ a.recycle()
40+ }
41+ }(context, attrs)
5942
60- alpha = if (animateOnStart ) 0f else defaultAlpha
43+ alpha = if (isAnimateOnStart ) 0f else Consts . ALPHA
6144
6245 inflate(context, R .layout.layout_code_view, this )
6346
64- if (animateOnStart) {
65- animate().setDuration(Utils .DELAY * 5 )
66- .alpha(defaultAlpha)
67- }
47+ if (isAnimateOnStart)
48+ animate().setDuration(Consts .DELAY * 5 )
49+ .alpha(Consts .ALPHA )
6850
69- vShadowRight = findViewById(R .id.v_shadow_right)// todo: shadow color customization
70- vShadowBottomLine = findViewById(R .id.v_shadow_bottom_line)// todo: shadow color customization
71- vShadowBottomContent = findViewById(R .id.v_shadow_bottom_content)// todo: shadow color customization
51+ // TODO: add shadow color customization
52+ vShadowRight = findViewById(R .id.v_shadow_right)
53+ vShadowBottomLine = findViewById(R .id.v_shadow_bottom_line)
54+ vShadowBottomContent = findViewById(R .id.v_shadow_bottom_content)
7255
7356 vCodeList = findViewById(R .id.rv_code_content) as RecyclerView
7457 vCodeList.layoutManager = LinearLayoutManager (context)
7558 vCodeList.isNestedScrollingEnabled = true
7659 }
7760
7861 /* *
79- * Initialize RecyclerView with adapter
80- * then start highlighting
81- */
82- fun init (h : Highlighter , adapter : AbstractCodeAdapter <* >) {
83- if (h.code.isEmpty()) {
84- throw IllegalStateException (" Please set code() before init/highlight" )
85- }
86-
87- vCodeList.adapter = adapter
88-
89- setupShadows(adapter.highlighter.shadows)
90-
91- highlight()
92- }
93-
94- /* *
95- * Initialize RecyclerView with adapter
96- * then start highlighting
97- */
98- fun init (adapter : AbstractCodeAdapter <* >) {
99- init (adapter.highlighter, adapter)
100- }
101-
102- /* *
103- * Initialize RecyclerView with adapter
104- * then start highlighting
62+ * Code adapter accessor.
10563 */
106- fun init (h : Highlighter ) {
107- init (h, CodeWithNotesAdapter (context, h))
108- }
64+ private fun getAdapter () = vCodeList.adapter as ? AbstractCodeAdapter <* >
10965
11066 /* *
11167 * Highlight code by defined programming language.
112- * It holds the placeholder on the view until code is highlighted.
68+ * It holds the placeholder on the view until code is not highlighted.
11369 */
114- fun highlight () {
115- if (vCodeList.adapter == null ) {
116- throw IllegalStateException (" Please set adapter or use init(highlighter) before highlight()" )
117- }
70+ private fun highlight () {
71+ getAdapter()?.highlight {
11872
119- getAdapter()?.highlight() {
120- animate().setDuration(Utils .DELAY * 2 )
73+ animate().setDuration(Consts .DELAY * 2 )
12174 .alpha(.1f )
12275
12376 delayed {
@@ -128,45 +81,72 @@ open class CodeView : RelativeLayout {
12881 }
12982
13083 /* *
131- * Remove code listener.
84+ * Border shadows will shown if presented full code listing.
85+ * It helps to see what part of code is scrolled & hidden.
86+ *
87+ * @param isShadows Is shadows needed
13288 */
133- fun removeLineClickListener () {
134- getAdapter()?.highlighter?.lineClickListener = null
135- }
89+ private fun setupShadows (isShadows : Boolean ) {
90+ val visibility = if (isShadows) VISIBLE else GONE
13691
137- fun getAdapter () = vCodeList.adapter as ? AbstractCodeAdapter <* >
92+ vShadowRight.visibility = visibility
93+ vShadowBottomLine.visibility = visibility
94+ vShadowBottomContent.visibility = visibility
95+ }
13896
13997 /* *
140- * Update code .
98+ * Prepare view with default adapter & options .
14199 */
142- fun update ( code : String ) {
143- getAdapter()?.updateCode(code )
100+ private fun prepare ( ) {
101+ setAdapter( CodeWithNotesAdapter (context) )
144102 }
145103
146104 /* *
147- * Update code.
105+ * Initialize with options.
106+ *
107+ * @param opts Options
148108 */
149- fun update ( h : Highlighter ) {
150- init (getAdapter() !! .highlighter.update(h ))
109+ fun setOptions ( opts : Options ) {
110+ setAdapter( CodeWithNotesAdapter (context, opts ))
151111 }
152112
153- // - Setup actions
113+ /* *
114+ * Initialize with adapter.
115+ *
116+ * @param adapter Adapter
117+ */
118+ fun setAdapter (adapter : AbstractCodeAdapter <* >) {
119+ vCodeList.adapter = adapter
120+ setupShadows(adapter.opts.shadows)
121+ highlight()
122+ }
154123
155124 /* *
156- * Border shadows will shown if presented full code listing.
157- * It helps user to see what part of code are scrolled & hidden.
125+ * Set code content.
126+ * At this point view should be prepared, otherwise it
127+ * will be configured automatically with default params.
128+ *
129+ * @param code Code content
158130 */
159- private fun setupShadows (shadows : Boolean ) {
160- val visibility = if (shadows) VISIBLE else GONE
131+ fun setCode (code : String ) {
132+ getAdapter() ? : prepare()
133+ getAdapter()?.updateCode(code)
134+ }
161135
162- vShadowRight.visibility = visibility
163- vShadowBottomLine.visibility = visibility
164- vShadowBottomContent.visibility = visibility
136+ /* *
137+ * Set code content.
138+ *
139+ * @param code Code content
140+ * @param language Programming language
141+ */
142+ fun setCode (code : String , language : String ) {
143+ getAdapter() ? : setOptions(Options (context, language = language))
144+ getAdapter()?.updateCode(code)
165145 }
166146}
167147
168148/* *
169- * Provides listener to code line clicks.
149+ * Provide listener to code line clicks.
170150 */
171151interface OnCodeLineClickListener {
172152 fun onLineClicked (n : Int , line : String )
0 commit comments