Skip to content

Commit b07530b

Browse files
committed
Added ability to add own view under line
1 parent d6267e5 commit b07530b

File tree

5 files changed

+124
-18
lines changed

5 files changed

+124
-18
lines changed

codeview/src/main/java/io/github/kbiakov/codeview/CodeContentAdapter.kt

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import android.support.v7.widget.RecyclerView
55
import android.view.LayoutInflater
66
import android.view.View
77
import android.view.ViewGroup
8+
import android.widget.LinearLayout
9+
import android.widget.RelativeLayout
810
import android.widget.TextView
911
import io.github.kbiakov.codeview.classifier.CodeProcessor
1012
import io.github.kbiakov.codeview.highlight.*
@@ -32,6 +34,12 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
3234

3335
internal var codeListener: OnCodeLineClickListener?
3436

37+
internal var lineNotes: HashMap<Int, List<String>>
38+
set(lineNotes) {
39+
field = lineNotes
40+
notifyDataSetChanged()
41+
}
42+
3543
internal var colorTheme: ColorThemeData
3644
set(colorTheme) {
3745
field = colorTheme
@@ -42,6 +50,7 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
4250
mLines = ArrayList()
4351
mDroppedLines = null
4452
isFullShowing = true
53+
lineNotes = HashMap()
4554
colorTheme = ColorTheme.SOLARIZED_LIGHT.with()
4655
}
4756

@@ -81,7 +90,7 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
8190
* @param shortcutNote Note will shown below code for listing shortcut
8291
*/
8392
private fun initCodeContent(isShowFull: Boolean,
84-
shortcutNote: String = mContext.getString(R.string.show_all)) {
93+
shortcutNote: String = showAllBottomNote()) {
8594
var lines: MutableList<String> = ArrayList(extractLines(mContent))
8695
isFullShowing = isShowFull || lines.size <= mMaxLines // limit is not reached
8796

@@ -106,6 +115,18 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
106115
notifyDataSetChanged()
107116
}
108117

