Skip to content

Commit

Permalink
TextAction: Add text case changing functionality (closes gsantner#2390,…
Browse files Browse the repository at this point in the history
… PR gsantner#2426)

* This commit introduces the ability to change text case within the editor,
addressing issue gsantner#2390. Users can now toggle case, switch case,
capitalize words, and capitalize sentences directly from the Edit menu.
* Added an example to the display text of each text case.
zeuchie authored Oct 11, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent ed3f20f commit f8aab77
Showing 6 changed files with 179 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -652,6 +652,26 @@ public void onFsViewerConfig(GsFileBrowserOptions.Options dopt) {
}, 250);
return true;
}
case R.id.action_toggle_case:
if (_hlEditor != null) {
_hlEditor.toggleCase();
}
return true;
case R.id.action_switch_case:
if (_hlEditor != null) {
_hlEditor.switchCase();
}
return true;
case R.id.action_capitalize_words:
if (_hlEditor != null) {
_hlEditor.capitalizeWords();
}
return true;
case R.id.action_capitalize_sentences:
if (_hlEditor != null) {
_hlEditor.capitalizeSentences();
}
return true;
default: {
return super.onOptionsItemSelected(item);
}
Original file line number Diff line number Diff line change
@@ -33,7 +33,9 @@
import net.gsantner.opoc.format.GsTextUtils;
import net.gsantner.opoc.wrapper.GsCallback;
import net.gsantner.opoc.wrapper.GsTextWatcherAdapter;
import net.gsantner.markor.util.TextCasingUtils;

import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -297,6 +299,60 @@ private int rowEnd(final int y) {
return layout.getLineEnd(line);
}

// Text-Casing
// ---------------------------------------------------------------------------------------------
public void toggleCase() {
String text = getSelectedText();
if (text.isEmpty()) {
text = Objects.requireNonNull(getText()).toString();
}
String newText = TextCasingUtils.toggleCase(text);
replaceSelection(newText);
}

public void switchCase() {
String text = getSelectedText();
if (text.isEmpty()) {
text = Objects.requireNonNull(getText()).toString();
}
String newText = TextCasingUtils.switchCase(text);
replaceSelection(newText);
}

public void capitalizeWords() {
String text = getSelectedText();
if (text.isEmpty()) {
text = Objects.requireNonNull(getText()).toString();
}
String newText = TextCasingUtils.capitalizeWords(text);
replaceSelection(newText);
}

public void capitalizeSentences() {
String text = getSelectedText();
if (text.isEmpty()) {
text = Objects.requireNonNull(getText()).toString();
}
String newText = TextCasingUtils.capitalizeSentences(text);
replaceSelection(newText);
}

private String getSelectedText() {
int start = Math.max(0, getSelectionStart());
int end = Math.max(0, getSelectionEnd());
return Objects.requireNonNull(getText()).toString().substring(start, end);
}

private void replaceSelection(String replacement) {
int start = Math.max(0, getSelectionStart());
int end = Math.max(0, getSelectionEnd());
if (start == end) { // If no selection is made, replace all the text in the document
setText(replacement);
} else { // Replace only the selected text
Objects.requireNonNull(getText()).replace(start, end, replacement);
}
}

