// Path: src/main/java/com/athaydes/logfx/data/LogLineColors.java
// public class LogLineColors {
// 
//     private final Paint background;
//     private final Paint fill;
// 
//     public LogLineColors( Paint background, Paint fill ) {
//         this.background = background;
//         this.fill = fill;
//     }
// 
//     public Paint getBackground() {
//         return background;
//     }
// 
//     public Paint getFill() {
//         return fill;
//     }
// }
// 
// Path: src/main/java/com/athaydes/logfx/text/HighlightExpression.java
// public final class HighlightExpression {
// 
//     private final Pattern expression;
//     private final Paint bkgColor;
//     private final Paint fillColor;
//     private final boolean isFiltered;
// 
//     public HighlightExpression( String expression, Paint bkgColor, Paint fillColor, boolean isFiltered ) {
//         this( Pattern.compile( expression ), bkgColor, fillColor, isFiltered );
//     }
// 
//     public HighlightExpression( Pattern expression, Paint bkgColor, Paint fillColor, boolean isFiltered ) {
//         this.expression = expression;
//         this.bkgColor = bkgColor;
//         this.fillColor = fillColor;
//         this.isFiltered = isFiltered;
//     }
// 
//     public Paint getBkgColor() {
//         return bkgColor;
//     }
// 
//     public Paint getFillColor() {
//         return fillColor;
//     }
// 
//     public Pattern getPattern() {
//         return expression;
//     }
// 
//     public boolean isFiltered() {
//         return isFiltered;
//     }
// 
//     public LogLineColors getLogLineColors() {
//         return new LogLineColors( bkgColor, fillColor );
//     }
// 
//     public boolean matches( String text ) {
//         if ( text == null ) {
//             text = "";
//         }
// 
//         // the find method does not anchor the String by default, unlike matches()
//         return expression.matcher( text ).find();
//     }
// 
//     public HighlightExpression withFilter( boolean enable ) {
//         return new HighlightExpression( this.expression, this.bkgColor, this.fillColor, enable );
//     }
// 
//     @Override
//     public String toString() {
//         return "{" +
//                 "expression=" + expression +
//                 ", bkgColor=" + bkgColor +
//                 ", fillColor=" + fillColor +
//                 ", isFiltered=" + isFiltered +
//                 '}';
//     }
// 
//     @Override
//     public boolean equals( Object o ) {
//         if ( this == o ) return true;
//         if ( o == null || getClass() != o.getClass() ) return false;
//         HighlightExpression that = ( HighlightExpression ) o;
//         return isFiltered == that.isFiltered &&
//                 expression.toString().equals( that.expression.toString() ) &&
//                 bkgColor.equals( that.bkgColor ) &&
//                 fillColor.equals( that.fillColor );
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash( expression.toString(), bkgColor, fillColor, isFiltered );
//     }
// }
// 
// Path: src/main/java/com/athaydes/logfx/ui/AwesomeIcons.java
// public static final String HELP = "\ue718";
// 
// Path: src/main/java/com/athaydes/logfx/ui/AwesomeIcons.java
// public static final String TRASH = "\ue605";
// 
// Path: src/main/java/com/athaydes/logfx/ui/FxUtils.java
// public static String resourcePath( String name ) {
//     return resourceUrl( name ).toExternalForm();
// }


