From 1759f6b25cea972590b9c7736ffcacb469b9bec2 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sun, 22 Aug 2021 17:26:29 +0200 Subject: [PATCH] Theme Editor: increment/decrement color parts (red, green, blue or alpha) at caret using `Ctrl+UP`/`Ctrl+DOWN` --- .../FlatSyntaxTextAreaActions.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatSyntaxTextAreaActions.java b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatSyntaxTextAreaActions.java index 60d76f90..d5614c78 100644 --- a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatSyntaxTextAreaActions.java +++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatSyntaxTextAreaActions.java @@ -92,15 +92,24 @@ class FlatSyntaxTextAreaActions @Override public void actionPerformedImpl( ActionEvent e, RTextArea textArea ) { + if( !incrementRGBColor( textArea ) ) + incrementNumber( textArea ); + } + + private void incrementNumber( RTextArea textArea ) { try { int caretPosition = textArea.getCaretPosition(); int start = caretPosition; int end = caretPosition; + + // find first digit for( int i = caretPosition - 1; i >= 0; i-- ) { if( !Character.isDigit( textArea.getText( i, 1 ).charAt( 0 ) ) ) break; start = i; } + + // find last digit int length = textArea.getDocument().getLength(); for( int i = caretPosition; i < length; i++ ) { if( !Character.isDigit( textArea.getText( i, 1 ).charAt( 0 ) ) ) @@ -111,8 +120,11 @@ class FlatSyntaxTextAreaActions if( start == end ) return; + // parse number String str = textArea.getText( start, end - start ); long number = Long.parseLong( str ); + + // increment/decrement number if( increment ) number++; else @@ -121,12 +133,89 @@ class FlatSyntaxTextAreaActions if( number < 0 ) return; + // update editor textArea.replaceRange( Long.toString( number ), start, end ); } catch( BadLocationException | IndexOutOfBoundsException | NumberFormatException ex ) { ex.printStackTrace(); } } + private boolean incrementRGBColor( RTextArea textArea ) { + try { + int caretPosition = textArea.getCaretPosition(); + int start = caretPosition; + int end = caretPosition; + + // find first '#' or hex digit + for( int i = caretPosition - 1; i >= 0; i-- ) { + char ch = textArea.getText( i, 1 ).charAt( 0 ); + if( ch != '#' && !isHexDigit( ch ) ) + break; + start = i; + } + + // find last hex digit + int length = textArea.getDocument().getLength(); + for( int i = caretPosition; i < length; i++ ) { + if( !isHexDigit( textArea.getText( i, 1 ).charAt( 0 ) ) ) + break; + end = i + 1; + } + + // check for valid length (#RGB, #RGBA, #RRGGBB or #RRGGBBAA) + int len = end - start; + if( len != 4 && len != 5 && len != 7 && len != 9 ) + return false; + + // check whether starts with '#' + if( textArea.getText( start, 1 ).charAt( 0 ) != '#' ) + return false; + + // find start of color part that should be changed (red, green, blue or alpha) + int start2; + int hexDigitCount = (len == 4 || len == 5) ? 1 : 2; + if( hexDigitCount == 1 ) { + // #RGB or #RGBA + start2 = caretPosition - 1; + } else { + // #RRGGBB or #RRGGBBAA + int offset = caretPosition - (start + 1); + offset += (offset % 2); + start2 = start + 1 + offset - 2; + } + start2 = Math.max( start2, start + 1 ); + + // parse number + String str = textArea.getText( start2, hexDigitCount ); + int number = Integer.parseInt( str, 16 ); + + // increment/decrement number + if( increment ) + number++; + else + number--; + + // wrap numbers if less than zero or too large + int maxNumber = (hexDigitCount == 1) ? 15 : 255; + if( number < 0 ) + number = maxNumber; + else if( number > maxNumber ) + number = 0; + + // update editor + String newStr = String.format( hexDigitCount == 1 ? "%1x" : "%02x", number ); + textArea.replaceRange( newStr, start2, start2 + hexDigitCount ); + return true; + } catch( BadLocationException | IndexOutOfBoundsException | NumberFormatException ex ) { + ex.printStackTrace(); + return false; + } + } + + private boolean isHexDigit( char ch ) { + return Character.isDigit( ch ) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); + } + @Override public String getMacroID() { return getName();