// Various overrides
// ---------------------------------------------------------------------------------------------
public void setSaveInstanceState(final boolean save) {
61 changes: 61 additions & 0 deletions app/src/main/java/net/gsantner/markor/util/TextCasingUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package net.gsantner.markor.util;

public class TextCasingUtils {
public static String toggleCase(String text) { // Toggle all text to Uppercase or Lowercase
if (text.equals(text.toUpperCase())) {
return text.toLowerCase();
} else {
return text.toUpperCase();
}
}

public static String switchCase(String text) { // Switch the text case of each character
StringBuilder result = new StringBuilder();
for (char c : text.toCharArray()) {
if (Character.isUpperCase(c)) {
result.append(Character.toLowerCase(c));
} else if (Character.isLowerCase(c)) {
result.append(Character.toUpperCase(c));
} else {
result.append(c);
}
}
return result.toString();
}

public static String capitalizeWords(String text) { // Capitalize the first letter of each word
StringBuilder result = new StringBuilder();
boolean capitalizeNext = true;
for (char c : text.toCharArray()) {
if (Character.isWhitespace(c)) {
capitalizeNext = true;
result.append(c);
} else if (capitalizeNext) {
result.append(Character.toUpperCase(c));
capitalizeNext = false;
} else {
result.append(Character.toLowerCase(c));
}
}
return result.toString();
}

public static String capitalizeSentences(String text) { // Capitalize the first letter of each sentence
StringBuilder result = new StringBuilder();
boolean capitalizeNext = true;
for (char c : text.toCharArray()) {
if (c == '.' || c == '!' || c == '?') {
capitalizeNext = true;
result.append(c);
} else if (Character.isWhitespace(c)) {
result.append(c);
} else if (capitalizeNext) {
result.append(Character.toUpperCase(c));
capitalizeNext = false;
} else {
result.append(c);
}
}
return result.toString();
}
}
12 changes: 12 additions & 0 deletions app/src/main/res/drawable/ic_format_text_case_black_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M16.51,3C16.82,3 17.1,3.2 17.21,3.5L22.71,19C22.85,19.39 22.64,19.82 22.25,19.96C21.86,20.1 21.43,19.89 21.29,19.5L19.87,15.5H12.76L11.2,19.52C11.05,19.91 10.62,20.1 10.23,19.95C9.84,19.8 9.65,19.37 9.8,18.98L15.8,3.48C15.91,3.19 16.2,3 16.51,3ZM16.47,5.91L13.34,14H19.34L16.47,5.91Z"/>
<path
android:fillColor="#FF000000"
android:pathData="M5.5,10.5L5.79,10.51C7.75,10.61 8.91,11.74 9,13.56L9,13.76V19.26C9,19.64 8.72,19.95 8.35,20L8.25,20.01C7.87,20.01 7.56,19.73 7.51,19.36L7.5,19.26L7.5,19.16C6.51,19.72 5.6,20.01 4.75,20.01C2.91,20.01 1.5,18.72 1.5,16.76C1.5,15.04 2.69,13.75 4.66,13.52C5.59,13.4 6.54,13.47 7.5,13.73C7.49,12.62 6.94,12.07 5.71,12.01C4.75,11.96 4.07,12.1 3.68,12.37C3.34,12.61 2.87,12.53 2.63,12.19C2.4,11.85 2.48,11.38 2.82,11.15C3.47,10.69 4.37,10.48 5.5,10.5ZM7.5,15.32L7.2,15.23C6.39,15.01 5.6,14.95 4.84,15.04C3.61,15.19 3,15.85 3,16.8C3,17.89 3.71,18.55 4.75,18.55C5.43,18.55 6.27,18.23 7.25,17.58L7.5,17.41V15.32Z"/>
</vector>
25 changes: 25 additions & 0 deletions app/src/main/res/menu/document__edit__menu.xml
Original file line number Diff line number Diff line change
@@ -103,6 +103,31 @@
android:title="@string/font_size"
app:showAsAction="never" />

<!-- Text Case menu -->
<item
android:id="@+id/action_text_case"
android:icon="@drawable/ic_format_text_case_black_24dp"
android:title="@string/text_case"
app:showAsAction="never">
<menu>
<item
android:id="@+id/action_toggle_case"
android:title="@string/toggle_case" />

<item
android:id="@+id/action_switch_case"
android:title="@string/switch_case" />

<item
android:id="@+id/action_capitalize_words"
android:title="@string/capitalize_words" />

<item
android:id="@+id/action_capitalize_sentences"
android:title="@string/capitalize_sentences" />
</menu>
</item>

<!-- Format menu -->
<item
android:id="@+id/submenu_format_selection"
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -477,4 +477,9 @@ work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
<string name="wont_save_min_length">Files with fewer than %d characters not saved automatically in order to prevent data loss.</string>
<string name="advanced_filtering_help"><![CDATA[<small><a href="https://www.github.com/gsantner/markor/discussions/1940">Advanced filtering syntax</a></small>]]></string>
<string name="filter">Filter</string>
<string name="text_case">Text Case</string>
<string name="toggle_case">Toggle Case (Ex: Case->CASE->case)</string>
<string name="switch_case">Switch Case (Ex: CaSe->cAsE)</string>
<string name="capitalize_words">Capitalize Words (Ex: a note->A Note)</string>
<string name="capitalize_sentences">Capitalize Sentences (Ex: case->Case)</string>
</resources>

0 comments on commit f8aab77

Please sign in to comment.