118+
/**
119+
* Add note to code line.
120+
*
121+
* @param num Line number
122+
* @param note Note content
123+
*/
124+
fun addLineNote(num: Int, note: String) {
125+
val notes = lineNotes[num] ?: ArrayList()
126+
lineNotes.put(num, notes + note)
127+
notifyDataSetChanged()
128+
}
129+
109130
/**
110131
* Highlight code content.
111132
*
@@ -134,7 +155,7 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
134155
}
135156
}
136157

137-
// - Helpers
158+
// - Helpers (for accessors)
138159

139160
private fun updateContent(codeLines: List<String>, onUpdated: () -> Unit) {
140161
ui {
@@ -153,6 +174,8 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
153174
updateContent(lines, onReady)
154175
}
155176

177+
private fun showAllBottomNote() = mContext.getString(R.string.show_all)
178+
156179
private fun monoTypeface() = MonoFontCache.getInstance(mContext).typeface
157180

158181
// - View holder
@@ -178,10 +201,20 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
178201
holder.mItem = codeLine
179202

180203
holder.itemView.setOnClickListener {
181-
codeListener?.onCodeLineClicked(position + 1, codeLine)
204+
codeListener?.onCodeLineClicked(position, codeLine)
182205
}
183206

184-
holder.tvLineContent.text = html(codeLine)
207+
setupLine(position, codeLine, holder)
208+
displayLineNotes(position, holder)
209+
addExtraPadding(position, holder)
210+
}
211+
212+
override fun getItemCount() = mLines.size
213+
214+
// Helpers (for view holder)
215+
216+
private fun setupLine(position: Int, line: String, holder: ViewHolder) {
217+
holder.tvLineContent.text = html(line)
185218

186219
if (!isFullShowing && position == MAX_SHORTCUT_LINES) {
187220
holder.tvLineNum.textSize = 10f
@@ -191,31 +224,44 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
191224
holder.tvLineNum.textSize = 12f
192225
holder.tvLineNum.text = "${position + 1}"
193226
}
194-
195-
addExtraPadding(position, holder.itemView, holder.tvLineNum, holder.tvLineContent)
196227
}
197228

198-
override fun getItemCount() = mLines.size
229+
private fun displayLineNotes(position: Int, holder: ViewHolder) {
230+
val notes = lineNotes[position]
231+
232+
holder.llLineNotes.removeAllViews()
199233

200-
private fun addExtraPadding(position: Int, itemView: View,
201-
tvLineNum: TextView, tvLineContent: TextView) {
234+
notes?.let {
235+
holder.llLineNotes.visibility = if (it.isNotEmpty()) View.VISIBLE else View.GONE
236+
237+
it.forEach { note ->
238+
val noteView = LineNoteView.create(mContext, note, colorTheme.noteColor.color())
239+
holder.llLineNotes.addView(noteView)
240+
}
241+
}
242+
}
243+
244+
private fun addExtraPadding(position: Int, holder: ViewHolder) {
202245
val dp8 = dpToPx(mContext, 8)
203246
val isFirst = position == 0
204247
val isLast = position == itemCount - 1
205248

206249
if (isFirst || isLast) {
207-
itemView.layoutParams.height = dp8 * 4
250+
// itemView.layoutParams.height = dp8 * 4
208251

209252
val topPadding = if (isFirst) dp8 else 0
210253
val bottomPadding = if (isLast) dp8 else 0
211-
tvLineNum.setPadding(0, topPadding, 0, bottomPadding)
212-
tvLineContent.setPadding(0, topPadding, 0, bottomPadding)
254+
holder.tvLineNum.setPadding(0, topPadding, 0, bottomPadding)
255+
holder.tvLineContent.setPadding(0, topPadding, 0, bottomPadding)
213256
} else {
214-
itemView.layoutParams.height = dp8 * 3
257+
// itemView.layoutParams.height = dp8 * 3
215258

216-
tvLineNum.setPadding(0, 0, 0, 0)
217-
tvLineContent.setPadding(0, 0, 0, 0)
259+
holder.tvLineNum.setPadding(0, 0, 0, 0)
260+
holder.tvLineContent.setPadding(0, 0, 0, 0)
218261
}
262+
263+
// TODO: measure height
264+
// holder.tvLineNum.layoutParams.height = holder.itemView.layoutParams.height
219265
}
220266

221267
companion object {
@@ -225,12 +271,16 @@ class CodeContentAdapter : RecyclerView.Adapter<CodeContentAdapter.ViewHolder> {
225271
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
226272
var tvLineNum: TextView
227273
var tvLineContent: TextView
274+
var rlLineBlock: RelativeLayout
275+
var llLineNotes: LinearLayout
228276

229277
var mItem: String? = null
230278

231279
init {
232280
tvLineNum = itemView.findViewById(R.id.tv_line_num) as TextView
233281
tvLineContent = itemView.findViewById(R.id.tv_line_content) as TextView
282+
rlLineBlock = itemView.findViewById(R.id.rl_line_block) as RelativeLayout
283+
llLineNotes = itemView.findViewById(R.id.ll_line_notes) as LinearLayout
234284
}
235285

236286
override fun toString() = "${super.toString()} '$mItem'"

codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,25 @@ class CodeView : RelativeLayout {
192192
vShadowBottomContent.visibility = visibility
193193
}
194194

195+
/**
196+
* Add notes to code snippet.
197+
*
198+
* @param notes Map of notes (line number -> list of notes)
199+
*/
200+
fun addLineNotes(notes: HashMap<Int, List<String>>) = addTask {
201+
adapter.lineNotes = notes
202+
}
203+
204+
/**
205+
* Add note to code line.
206+
*
207+
* @param num Line number
208+
* @param note Note content
209+
*/
210+
fun addLineNote(num: Int, note: String) = addTask {
211+
adapter.addLineNote(num, note)
212+
}
213+
195214
/**
196215
* Update code content if view was built or, finally, build code view.
197216
*
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.github.kbiakov.codeview
2+
3+
import android.content.Context
4+
import android.widget.TextView
5+
6+
class LineNoteView(context: Context?) : TextView(context) {
7+
8+
companion object Factory {
9+
fun create(context: Context, text: String, textColor: Int): LineNoteView {
10+
val noteView = LineNoteView(context)
11+
noteView.textSize = 12f
12+
noteView.text = text
13+
noteView.setTextColor(textColor)
14+
return noteView
15+
}
16+
}
17+
}

codeview/src/main/res/layout/item_code_line.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
<RelativeLayout
33
xmlns:android="http://schemas.android.com/apk/res/android"
44
android:layout_width="match_parent"
5-
android:layout_height="wrap_content">
5+
android:layout_height="wrap_content"
6+
android:animateLayoutChanges="true">
67

78
<TextView
89
android:id="@+id/tv_line_num"
@@ -26,4 +27,13 @@
2627
android:textSize="12sp"
2728
android:text="@string/stub_line_content"/>
2829

30+
<!--
31+
<LinearLayout
32+
android:id="@+id/ll_line_notes"
33+
android:layout_width="match_parent"
34+
android:layout_height="match_parent"
35+
android:layout_below="@+id/tv_line_content"
36+
android:orientation="vertical"
37+
android:visibility="gone"/>-->
38+
2939
</RelativeLayout>

example/src/main/java/io/github/kbiakov/codeviewexample/ListingsActivity.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
import android.support.annotation.Nullable;
55
import android.support.v7.app.AppCompatActivity;
66

7+
import org.jetbrains.annotations.NotNull;
8+
79
import io.github.kbiakov.codeview.CodeView;
10+
import io.github.kbiakov.codeview.OnCodeLineClickListener;
811
import io.github.kbiakov.codeview.highlight.ColorTheme;
912

1013
public class ListingsActivity extends AppCompatActivity {
@@ -16,7 +19,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
1619

1720
//int myColor = ContextCompat.getColor(this, R.color.code_content_background);
1821

19-
CodeView codeView = (CodeView) findViewById(R.id.code_view);
22+
final CodeView codeView = (CodeView) findViewById(R.id.code_view);
2023

2124
// use chaining to build view
2225
codeView.highlightCode("js")
@@ -25,8 +28,15 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
2528

2629
// do not use chaining for built view
2730
// (you can, but follow it should be performed sequentially)
28-
codeView.setCodeContent(getString(R.string.listing_java));
31+
codeView.setCodeContent(getString(R.string.mark));
2932
codeView.setColorTheme(ColorTheme.DEFAULT);
3033
codeView.highlightCode("java");
34+
35+
codeView.setCodeListener(new OnCodeLineClickListener() {
36+
@Override
37+
public void onCodeLineClicked(int n, @NotNull String line) {
38+
codeView.addLineNote(n, line);
39+
}
40+
});
3141
}
3242
}

0 commit comments

Comments
 (0)