1
- use std:: sync :: Arc ;
1
+ use std:: mem ;
2
2
3
- use egui:: { Frame , Margin } ;
3
+ use egui:: { Atom , AtomLayout , Atoms , Frame , Margin , Sense } ;
4
4
5
5
use re_ui:: { SyntaxHighlighting , UiExt as _, syntax_highlighting:: SyntaxHighlightedBuilder } ;
6
6
@@ -117,65 +117,35 @@ impl FilterState {
117
117
let active_index = self . active_filter . take ( ) ;
118
118
let mut remove_idx = None ;
119
119
120
- // TODO(#11194): ideally, egui would allow wrapping `Frame` widget itself. Remove
121
- // this when it does.
122
- let prepared_uis = self
123
- . filters
124
- . iter ( )
125
- . map ( |filter| filter. prepare_ui ( ui) )
126
- . collect :: < Vec < _ > > ( ) ;
127
- let item_spacing = ui. style ( ) . spacing . item_spacing . x ;
128
- let available_width = ui. available_width ( ) ;
129
- let mut rows = vec1:: vec1![ vec![ ] ] ;
130
- let mut current_left_position = 0.0 ;
131
- for ( index, prepared_ui) in prepared_uis. iter ( ) . enumerate ( ) {
132
- if current_left_position > 0.0
133
- && current_left_position + prepared_ui. desired_width ( ) > available_width
134
- {
135
- rows. push ( vec ! [ ] ) ;
136
- current_left_position = 0.0 ;
137
- }
138
-
139
- rows. last_mut ( ) . push ( index) ;
140
- current_left_position += prepared_ui. desired_width ( ) + item_spacing;
141
- }
142
-
143
- for row in rows {
144
- ui. horizontal ( |ui| {
145
- for index in row {
146
- let filter = & mut self . filters [ index] ;
147
-
148
- // egui uses this id to store the popup openness and size information,
149
- // so we must invalidate if the filter at a given index changes its
150
- // nature
151
- let filter_id = ui. make_persistent_id ( egui:: Id :: new ( index) . with (
152
- match filter. operation {
153
- FilterOperation :: IntCompares { .. } => "int" ,
154
- FilterOperation :: FloatCompares { .. } => "float" ,
155
- FilterOperation :: StringContains ( _) => "string" ,
156
- FilterOperation :: Boolean ( _) => "bool" ,
157
- } ,
158
- ) ) ;
159
-
160
- let prepared_ui = & prepared_uis[ index] ;
161
-
162
- let result =
163
- filter. ui ( ui, prepared_ui, filter_id, Some ( index) == active_index) ;
164
-
165
- action = action. merge ( result. filter_action ) ;
166
-
167
- if result. should_delete_filter {
168
- remove_idx = Some ( index) ;
169
- }
120
+ ui. horizontal_wrapped ( |ui| {
121
+ for ( index, filter) in self . filters . iter_mut ( ) . enumerate ( ) {
122
+ // egui uses this id to store the popup openness and size information,
123
+ // so we must invalidate if the filter at a given index changes its
124
+ // nature
125
+ let filter_id = ui. make_persistent_id ( egui:: Id :: new ( index) . with (
126
+ match filter. operation {
127
+ FilterOperation :: IntCompares { .. } => "int" ,
128
+ FilterOperation :: FloatCompares { .. } => "float" ,
129
+ FilterOperation :: StringContains ( _) => "string" ,
130
+ FilterOperation :: Boolean ( _) => "bool" ,
131
+ } ,
132
+ ) ) ;
133
+
134
+ let result = filter. ui ( ui, filter_id, Some ( index) == active_index) ;
135
+
136
+ action = action. merge ( result. filter_action ) ;
137
+
138
+ if result. should_delete_filter {
139
+ remove_idx = Some ( index) ;
170
140
}
171
- } ) ;
172
- }
141
+ }
173
142
174
- if let Some ( remove_idx) = remove_idx {
175
- self . active_filter = None ;
176
- self . filters . remove ( remove_idx) ;
177
- should_commit = true ;
178
- }
143
+ if let Some ( remove_idx) = remove_idx {
144
+ self . active_filter = None ;
145
+ self . filters . remove ( remove_idx) ;
146
+ should_commit = true ;
147
+ }
148
+ } ) ;
179
149
} ) ;
180
150
181
151
action
@@ -188,79 +158,65 @@ struct DisplayFilterUiResult {
188
158
should_delete_filter : bool ,
189
159
}
190
160
191
- // TODO(#11194): used by the manual wrapping code. Remove when no longer needed.
192
- struct FilterPreparedUi {
193
- frame : Frame ,
194
- galley : Arc < egui:: Galley > ,
195
- desired_width : f32 ,
196
- }
197
-
198
- impl FilterPreparedUi {
199
- fn desired_width ( & self ) -> f32 {
200
- self . desired_width
201
- }
202
- }
203
-
204
161
impl Filter {
205
- /// Prepare the UI for this filter
206
- fn prepare_ui ( & self , ui : & egui:: Ui ) -> FilterPreparedUi {
207
- let layout_job = SyntaxHighlightedBuilder :: new ( )
208
- . with_body ( & self . column_name )
209
- . with_keyword ( " " )
210
- . with ( & self . operation )
211
- . into_job ( ui. style ( ) ) ;
212
-
213
- let galley = ui. fonts ( |f| f. layout_job ( layout_job) ) ;
214
-
215
- let frame = Frame :: new ( )
216
- . inner_margin ( Margin :: symmetric ( 4 , 4 ) )
217
- . stroke ( ui. tokens ( ) . table_filter_frame_stroke )
218
- . corner_radius ( 2.0 ) ;
219
-
220
- let desired_width = galley. size ( ) . x
221
- + ui. style ( ) . spacing . item_spacing . x
222
- + ui. tokens ( ) . small_icon_size . x
223
- + frame. total_margin ( ) . sum ( ) . x ;
224
-
225
- FilterPreparedUi {
226
- frame,
227
- galley,
228
- desired_width,
229
- }
162
+ pub fn close_button_id ( ) -> egui:: Id {
163
+ egui:: Id :: new ( "filter_close_button" )
230
164
}
231
165
232
166
/// UI for a single filter.
233
167
#[ must_use]
234
168
fn ui (
235
169
& mut self ,
236
170
ui : & mut egui:: Ui ,
237
- prepared_ui : & FilterPreparedUi ,
238
171
filter_id : egui:: Id ,
239
172
activate_filter : bool ,
240
173
) -> DisplayFilterUiResult {
241
174
let mut should_delete_filter = false ;
242
175
let mut action_due_to_filter_deletion = FilterUiAction :: None ;
243
176
244
- let response = prepared_ui
245
- . frame
246
- . show ( ui, |ui| {
247
- let text_response = ui. add (
248
- egui:: Label :: new ( Arc :: clone ( & prepared_ui. galley ) )
249
- . selectable ( false )
250
- . sense ( egui:: Sense :: click ( ) ) ,
251
- ) ;
252
-
253
- if ui
254
- . small_icon_button ( & re_ui:: icons:: CLOSE_SMALL , "Remove filter" )
255
- . clicked ( )
256
- {
257
- should_delete_filter = true ;
258
- action_due_to_filter_deletion = FilterUiAction :: CommitStateToBlueprint ;
259
- }
177
+ let mut atoms = Atoms :: default ( ) ;
260
178
261
- text_response
262
- } )
263
- . inner ;
179
+ let layout_job = SyntaxHighlightedBuilder :: new ( )
180
+ . with_body_default ( & self . column_name )
181
+ . with_keyword ( " " )
182
+ . with ( & self . operation )
183
+ . into_job ( ui. style ( ) ) ;
184
+
185
+ atoms. push_right ( layout_job) ;
186
+
187
+ atoms. push_right ( Atom :: custom (
188
+ Self :: close_button_id ( ) ,
189
+ ui. tokens ( ) . small_icon_size ,
190
+ ) ) ;
191
+
192
+ let frame = Frame :: new ( )
193
+ . inner_margin ( Margin :: symmetric ( 4 , 4 ) )
194
+ . stroke ( ui. tokens ( ) . table_filter_frame_stroke )
195
+ . corner_radius ( 2.0 ) ;
196
+
197
+ let atom_layout = AtomLayout :: new ( atoms) . sense ( Sense :: click ( ) ) . frame ( frame) ;
198
+
199
+ let atom_response = atom_layout. show ( ui) ;
200
+
201
+ if let Some ( rect) = atom_response. rect ( Self :: close_button_id ( ) ) {
202
+ // The default padding is (1.0, 0.0), making the button look weird
203
+ let button_padding = mem:: take ( & mut ui. style_mut ( ) . spacing . button_padding ) ;
204
+ if ui
205
+ . place (
206
+ rect,
207
+ ui. small_icon_button_widget ( & re_ui:: icons:: CLOSE_SMALL , "Remove filter" )
208
+ // Without small the button would grow to interact_size and be off-center
209
+ . small ( ) ,
210
+ )
211
+ . clicked ( )
212
+ {
213
+ should_delete_filter = true ;
214
+ action_due_to_filter_deletion = FilterUiAction :: CommitStateToBlueprint ;
215
+ }
216
+ ui. style_mut ( ) . spacing . button_padding = button_padding;
217
+ }
218
+
219
+ let response = atom_response. response ;
264
220
265
221
// Should the popup be open?
266
222
//
@@ -375,7 +331,7 @@ fn numerical_comparison_operator_ui(
375
331
op : & mut ComparisonOperator ,
376
332
) {
377
333
ui. horizontal ( |ui| {
378
- ui. label ( SyntaxHighlightedBuilder :: body ( column_name) . into_widget_text ( ui. style ( ) ) ) ;
334
+ ui. label ( SyntaxHighlightedBuilder :: body_default ( column_name) . into_widget_text ( ui. style ( ) ) ) ;
379
335
380
336
egui:: ComboBox :: new ( "comp_op" , "" )
381
337
. selected_text (
@@ -399,7 +355,7 @@ fn numerical_comparison_operator_ui(
399
355
400
356
pub fn basic_operation_ui ( ui : & mut egui:: Ui , column_name : & str , operator_text : & str ) {
401
357
ui. label (
402
- SyntaxHighlightedBuilder :: body ( column_name)
358
+ SyntaxHighlightedBuilder :: body_default ( column_name)
403
359
. with_keyword ( " " )
404
360
. with_keyword ( operator_text)
405
361
. into_widget_text ( ui. style ( ) ) ,
0 commit comments