From 2f5ea8d45e2632d48f7829b0148586ba158a96c8 Mon Sep 17 00:00:00 2001 From: Christopher Keenan Date: Wed, 29 Dec 2021 16:40:58 -0600 Subject: [PATCH] Updated README file --- README.md | 215 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 121 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 23c1f17..27c81d1 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,50 @@ # chords -An easily customizable Kotlin multi-platform View to display guitar (and other stringed instrument) chords. -Simple to use and beautifully designed. +An easily customizable Kotlin multi-platform View to display guitar (and other stringed instrument) chords. Simple to +use and beautifully designed. **Current Version:** ![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/chrynan/chords) Sample Screenshot Sample Screenshot -This library has been updated significantly from its original version and the process is detailed in this [blog post](https://chrynan.codes/converting-an-old-java-library-to-kotlin/) which was featured in Android Weekly issue #398. +This library has been updated significantly from its original version and the process is detailed in +this [blog post](https://chrynan.codes/converting-an-old-java-library-to-kotlin/) which was featured in Android Weekly +issue #398. Badge ## Building the library -The library is provided through [Repsy.io](https://repsy.io). Checkout the [releases page](https://github.com/chRyNaN/chords/releases) to get the latest version.
+The library is provided through [Repsy.io](https://repsy.io). Checkout +the [releases page](https://github.com/chRyNaN/chords/releases) to get the latest version.
GitHub tag (latest by date) ### Repository ```groovy repositories { - maven { url = "https://repo.repsy.io/mvn/chrynan/public" } + maven { url = uri("https://repo.repsy.io/mvn/chrynan/public") } } ``` ### Dependencies -**Core Kotlin Common:** +**core:** + ```kotlin implementation("com.chrynan.chords:chords-core:VERSION") ``` -**Core Kotlin JVM:** -```kotlin -implementation("com.chrynan.chords:chords-core-jvm:VERSION") -``` +**compose:** -**Core Kotlin JS:** ```kotlin -implementation("com.chrynan.chords:chords-core-js:VERSION") +implementation("com.chrynan.chords:chords-compose:VERSION") ``` -**Android Library:** -```kotlin -implementation("com.chrynan.chords:chords-android:VERSION") -``` +## Usage -## Using the library There are a few main components to using the library: * `ChordWidget` is the `ChordView` implementation that displays the chord. @@ -58,75 +54,76 @@ There are a few main components to using the library: ### Creating an instance of `ChordWidget` **Android:** + ```xml + android:id="@+id/chordWidget" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> ``` **Kotlin JS:** + ```kotlin val widget = ChordWidget(htmlCanvas) ``` **Jetpack Compose:** + ```kotlin -@Composable -fun MyLayout(chord: Chord, chart: ChordChart, viewModel: ChordViewModel) { - ChordWidget( - modifier = Modifier.size(width = 200.dp, height = 200.dp), - chord = chord, - chart = chart, - viewModel = viewModel - ) -} +ChordWidget( + modifier = Modifier.size(width = 200.dp, height = 200.dp), + chord = chord, + chart = chart +) ``` ### Assigning a `ChordChart` to a `ChordWidget` ```kotlin chordWidget?.chart = ChordChart( - fretStart = FretNumber(1), - fretEnd = FretNumber(2), - stringCount = 6, - stringLabels = setOf( - StringLabel(string = StringNumber(1), label = "e"), - StringLabel(string = StringNumber(2), label = "B"), - StringLabel(string = StringNumber(3), label = "G"), - StringLabel(string = StringNumber(4), label = "D"), - StringLabel(string = StringNumber(5), label = "A"), - StringLabel(string = StringNumber(6), label = "E"))) + fretStart = FretNumber(1), + fretEnd = FretNumber(2), + stringCount = 6, + stringLabels = setOf( + StringLabel(string = StringNumber(1), label = "e"), + StringLabel(string = StringNumber(2), label = "B"), + StringLabel(string = StringNumber(3), label = "G"), + StringLabel(string = StringNumber(4), label = "D"), + StringLabel(string = StringNumber(5), label = "A"), + StringLabel(string = StringNumber(6), label = "E") + ) +) ``` ### Creating a Chord using the DSL ```kotlin val chord = chord("G") { - +ChordMarker.Note( - fret = FretNumber(3), - finger = Finger.MIDDLE, - string = StringNumber(6) - ) - +ChordMarker.Note( - fret = FretNumber(2), - finger = Finger.INDEX, - string = StringNumber(5) - ) - +ChordMarker.Open(string = StringNumber(4)) - +ChordMarker.Open(string = StringNumber(3)) - +ChordMarker.Note( - fret = FretNumber(3), - finger = Finger.RING, - string = StringNumber(2) - ) - +ChordMarker.Note( - fret = FretNumber(3), - finger = Finger.PINKY, - string = StringNumber(1) - ) - } + +ChordMarker.Note( + fret = FretNumber(3), + finger = Finger.MIDDLE, + string = StringNumber(6) + ) + +ChordMarker.Note( + fret = FretNumber(2), + finger = Finger.INDEX, + string = StringNumber(5) + ) + +ChordMarker.Open(string = StringNumber(4)) + +ChordMarker.Open(string = StringNumber(3)) + +ChordMarker.Note( + fret = FretNumber(3), + finger = Finger.RING, + string = StringNumber(2) + ) + +ChordMarker.Note( + fret = FretNumber(3), + finger = Finger.PINKY, + string = StringNumber(1) + ) +} ``` ### Assigning a `Chord` to a `ChordWidget` @@ -135,16 +132,19 @@ val chord = chord("G") { chordWidget?.chord = chord ``` -**Note:** This library doesn't try to coerce values to fit into a chart or exclude values that exceed the chart bounds. If the `ChordChart` and `Chord` have inconsistent values, the `ChordWidget` may look peculiar. -It's important for the user of the library to properly handle coordinating the different components. +**Note:** This library doesn't try to coerce values to fit into a chart or exclude values that exceed the chart bounds. +If the `ChordChart` and `Chord` have inconsistent values, the `ChordWidget` may look peculiar. It's important for the +user of the library to properly handle coordinating the different components. ### Parsing Chords from other formats -The `ChordParser` interface takes in an input type and outputs a `ChordParseResult`. This interface can be implemented for different format input types. There are a couple provided `ChordParser` implementations. +The `ChordParser` interface takes in an input type and outputs a `ChordParseResult`. This interface can be implemented +for different format input types. There are a couple provided `ChordParser` implementations. **AsciiChordParser:** -`AsciiChordParser` parses a `String` input of an ASCII Chord Diagram and outputs a `ChordParseResult` containing a `Chord`. +`AsciiChordParser` parses a `String` input of an ASCII Chord Diagram and outputs a `ChordParseResult` containing +a `Chord`. ```kotlin val chordDiagram = """ @@ -172,7 +172,8 @@ launch { **ChordProParser:** -`ChordProParser` parses a `String` input of a Chord Pro (Chord or Define) Directive and outputs a `ChordParseResult` containing a `Chord`. +`ChordProParser` parses a `String` input of a Chord Pro (Chord or Define) Directive and outputs a `ChordParseResult` +containing a `Chord`. ```kotlin val chordDiagram = "{define: Bes base-fret 1 frets 1 1 3 3 3 1 fingers 1 1 2 3 4 1}" @@ -183,7 +184,7 @@ launch { // parse() is a suspending function and needs to be called from another suspending // function or a coroutine val result = parser.parse(chordDiagram) - + val chord: Chord = result.chord val stringLabels: Set = result.stringLabels val baseFret: FretNumber? = result.baseFret @@ -195,6 +196,7 @@ launch { `ChordWidget` implements the `ChordView` interface which contains properties to alter the appearance of the view. **ChordView:** + ```kotlin interface ChordView { @@ -229,32 +231,39 @@ interface ChordView { ``` **Updating properties directly on ChordWidget:** + ```kotlin chordWidget?.noteColor = Color.BLUE chordWidget?.openStringText = "o" ``` -**Note:** That in Kotlin JS, you have to explicitly call the `render()` function after updating properties on the `ChordWidget`. +**Note:** That in Kotlin JS, you have to explicitly call the `render()` function after updating properties on +the `ChordWidget`. **Updating properties using a ViewModel and Binder:** + ```kotlin val binder = ChordViewBinder(chordWidget) - + val viewModel = ChordViewModel( - fretColor = Color.BLACK, - fretLabelTextColor = Color.WHITE, - stringLabelTextColor = Color.BLACK, - stringColor = Color.BLACK, - noteColor = Color.BLACK, - noteLabelTextColor = Color.WHITE) + fretColor = Color.BLACK, + fretLabelTextColor = Color.WHITE, + stringLabelTextColor = Color.BLACK, + stringColor = Color.BLACK, + noteColor = Color.BLACK, + noteLabelTextColor = Color.WHITE +) binder.bind(viewModel) ``` -**Note:** That in Kotlin JS, there is a convenience function `ChordViewBinder.bindAndRender()` which will bind the properties from the `ChordViewModel` to the `ChordWidget` and call `render()`. +**Note:** That in Kotlin JS, there is a convenience function `ChordViewBinder.bindAndRender()` which will bind the +properties from the `ChordViewModel` to the `ChordWidget` and call `render()`. **Updating properties in Android XML:** + ```xml + @@ -276,9 +287,9 @@ binder.bind(viewModel) - - - + + + @@ -288,9 +299,11 @@ binder.bind(viewModel) ### Selectable Chord names in Text using Android Spans -The library comes with a `ChordSpan` which allows the pairing of text with a `Chord`. And when the `ChordSpan` is selected, a listener is alerted with the `Chord`. +The library comes with a `ChordSpan` which allows the pairing of text with a `Chord`. And when the `ChordSpan` is +selected, a listener is alerted with the `Chord`. **Adding a `ChordSpan` to a `TextView`:** + ```kotlin val text = SpannableString("G") val span = ChordSpan(chord, this) // "this" refers to the listener @@ -303,17 +316,18 @@ textView?.movementMethod = LinkTouchMovementMethod() ``` **Using DSL functions to add a `ChordSpan` to a `TextView`:** + ```kotlin val textBuilder = buildSpannableString { - +chordSpan(chord, listener) + +chordSpan(chord, listener) - +chordSpan("G", chord) { - // Handle click event - } + +chordSpan("G", chord) { + // Handle click event + } - +styledChordSpan(chord, listener) { - this.backgroundColor = Color.BLUE - } + +styledChordSpan(chord, listener) { + this.backgroundColor = Color.BLUE + } } textView?.text = textBuilder @@ -322,6 +336,7 @@ textView?.movementMethod = LinkTouchMovementMethod() ``` **Listening to `Chord` selected events:** + ```kotlin class MainActivity : AppCompatActivity(), ChordSpan.ChordSelectedListener { @@ -334,7 +349,9 @@ class MainActivity : AppCompatActivity(), **Customizing the `ChordSpan` appearance:** -`ChordSpan` extends from `TouchableSpan` which inherits from `TouchableSpanView` and has the following customizable properties: +`ChordSpan` extends from `TouchableSpan` which inherits from `TouchableSpanView` and has the following customizable +properties: + ```kotlin var backgroundColor = Color.TRANSPARENT var selectedBackgroundColor = Color.TRANSPARENT @@ -347,17 +364,22 @@ var selectedTextTypeface = Typeface.DEFAULT ``` These properties can be changed on the span: + ```kotlin span.textColor = Color.RED ``` ### Passing Chords between Android components -The model classes are not `Parcelable` because they are in a Kotlin multi-platform module and don't have access to Android Framework classes. But the Android library module does have wrapper classes that handle the serialization and de-serialization of the `Chord` and `ChordChart` models. +The model classes are not `Parcelable` because they are in a Kotlin multi-platform module and don't have access to +Android Framework classes. But the Android library module does have wrapper classes that handle the serialization and +de-serialization of the `Chord` and `ChordChart` models. + +These classes are `ParcelableChordWrapper` and `ParcelableChartWrapper`. To pass `Chord` and `ChordChart` between +components, such as, in a Bundle, just wrap them with their respective wrapper models. -These classes are `ParcelableChordWrapper` and `ParcelableChartWrapper`. To pass `Chord` and `ChordChart` between components, such as, in a Bundle, just wrap them with their respective wrapper models. ```kotlin -arguments = +arguments = Bundle().apply { putParcelable(KEY_CHORD, ParcelableChordWrapper(chord)) putParcelable(KEY_CHART, ParcelableChartWrapper(chart)) @@ -365,14 +387,17 @@ arguments = ``` Then retrieve the wrappers just as you would with any other Parcelable object. + ```kotlin arguments?.getParcelable(KEY_CHORD) arguments?.getParcelable(KEY_CHART) ``` -For convenience, there are extension functions on the `Bundle` and `Intent` objects which handle the wrapping and unwrapping of the `Chord` and `ChordChart` objects. +For convenience, there are extension functions on the `Bundle` and `Intent` objects which handle the wrapping and +unwrapping of the `Chord` and `ChordChart` objects. **Bundle:** + ```kotlin arguments = Bundle().apply { @@ -385,6 +410,7 @@ val chart = arguments?.getChordChart(KEY_CHART) ``` **Intent:** + ```kotlin intent.putChord(KEY_CHORD, chord) intent.putChordChart(KEY_CHART, chart) @@ -393,7 +419,8 @@ val chord = intent.getChordExtra(KEY_CHORD) val chart = intent.getChordChartExtra(KEY_CHART) ``` -There is also a convenience `ChordAndChart` class (with similar Parcelable extension functions) for when both a `Chord` and a `ChordChart` need to be passed between Android components together. +There is also a convenience `ChordAndChart` class (with similar Parcelable extension functions) for when both a `Chord` +and a `ChordChart` need to be passed between Android components together. ```kotlin val chordAndChart = ChordAndChart(chord = chord, chart = chordChart)