import com.athaydes.logfx.data.LogLineColors;
import com.athaydes.logfx.text.HighlightExpression;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.StageStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.function.BiFunction;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;
import static com.athaydes.logfx.ui.Arrow.Direction.DOWN;
import static com.athaydes.logfx.ui.Arrow.Direction.UP;
import static com.athaydes.logfx.ui.AwesomeIcons.HELP;
import static com.athaydes.logfx.ui.AwesomeIcons.TRASH;
import static com.athaydes.logfx.ui.FxUtils.resourcePath;
                    Arrow.arrowButton( UP, moveUpEventHandler(), "Move rule up" ),
                    Arrow.arrowButton( DOWN, moveDownEventHandler(), "Move rule down" ) );
            return upDownArrows;
        }

        private EventHandler<ActionEvent> moveUpEventHandler() {
            return event -> {
                int index = observableExpressions.indexOf( expression );
                if ( index > 0 ) {
                    observableExpressions.remove( index );
                    parent.getChildren().remove( index );
                    observableExpressions.add( index - 1, expression );
                    parent.getChildren().add( index - 1, this );
                }
            };
        }

        private EventHandler<ActionEvent> moveDownEventHandler() {
            return event -> {
                int index = observableExpressions.indexOf( expression );
                if ( index < observableExpressions.size() - 1 ) {
                    observableExpressions.remove( index );
                    parent.getChildren().remove( index );
                    observableExpressions.add( index + 1, expression );
                    parent.getChildren().add( index + 1, this );
                }
            };
        }

        private Node removeButton() {
// Path: src/main/java/com/athaydes/logfx/data/LogLineColors.java
// public class LogLineColors {
// 
//     private final Paint background;
//     private final Paint fill;
// 
//     public LogLineColors( Paint background, Paint fill ) {
//         this.background = background;
//         this.fill = fill;
//     }
// 
//     public Paint getBackground() {
//         return background;
//     }
// 
//     public Paint getFill() {
//         return fill;
//     }
// }
// 
// Path: src/main/java/com/athaydes/logfx/text/HighlightExpression.java
// public final class HighlightExpression {
// 
//     private final Pattern expression;
//     private final Paint bkgColor;
//     private final Paint fillColor;
//     private final boolean isFiltered;
// 
//     public HighlightExpression( String expression, Paint bkgColor, Paint fillColor, boolean isFiltered ) {
//         this( Pattern.compile( expression ), bkgColor, fillColor, isFiltered );
//     }
// 
//     public HighlightExpression( Pattern expression, Paint bkgColor, Paint fillColor, boolean isFiltered ) {
//         this.expression = expression;
//         this.bkgColor = bkgColor;
//         this.fillColor = fillColor;
//         this.isFiltered = isFiltered;
//     }
// 
//     public Paint getBkgColor() {
//         return bkgColor;
//     }
// 
//     public Paint getFillColor() {
//         return fillColor;
//     }
// 
//     public Pattern getPattern() {
//         return expression;
//     }
// 
//     public boolean isFiltered() {
//         return isFiltered;
//     }
// 
//     public LogLineColors getLogLineColors() {
//         return new LogLineColors( bkgColor, fillColor );
//     }
// 
//     public boolean matches( String text ) {
//         if ( text == null ) {
//             text = "";
//         }
// 
//         // the find method does not anchor the String by default, unlike matches()
//         return expression.matcher( text ).find();
//     }
// 
//     public HighlightExpression withFilter( boolean enable ) {
//         return new HighlightExpression( this.expression, this.bkgColor, this.fillColor, enable );
//     }
// 
//     @Override
//     public String toString() {
//         return "{" +
//                 "expression=" + expression +
//                 ", bkgColor=" + bkgColor +
//                 ", fillColor=" + fillColor +
//                 ", isFiltered=" + isFiltered +
//                 '}';
//     }
// 
//     @Override
//     public boolean equals( Object o ) {
//         if ( this == o ) return true;
//         if ( o == null || getClass() != o.getClass() ) return false;
//         HighlightExpression that = ( HighlightExpression ) o;
//         return isFiltered == that.isFiltered &&
//                 expression.toString().equals( that.expression.toString() ) &&
//                 bkgColor.equals( that.bkgColor ) &&
//                 fillColor.equals( that.fillColor );
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash( expression.toString(), bkgColor, fillColor, isFiltered );
//     }
// }
// 
// Path: src/main/java/com/athaydes/logfx/ui/AwesomeIcons.java
// public static final String HELP = "\ue718";
// 
// Path: src/main/java/com/athaydes/logfx/ui/AwesomeIcons.java
// public static final String TRASH = "\ue605";
// 
// Path: src/main/java/com/athaydes/logfx/ui/FxUtils.java
// public static String resourcePath( String name ) {
//     return resourceUrl( name ).toExternalForm();
// }


// Path: src/main/java/com/athaydes/logfx/ui/HighlightOptions.java
import com.athaydes.logfx.data.LogLineColors;
import com.athaydes.logfx.text.HighlightExpression;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.StageStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.function.BiFunction;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;
import static com.athaydes.logfx.ui.Arrow.Direction.DOWN;
import static com.athaydes.logfx.ui.Arrow.Direction.UP;
import static com.athaydes.logfx.ui.AwesomeIcons.HELP;
import static com.athaydes.logfx.ui.AwesomeIcons.TRASH;
import static com.athaydes.logfx.ui.FxUtils.resourcePath;

                    Arrow.arrowButton( UP, moveUpEventHandler(), "Move rule up" ),
                    Arrow.arrowButton( DOWN, moveDownEventHandler(), "Move rule down" ) );
            return upDownArrows;
        }

        private EventHandler<ActionEvent> moveUpEventHandler() {
            return event -> {
                int index = observableExpressions.indexOf( expression );
                if ( index > 0 ) {
                    observableExpressions.remove( index );
                    parent.getChildren().remove( index );
                    observableExpressions.add( index - 1, expression );
                    parent.getChildren().add( index - 1, this );
                }
            };
        }

        private EventHandler<ActionEvent> moveDownEventHandler() {
            return event -> {
                int index = observableExpressions.indexOf( expression );
                if ( index < observableExpressions.size() - 1 ) {
                    observableExpressions.remove( index );
                    parent.getChildren().remove( index );
                    observableExpressions.add( index + 1, expression );
                    parent.getChildren().add( index + 1, this );
                }
            };
        }

        private Node removeButton() {
            Button removeButton = AwesomeIcons.createIconButton( TRASH );