Skip to content

Commit

Permalink
Dynamic widget improvements to Table.filter. (#12032)
Browse files Browse the repository at this point in the history
- Only shows relevant filter conditions for the selected columns.
- Only show relevant columns and constants for the right hand side.

https://github.com/user-attachments/assets/fe2ab7dd-27bb-401b-8827-55a0d8742d78
  • Loading branch information
jdunkerley authored Jan 17, 2025
1 parent 7cde786 commit fb6f842
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ Text.characters self =
example_find_insensitive =
## This matches `aBc` @ character 11
"aabbbbccccaaBcaaaa".find "a[ab]c" Case_Sensitivity.Insensitive
@pattern make_regex_text_widget
Text.find : (Regex | Text) -> Case_Sensitivity -> Match | Nothing ! Regex_Syntax_Error | Illegal_Argument
Text.find self pattern:(Regex | Text)=".*" case_sensitivity:Case_Sensitivity=..Sensitive =
case_insensitive = case_sensitivity.is_case_insensitive_in_memory
Expand Down Expand Up @@ -299,6 +300,7 @@ Text.find self pattern:(Regex | Text)=".*" case_sensitivity:Case_Sensitivity=..S
example_find_all_insensitive =
## This matches `aABbbbc` @ character 0 and `aBC` @ character 11
"aABbbbccccaaBCaaaa".find_all "a[ab]+c" Case_Sensitivity.Insensitive
@pattern make_regex_text_widget
Text.find_all : Text|Regex -> Case_Sensitivity -> Vector Match ! Regex_Syntax_Error | Illegal_Argument
Text.find_all self pattern:Text|Regex=".*" case_sensitivity:Case_Sensitivity=..Sensitive =
case_insensitive = case_sensitivity.is_case_insensitive_in_memory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ type DB_Table
@column (Widget_Helpers.make_column_name_selector add_expression=True)
@filter Widget_Helpers.make_filter_condition_selector
filter : (DB_Column | Text | Integer) -> (Filter_Condition | (Any -> Boolean)) -> Problem_Behavior -> DB_Table ! No_Such_Column | Index_Out_Of_Bounds | Invalid_Value_Type
filter self column (filter : Filter_Condition | (Any -> Boolean) = Filter_Condition.Equal True) on_problems:Problem_Behavior=..Report_Warning =
filter self column=(Missing_Argument.throw "column") (filter : Filter_Condition | (Any -> Boolean) = Filter_Condition.Equal True) on_problems:Problem_Behavior=..Report_Warning =
Feature.Filter.if_supported_else_throw self.connection.dialect "filter" <|
case column of
_ : DB_Column ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ from Standard.Base.System.File_Format import format_types
from Standard.Base.Widget_Helpers import make_any_selector, make_format_chooser

import project.Aggregate_Column.Aggregate_Column
import project.Expression.Expression
import project.Internal.Parse_Values_Helper
import project.Join_Condition.Join_Condition
import project.Join_Kind.Join_Kind
Expand Down Expand Up @@ -101,6 +102,27 @@ make_column_ref_by_name_selector table display:Display=..Always add_text:Boolean
values = if columns_first then col_names + constants + expression else constants + expression + col_names
Single_Choice values=values display=display

## PRIVATE
Make a column reference by name selector filtered by type.
make_column_ref_by_name_selector_for_type table display:Display=..Always value_type:Value_Type add_nothing:Boolean=False =
is_all = include_all value_type
include_number = is_all || value_type.is_numeric
include_text = is_all || value_type.is_text
include_boolean = is_all || value_type.is_boolean
include_date = is_all || value_type.is_date
include_date_time = is_all || value_type.is_date_time
include_time = is_all || value_type.is_time

constants = make_any_selector add_text=include_text add_number=include_number add_boolean=include_boolean add_date=include_date add_time=include_time add_date_time=include_date_time add_nothing=add_nothing . values
expression = if table.is_nothing then [] else [Option "<Expression>" "(expr '["+table.column_names.first+"]')"]

col_names = if table.is_nothing then [] else
names = if is_all then table.column_names else (table.select_columns [..By_Type value_type, ..By_Type Value_Type.Mixed] . column_names)
names.map (name -> Option name "(..Name "+name.pretty+")")

values = constants + expression + col_names
Single_Choice values=values display=display

## PRIVATE
If `column_source` is Nothing, `Column_Ref` options will not be added.
make_fill_default_value_selector column_source=Nothing display:Display=..Always value_types=Value_Type.Mixed add_nothing:Boolean=False =
Expand All @@ -111,38 +133,52 @@ make_fill_default_value_selector column_source=Nothing display:Display=..Always

## PRIVATE
Make a filter condition selector.
make_filter_condition_selector table display:Display=..Always =
equatable_types = make_column_ref_by_name_selector table add_text=True add_number=True add_boolean=True add_date=True add_time=True add_date_time=True
comparable_types = make_column_ref_by_name_selector table add_text=True add_number=True add_date=True add_time=True add_date_time=True
with_text = make_column_ref_by_name_selector table add_text=True
make_filter_condition_selector table display:Display=..Always cache=Nothing =
column_value_type = get_column_value_type table cache
column_chooser = make_column_ref_by_name_selector_for_type table display add_nothing=False value_type=column_value_type

is_all = include_all column_value_type
include_text = is_all || column_value_type.is_text
include_boolean = is_all || column_value_type.is_boolean
include_floating = is_all || column_value_type.is_floating_point

options = Vector.build builder->
builder.append (Option "Equals" "..Equal" [["to", equatable_types]])
builder.append (Option "Not Equals" "..Not_Equal" [["to", equatable_types]])
builder.append (Option "Less Than" "..Less" [["than", comparable_types]])
builder.append (Option "Less Than Or Equal" "..Equal_Or_Less" [["than", comparable_types]])
builder.append (Option "Greater Than" "..Greater" [["than", comparable_types]])
builder.append (Option "Greater Than Or Equal" "..Equal_Or_Greater" [["than", comparable_types]])
builder.append (Option "Between" "..Between" [["lower", comparable_types], ["upper", comparable_types]])
builder.append (Option "Equals Ignore Case" "..Equal_Ignore_Case" [["to", with_text]])
builder.append (Option "Starts With" "..Starts_With" [["prefix", with_text]])
builder.append (Option "Ends With" "..Ends_With" [["suffix", with_text]])
builder.append (Option "Contains" "..Contains" [["substring", with_text]])
builder.append (Option "Like" "..Like" [["pattern", with_text]])
builder.append (Option "Equals" "..Equal" [["to", column_chooser]])
builder.append (Option "Not Equals" "..Not_Equal" [["to", column_chooser]])

if column_value_type.has_ordering && column_value_type!=Value_Type.Boolean then
builder.append (Option "Less Than" "..Less" [["than", column_chooser]])
builder.append (Option "Less Than Or Equal" "..Equal_Or_Less" [["than", column_chooser]])
builder.append (Option "Greater Than" "..Greater" [["than", column_chooser]])
builder.append (Option "Greater Than Or Equal" "..Equal_Or_Greater" [["than", column_chooser]])
builder.append (Option "Between" "..Between" [["lower", column_chooser], ["upper", column_chooser]])

if include_text then
builder.append (Option "Equals Ignore Case" "..Equal_Ignore_Case" [["to", column_chooser]])
builder.append (Option "Starts With" "..Starts_With" [["prefix", column_chooser]])
builder.append (Option "Ends With" "..Ends_With" [["suffix", column_chooser]])
builder.append (Option "Contains" "..Contains" [["substring", column_chooser]])
builder.append (Option "Like" "..Like" [["pattern", column_chooser]])

builder.append (Option "Is Nothing" "..Is_Nothing")
builder.append (Option "Is Not Nothing" "..Not_Nothing")
builder.append (Option "Is True" "..Is_True")
builder.append (Option "Is False" "..Is_False")

value_editor = Widget.Vector_Editor item_editor=equatable_types display=Display.Always item_default='""'
if include_boolean then
builder.append (Option "Is True" "..Is_True")
builder.append (Option "Is False" "..Is_False")

value_editor = Widget.Vector_Editor item_editor=column_chooser display=Display.Always item_default='""'
builder.append (Option "Is In" "..Is_In" [["values", value_editor]])

builder.append (Option "Is Finite" "..Is_Finite")
builder.append (Option "Is Infinite" "..Is_Infinite")
builder.append (Option "Is NaN" "..Is_Nan")
builder.append (Option "Is Not NaN" "..Not_Nan")
builder.append (Option "Is Empty" "..Is_Empty")
builder.append (Option "Is Not Empty" "..Not_Empty")
if include_floating then
builder.append (Option "Is Finite" "..Is_Finite")
builder.append (Option "Is Infinite" "..Is_Infinite")
builder.append (Option "Is NaN" "..Is_Nan")
builder.append (Option "Is Not NaN" "..Not_Nan")

if include_text then
builder.append (Option "Is Empty" "..Is_Empty")
builder.append (Option "Is Not Empty" "..Not_Empty")
Single_Choice options display=display

## PRIVATE
Expand Down Expand Up @@ -300,3 +336,22 @@ type Types_To_Include
ICON metadata
Are there any date_time columns?
date_time self = self.types.any value_type-> value_type.is_date_time || value_type==Value_Type.Mixed

## PRIVATE
private get_column_value_type table cache parameter:Text="column" default:Value_Type=Value_Type.Mixed =
raw_column = cache.if_not_nothing <| cache parameter
column = case raw_column of
Nothing -> Nothing
_ : Text -> table.get raw_column
_ : Expression -> table.evaluate_expression raw_column ..Ignore
_ -> raw_column
Panic.catch Any handler=_->default <|
if Nothing == column then default else column.value_type

## PRIVATE
Treat Value_Type as if it could be any type (i.e. include all constants and types).
private include_all value_type:Value_Type -> Boolean =
case value_type of
Value_Type.Mixed -> True
Value_Type.Unsupported_Data_Type _ _ -> True
_ -> False
2 changes: 1 addition & 1 deletion distribution/lib/Standard/Table/0.0.0-dev/src/Table.enso
Original file line number Diff line number Diff line change
Expand Up @@ -2161,7 +2161,7 @@ type Table
@column (Widget_Helpers.make_column_name_selector add_expression=True)
@filter Widget_Helpers.make_filter_condition_selector
filter : (Column | Expression | Text | Integer) -> (Filter_Condition | (Any -> Boolean)) -> Problem_Behavior -> Table ! No_Such_Column | Index_Out_Of_Bounds | Invalid_Value_Type
filter self column (filter : Filter_Condition | (Any -> Boolean) = Filter_Condition.Equal True) on_problems:Problem_Behavior=..Report_Warning = case column of
filter self column=(Missing_Argument.throw "column") (filter : Filter_Condition | (Any -> Boolean) = Filter_Condition.Equal True) on_problems:Problem_Behavior=..Report_Warning = case column of
_ : Column ->
mask filter_column = Table.Value (self.java_table.filter filter_column.java_column)
filter_condition = Filter_Condition.resolve_auto_scoped filter
Expand Down

0 comments on commit fb6f842

Please sign in to comment.