9120e874 Andy McCall 25 days ago
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#if defined (_MSC_VER) && !defined (_CRT_SECURE_NO_WARNINGS)
191
#define _CRT_SECURE_NO_WARNINGS
192
#endif
193
194
#ifndef IMGUI_DEFINE_MATH_OPERATORS
195
#define IMGUI_DEFINE_MATH_OPERATORS
196
#endif
197
198
#include " imgui.h"
199
#ifndef IMGUI_DISABLE
200
#include " imgui_internal.h"
201
202
203
#include < stdint.h>
204
205
206
#ifdef _MSC_VER
207
#pragma warning (disable: 4127)
208
#pragma warning (disable: 4996)
209
#if defined (_MSC_VER) && _MSC_VER >= 1922
210
#pragma warning (disable: 5054)
211
#endif
212
#pragma warning (disable: 26451)
213
#pragma warning (disable: 26812)
214
#endif
215
216
217
#if defined (__clang__)
218
#if __has_warning("-Wunknown-warning-option")
219
#pragma clang diagnostic ignored "-Wunknown-warning-option"
220
#endif
221
#pragma clang diagnostic ignored "-Wunknown-pragmas"
222
#pragma clang diagnostic ignored "-Wold-style-cast"
223
#pragma clang diagnostic ignored "-Wfloat-equal"
224
#pragma clang diagnostic ignored "-Wformat-nonliteral"
225
#pragma clang diagnostic ignored "-Wsign-conversion"
226
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
227
#pragma clang diagnostic ignored "-Wdouble-promotion"
228
#pragma clang diagnostic ignored "-Wenum-enum-conversion"
229
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"
230
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
231
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
232
#pragma clang diagnostic ignored "-Wnontrivial-memaccess"
233
#elif defined (__GNUC__)
234
#pragma GCC diagnostic ignored "-Wpragmas"
235
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
236
#pragma GCC diagnostic ignored "-Wclass-memaccess"
237
#endif
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
static const int TABLE_DRAW_CHANNEL_BG0 = 0 ;
258
static const int TABLE_DRAW_CHANNEL_BG2_FROZEN = 1 ;
259
static const int TABLE_DRAW_CHANNEL_NOCLIP = 2 ;
260
static const float TABLE_BORDER_SIZE = 1.0f ;
261
static const float TABLE_RESIZE_SEPARATOR_HALF_THICKNESS = 4.0f ;
262
static const float TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER = 0.06f ;
263
264
265
inline ImGuiTableFlags TableFixFlags ( ImGuiTableFlags flags , ImGuiWindow* outer_window )
266
{
267
268
if ( ( flags & ImGuiTableFlags_SizingMask_) == 0 )
269
flags |= ( ( flags & ImGuiTableFlags_ScrollX) || ( outer_window-> Flags & ImGuiWindowFlags_AlwaysAutoResize) ) ? ImGuiTableFlags_SizingFixedFit : ImGuiTableFlags_SizingStretchSame;
270
271
272
if ( ( flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame)
273
flags |= ImGuiTableFlags_NoKeepColumnsVisible;
274
275
276
if ( flags & ImGuiTableFlags_Resizable)
277
flags |= ImGuiTableFlags_BordersInnerV;
278
279
280
if ( flags & ( ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY) )
281
flags &= ~ ( ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_NoHostExtendY) ;
282
283
284
if ( flags & ImGuiTableFlags_NoBordersInBodyUntilResize)
285
flags &= ~ ImGuiTableFlags_NoBordersInBody;
286
287
288
if ( ( flags & ( ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable) ) == 0 )
289
flags |= ImGuiTableFlags_NoSavedSettings;
290
291
292
if ( outer_window-> RootWindow -> Flags & ImGuiWindowFlags_NoSavedSettings)
293
flags |= ImGuiTableFlags_NoSavedSettings;
294
295
return flags;
296
}
297
298
ImGuiTable* ImGui:: TableFindByID ( ImGuiID id )
299
{
300
ImGuiContext& g = * GImGui;
301
return g. Tables . GetByKey ( id ) ;
302
}
303
304
305
bool ImGui:: BeginTable ( const char * str_id , int columns_count , ImGuiTableFlags flags , const ImVec2& outer_size , float inner_width )
306
{
307
ImGuiID id = GetID ( str_id ) ;
308
return BeginTableEx ( str_id, id, columns_count, flags, outer_size, inner_width ) ;
309
}
310
311
bool ImGui:: BeginTableEx ( const char * name , ImGuiID id , int columns_count , ImGuiTableFlags flags , const ImVec2& outer_size , float inner_width )
312
{
313
ImGuiContext& g = * GImGui;
314
ImGuiWindow* outer_window = GetCurrentWindow ( ) ;
315
if ( outer_window-> SkipItems )
316
return false ;
317
318
319
IM_ASSERT ( columns_count > 0 && columns_count < IMGUI_TABLE_MAX_COLUMNS ) ;
320
if ( flags & ImGuiTableFlags_ScrollX)
321
IM_ASSERT ( inner_width >= 0.0f ) ;
322
323
324
325
326
327
328
329
330
const bool use_child_window = ( flags & ( ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY) ) != 0 ;
331
const ImVec2 avail_size = GetContentRegionAvail ( ) ;
332
const ImVec2 actual_outer_size = ImTrunc ( CalcItemSize ( outer_size, ImMax ( avail_size. x , 1.0f ) , use_child_window ? ImMax ( avail_size. y , 1.0f ) : 0.0f ) ) ;
333
const ImRect outer_rect ( outer_window-> DC . CursorPos , outer_window-> DC . CursorPos + actual_outer_size ) ;
334
const bool outer_window_is_measuring_size = ( outer_window-> AutoFitFramesX > 0 ) || ( outer_window-> AutoFitFramesY > 0 ) ;
335
if ( use_child_window && IsClippedEx ( outer_rect, 0 ) && ! outer_window_is_measuring_size)
336
{
337
ItemSize ( outer_rect ) ;
338
ItemAdd ( outer_rect, id ) ;
339
return false ;
340
}
341
342
343
if ( g. DebugBreakInTable == id)
344
IM_DEBUG_BREAK ( ) ;
345
346
347
ImGuiTable* table = g. Tables . GetOrAddByKey ( id ) ;
348
349
350
const int table_idx = g. Tables . GetIndex ( table ) ;
351
if ( + + g. TablesTempDataStacked > g. TablesTempData . Size )
352
g. TablesTempData . resize ( g. TablesTempDataStacked , ImGuiTableTempData ( ) ) ;
353
ImGuiTableTempData* temp_data = table-> TempData = & g. TablesTempData [ g. TablesTempDataStacked - 1 ] ;
354
temp_data-> TableIndex = table_idx;
355
table-> DrawSplitter = & table-> TempData -> DrawSplitter ;
356
table-> DrawSplitter -> Clear ( ) ;
357
358
359
table-> IsDefaultSizingPolicy = ( flags & ImGuiTableFlags_SizingMask_) == 0 ;
360
flags = TableFixFlags ( flags, outer_window ) ;
361
362
363
const int previous_frame_active = table-> LastFrameActive ;
364
const int instance_no = ( previous_frame_active != g. FrameCount ) ? 0 : table-> InstanceCurrent + 1 ;
365
const ImGuiTableFlags previous_flags = table-> Flags ;
366
table-> ID = id;
367
table-> Flags = flags;
368
table-> LastFrameActive = g. FrameCount ;
369
table-> OuterWindow = table-> InnerWindow = outer_window;
370
table-> ColumnsCount = columns_count;
371
table-> IsLayoutLocked = false ;
372
table-> InnerWidth = inner_width;
373
temp_data-> UserOuterSize = outer_size;
374
375
376
ImGuiID instance_id;
377
table-> InstanceCurrent = ( ImS16) instance_no;
378
if ( instance_no > 0 )
379
{
380
IM_ASSERT ( table-> ColumnsCount == columns_count && " BeginTable(): Cannot change columns count mid-frame while preserving same ID" ) ;
381
if ( table-> InstanceDataExtra . Size < instance_no)
382
table-> InstanceDataExtra . push_back ( ImGuiTableInstanceData ( ) ) ;
383
instance_id = GetIDWithSeed ( instance_no, GetIDWithSeed ( " ##Instances" , NULL , id) ) ;
384
}
385
else
386
{
387
instance_id = id;
388
}
389
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, table-> InstanceCurrent ) ;
390
table_instance-> TableInstanceID = instance_id;
391
392
393
if ( use_child_window)
394
{
395
396
397
ImVec2 override_content_size ( FLT_MAX, FLT_MAX ) ;
398
if ( ( flags & ImGuiTableFlags_ScrollX) && ! ( flags & ImGuiTableFlags_ScrollY) )
399
override_content_size. y = FLT_MIN;
400
401
402
403
404
405
if ( ( flags & ImGuiTableFlags_ScrollX) && inner_width > 0.0f )
406
override_content_size. x = inner_width;
407
408
if ( override_content_size. x != FLT_MAX || override_content_size. y != FLT_MAX)
409
SetNextWindowContentSize ( ImVec2 ( override_content_size. x != FLT_MAX ? override_content_size. x : 0.0f , override_content_size. y != FLT_MAX ? override_content_size. y : 0.0f ) ) ;
410
411
412
if ( ( previous_flags & ( ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY) ) == 0 )
413
SetNextWindowScroll ( ImVec2 ( 0.0f , 0.0f ) ) ;
414
415
416
ImGuiWindowFlags child_window_flags = ( flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None;
417
BeginChildEx ( name, instance_id, outer_rect. GetSize ( ) , ImGuiChildFlags_None, child_window_flags ) ;
418
table-> InnerWindow = g. CurrentWindow ;
419
table-> WorkRect = table-> InnerWindow -> WorkRect ;
420
table-> OuterRect = table-> InnerWindow -> Rect ( ) ;
421
table-> InnerRect = table-> InnerWindow -> InnerRect ;
422
IM_ASSERT ( table-> InnerWindow -> WindowPadding . x == 0.0f && table-> InnerWindow -> WindowPadding . y == 0.0f && table-> InnerWindow -> WindowBorderSize == 0.0f ) ;
423
424
425
if ( table-> InnerWindow -> SkipItems && outer_window_is_measuring_size)
426
table-> InnerWindow -> SkipItems = false ;
427
428
429
if ( instance_no == 0 )
430
{
431
table-> HasScrollbarYPrev = table-> HasScrollbarYCurr ;
432
table-> HasScrollbarYCurr = false ;
433
}
434
table-> HasScrollbarYCurr |= table-> InnerWindow -> ScrollbarY ;
435
}
436
else
437
{
438
439
440
table-> WorkRect = table-> OuterRect = table-> InnerRect = outer_rect;
441
table-> HasScrollbarYPrev = table-> HasScrollbarYCurr = false ;
442
}
443
444
445
PushOverrideID ( id ) ;
446
if ( instance_no > 0 )
447
PushOverrideID ( instance_id ) ;
448
449
450
ImGuiWindow* inner_window = table-> InnerWindow ;
451
table-> HostIndentX = inner_window-> DC . Indent . x ;
452
table-> HostClipRect = inner_window-> ClipRect ;
453
table-> HostSkipItems = inner_window-> SkipItems ;
454
temp_data-> HostBackupWorkRect = inner_window-> WorkRect ;
455
temp_data-> HostBackupParentWorkRect = inner_window-> ParentWorkRect ;
456
temp_data-> HostBackupColumnsOffset = outer_window-> DC . ColumnsOffset ;
457
temp_data-> HostBackupPrevLineSize = inner_window-> DC . PrevLineSize ;
458
temp_data-> HostBackupCurrLineSize = inner_window-> DC . CurrLineSize ;
459
temp_data-> HostBackupCursorMaxPos = inner_window-> DC . CursorMaxPos ;
460
temp_data-> HostBackupItemWidth = outer_window-> DC . ItemWidth ;
461
temp_data-> HostBackupItemWidthStackSize = outer_window-> DC . ItemWidthStack . Size ;
462
inner_window-> DC . PrevLineSize = inner_window-> DC . CurrLineSize = ImVec2 ( 0.0f , 0.0f ) ;
463
464
465
466
467
468
if ( inner_window != outer_window)
469
{
470
471
472
473
if ( flags & ImGuiTableFlags_BordersOuterV)
474
{
475
table-> HostClipRect . Min . x = ImMin ( table-> HostClipRect . Min . x + TABLE_BORDER_SIZE, table-> HostClipRect . Max . x ) ;
476
if ( inner_window-> DecoOuterSizeX2 == 0.0f )
477
table-> HostClipRect . Max . x = ImMax ( table-> HostClipRect . Max . x - TABLE_BORDER_SIZE, table-> HostClipRect . Min . x ) ;
478
}
479
if ( flags & ImGuiTableFlags_BordersOuterH)
480
{
481
table-> HostClipRect . Min . y = ImMin ( table-> HostClipRect . Min . y + TABLE_BORDER_SIZE, table-> HostClipRect . Max . y ) ;
482
if ( inner_window-> DecoOuterSizeY2 == 0.0f )
483
table-> HostClipRect . Max . y = ImMax ( table-> HostClipRect . Max . y - TABLE_BORDER_SIZE, table-> HostClipRect . Min . y ) ;
484
}
485
}
486
487
488
489
490
491
492
const bool pad_outer_x = ( flags & ImGuiTableFlags_NoPadOuterX) ? false : ( flags & ImGuiTableFlags_PadOuterX) ? true : ( flags & ImGuiTableFlags_BordersOuterV) != 0 ;
493
const bool pad_inner_x = ( flags & ImGuiTableFlags_NoPadInnerX) ? false : true ;
494
const float inner_spacing_for_border = ( flags & ImGuiTableFlags_BordersInnerV) ? TABLE_BORDER_SIZE : 0.0f ;
495
const float inner_spacing_explicit = ( pad_inner_x && ( flags & ImGuiTableFlags_BordersInnerV) == 0 ) ? g. Style . CellPadding . x : 0.0f ;
496
const float inner_padding_explicit = ( pad_inner_x && ( flags & ImGuiTableFlags_BordersInnerV) != 0 ) ? g. Style . CellPadding . x : 0.0f ;
497
table-> CellSpacingX1 = inner_spacing_explicit + inner_spacing_for_border;
498
table-> CellSpacingX2 = inner_spacing_explicit;
499
table-> CellPaddingX = inner_padding_explicit;
500
501
const float outer_padding_for_border = ( flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f ;
502
const float outer_padding_explicit = pad_outer_x ? g. Style . CellPadding . x : 0.0f ;
503
table-> OuterPaddingX = ( outer_padding_for_border + outer_padding_explicit) - table-> CellPaddingX ;
504
505
table-> CurrentColumn = - 1 ;
506
table-> CurrentRow = - 1 ;
507
table-> RowBgColorCounter = 0 ;
508
table-> LastRowFlags = ImGuiTableRowFlags_None;
509
table-> InnerClipRect = ( inner_window == outer_window) ? table-> WorkRect : inner_window-> ClipRect ;
510
table-> InnerClipRect . ClipWith ( table-> WorkRect ) ;
511
table-> InnerClipRect . ClipWithFull ( table-> HostClipRect ) ;
512
table-> InnerClipRect . Max . y = ( flags & ImGuiTableFlags_NoHostExtendY) ? ImMin ( table-> InnerClipRect . Max . y , inner_window-> WorkRect . Max . y ) : table-> HostClipRect . Max . y ;
513
514
table-> RowPosY1 = table-> RowPosY2 = table-> WorkRect . Min . y ;
515
table-> RowTextBaseline = 0.0f ;
516
table-> RowCellPaddingY = 0.0f ;
517
table-> FreezeRowsRequest = table-> FreezeRowsCount = 0 ;
518
table-> FreezeColumnsRequest = table-> FreezeColumnsCount = 0 ;
519
table-> IsUnfrozenRows = true ;
520
table-> DeclColumnsCount = table-> AngledHeadersCount = 0 ;
521
if ( previous_frame_active + 1 < g. FrameCount )
522
table-> IsActiveIdInTable = false ;
523
table-> AngledHeadersHeight = 0.0f ;
524
temp_data-> AngledHeadersExtraWidth = 0.0f ;
525
526
527
table-> BorderColorStrong = GetColorU32 ( ImGuiCol_TableBorderStrong ) ;
528
table-> BorderColorLight = GetColorU32 ( ImGuiCol_TableBorderLight ) ;
529
530
531
g. CurrentTable = table;
532
outer_window-> DC . NavIsScrollPushableX = false ;
533
outer_window-> DC . CurrentTableIdx = table_idx;
534
if ( inner_window != outer_window)
535
inner_window-> DC . CurrentTableIdx = table_idx;
536
537
if ( ( previous_flags & ImGuiTableFlags_Reorderable) && ( flags & ImGuiTableFlags_Reorderable) == 0 )
538
table-> IsResetDisplayOrderRequest = true ;
539
540
541
if ( table_idx >= g. TablesLastTimeActive . Size )
542
g. TablesLastTimeActive . resize ( table_idx + 1 , - 1.0f ) ;
543
g. TablesLastTimeActive [ table_idx] = ( float ) g. Time ;
544
temp_data-> LastTimeActive = ( float ) g. Time ;
545
table-> MemoryCompacted = false ;
546
547
548
ImGuiTableColumn* old_columns_to_preserve = NULL ;
549
void * old_columns_raw_data = NULL ;
550
const int old_columns_count = table-> Columns . size ( ) ;
551
if ( old_columns_count != 0 && old_columns_count != columns_count)
552
{
553
554
old_columns_to_preserve = table-> Columns . Data ;
555
old_columns_raw_data = table-> RawData ;
556
table-> RawData = NULL ;
557
}
558
if ( table-> RawData == NULL )
559
{
560
TableBeginInitMemory ( table, columns_count ) ;
561
table-> IsInitializing = table-> IsSettingsRequestLoad = true ;
562
}
563
if ( table-> IsResetAllRequest )
564
TableResetSettings ( table ) ;
565
if ( table-> IsInitializing )
566
{
567
568
table-> SettingsOffset = - 1 ;
569
table-> IsSortSpecsDirty = true ;
570
table-> InstanceInteracted = - 1 ;
571
table-> ContextPopupColumn = - 1 ;
572
table-> ReorderColumn = table-> ResizedColumn = table-> LastResizedColumn = - 1 ;
573
table-> AutoFitSingleColumn = - 1 ;
574
table-> HoveredColumnBody = table-> HoveredColumnBorder = - 1 ;
575
for ( int n = 0 ; n < columns_count; n+ + )
576
{
577
ImGuiTableColumn* column = & table-> Columns [ n] ;
578
if ( old_columns_to_preserve && n < old_columns_count)
579
{
580
581
* column = old_columns_to_preserve[ n] ;
582
}
583
else
584
{
585
float width_auto = column-> WidthAuto ;
586
* column = ImGuiTableColumn ( ) ;
587
column-> WidthAuto = width_auto;
588
column-> IsPreserveWidthAuto = true ;
589
column-> IsEnabled = column-> IsUserEnabled = column-> IsUserEnabledNextFrame = true ;
590
}
591
column-> DisplayOrder = table-> DisplayOrderToIndex [ n] = ( ImGuiTableColumnIdx) n;
592
}
593
}
594
if ( old_columns_raw_data)
595
IM_FREE ( old_columns_raw_data ) ;
596
597
598
if ( table-> IsSettingsRequestLoad )
599
TableLoadSettings ( table ) ;
600
601
602
603
604
605
606
const float new_ref_scale_unit = g. FontSize ;
607
if ( table-> RefScale != 0.0f && table-> RefScale != new_ref_scale_unit)
608
{
609
const float scale_factor = new_ref_scale_unit / table-> RefScale ;
610
611
for ( int n = 0 ; n < columns_count; n+ + )
612
table-> Columns [ n] . WidthRequest = table-> Columns [ n] . WidthRequest * scale_factor;
613
}
614
table-> RefScale = new_ref_scale_unit;
615
616
617
618
619
inner_window-> SkipItems = true ;
620
621
622
623
if ( table-> ColumnsNames . Buf . Size > 0 )
624
table-> ColumnsNames . Buf . resize ( 0 ) ;
625
626
627
TableBeginApplyRequests ( table ) ;
628
629
return true ;
630
}
631
632
633
634
635
636
637
638
639
640
641
void ImGui:: TableBeginInitMemory ( ImGuiTable* table , int columns_count )
642
{
643
644
const int columns_bit_array_size = ( int ) ImBitArrayGetStorageSizeInBytes ( columns_count ) ;
645
ImSpanAllocator< 6 > span_allocator;
646
span_allocator. Reserve ( 0 , columns_count * sizeof ( ImGuiTableColumn ) ) ;
647
span_allocator. Reserve ( 1 , columns_count * sizeof ( ImGuiTableColumnIdx ) ) ;
648
span_allocator. Reserve ( 2 , columns_count * sizeof ( ImGuiTableCellData ) , 4 ) ;
649
for ( int n = 3 ; n < 6 ; n+ + )
650
span_allocator. Reserve ( n, columns_bit_array_size ) ;
651
table-> RawData = IM_ALLOC ( span_allocator. GetArenaSizeInBytes ( ) ) ;
652
memset ( table-> RawData , 0 , span_allocator. GetArenaSizeInBytes ( ) ) ;
653
span_allocator. SetArenaBasePtr ( table-> RawData ) ;
654
span_allocator. GetSpan ( 0 , & table-> Columns ) ;
655
span_allocator. GetSpan ( 1 , & table-> DisplayOrderToIndex ) ;
656
span_allocator. GetSpan ( 2 , & table-> RowCellData ) ;
657
table-> EnabledMaskByDisplayOrder = ( ImU32* ) span_allocator. GetSpanPtrBegin ( 3 ) ;
658
table-> EnabledMaskByIndex = ( ImU32* ) span_allocator. GetSpanPtrBegin ( 4 ) ;
659
table-> VisibleMaskByIndex = ( ImU32* ) span_allocator. GetSpanPtrBegin ( 5 ) ;
660
}
661
662
663
void ImGui:: TableBeginApplyRequests ( ImGuiTable* table )
664
{
665
666
667
668
if ( table-> InstanceCurrent == 0 )
669
{
670
if ( table-> ResizedColumn != - 1 && table-> ResizedColumnNextWidth != FLT_MAX)
671
TableSetColumnWidth ( table-> ResizedColumn , table-> ResizedColumnNextWidth ) ;
672
table-> LastResizedColumn = table-> ResizedColumn ;
673
table-> ResizedColumnNextWidth = FLT_MAX;
674
table-> ResizedColumn = - 1 ;
675
676
677
678
if ( table-> AutoFitSingleColumn != - 1 )
679
{
680
TableSetColumnWidth ( table-> AutoFitSingleColumn , table-> Columns [ table-> AutoFitSingleColumn ] . WidthAuto ) ;
681
table-> AutoFitSingleColumn = - 1 ;
682
}
683
}
684
685
686
687
if ( table-> InstanceCurrent == 0 )
688
{
689
if ( table-> HeldHeaderColumn == - 1 && table-> ReorderColumn != - 1 )
690
table-> ReorderColumn = - 1 ;
691
table-> HeldHeaderColumn = - 1 ;
692
if ( table-> ReorderColumn != - 1 && table-> ReorderColumnDir != 0 )
693
{
694
695
696
697
698
const int reorder_dir = table-> ReorderColumnDir ;
699
IM_ASSERT ( reorder_dir == - 1 || reorder_dir == + 1 ) ;
700
IM_ASSERT ( table-> Flags & ImGuiTableFlags_Reorderable ) ;
701
ImGuiTableColumn* src_column = & table-> Columns [ table-> ReorderColumn ] ;
702
ImGuiTableColumn* dst_column = & table-> Columns [ ( reorder_dir == - 1 ) ? src_column-> PrevEnabledColumn : src_column-> NextEnabledColumn ] ;
703
IM_UNUSED ( dst_column ) ;
704
const int src_order = src_column-> DisplayOrder ;
705
const int dst_order = dst_column-> DisplayOrder ;
706
src_column-> DisplayOrder = ( ImGuiTableColumnIdx) dst_order;
707
for ( int order_n = src_order + reorder_dir; order_n != dst_order + reorder_dir; order_n += reorder_dir)
708
table-> Columns [ table-> DisplayOrderToIndex [ order_n] ] . DisplayOrder -= ( ImGuiTableColumnIdx) reorder_dir;
709
IM_ASSERT ( dst_column-> DisplayOrder == dst_order - reorder_dir ) ;
710
711
712
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
713
table-> DisplayOrderToIndex [ table-> Columns [ column_n] . DisplayOrder ] = ( ImGuiTableColumnIdx) column_n;
714
table-> ReorderColumnDir = 0 ;
715
table-> IsSettingsDirty = true ;
716
}
717
}
718
719
720
if ( table-> IsResetDisplayOrderRequest )
721
{
722
for ( int n = 0 ; n < table-> ColumnsCount ; n+ + )
723
table-> DisplayOrderToIndex [ n] = table-> Columns [ n] . DisplayOrder = ( ImGuiTableColumnIdx) n;
724
table-> IsResetDisplayOrderRequest = false ;
725
table-> IsSettingsDirty = true ;
726
}
727
}
728
729
730
static void TableSetupColumnFlags ( ImGuiTable* table , ImGuiTableColumn* column , ImGuiTableColumnFlags flags_in )
731
{
732
ImGuiTableColumnFlags flags = flags_in;
733
734
735
if ( ( flags & ImGuiTableColumnFlags_WidthMask_) == 0 )
736
{
737
const ImGuiTableFlags table_sizing_policy = ( table-> Flags & ImGuiTableFlags_SizingMask_) ;
738
if ( table_sizing_policy == ImGuiTableFlags_SizingFixedFit || table_sizing_policy == ImGuiTableFlags_SizingFixedSame)
739
flags |= ImGuiTableColumnFlags_WidthFixed;
740
else
741
flags |= ImGuiTableColumnFlags_WidthStretch;
742
}
743
else
744
{
745
IM_ASSERT ( ImIsPowerOfTwo ( flags & ImGuiTableColumnFlags_WidthMask_ ) ) ;
746
}
747
748
749
if ( ( table-> Flags & ImGuiTableFlags_Resizable) == 0 )
750
flags |= ImGuiTableColumnFlags_NoResize;
751
752
753
if ( ( flags & ImGuiTableColumnFlags_NoSortAscending) && ( flags & ImGuiTableColumnFlags_NoSortDescending) )
754
flags |= ImGuiTableColumnFlags_NoSort;
755
756
757
if ( ( flags & ImGuiTableColumnFlags_IndentMask_) == 0 )
758
flags |= ( table-> Columns . index_from_ptr ( column ) == 0 ) ? ImGuiTableColumnFlags_IndentEnable : ImGuiTableColumnFlags_IndentDisable;
759
760
761
762
763
764
765
766
column-> Flags = flags | ( column-> Flags & ImGuiTableColumnFlags_StatusMask_) ;
767
768
769
column-> SortDirectionsAvailCount = column-> SortDirectionsAvailMask = column-> SortDirectionsAvailList = 0 ;
770
if ( table-> Flags & ImGuiTableFlags_Sortable)
771
{
772
int count = 0 , mask = 0 , list = 0 ;
773
if ( ( flags & ImGuiTableColumnFlags_PreferSortAscending) != 0 && ( flags & ImGuiTableColumnFlags_NoSortAscending) == 0 ) { mask |= 1 << ImGuiSortDirection_Ascending; list |= ImGuiSortDirection_Ascending << ( count << 1 ) ; count+ + ; }
774
if ( ( flags & ImGuiTableColumnFlags_PreferSortDescending) != 0 && ( flags & ImGuiTableColumnFlags_NoSortDescending) == 0 ) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << ( count << 1 ) ; count+ + ; }
775
if ( ( flags & ImGuiTableColumnFlags_PreferSortAscending) == 0 && ( flags & ImGuiTableColumnFlags_NoSortAscending) == 0 ) { mask |= 1 << ImGuiSortDirection_Ascending; list |= ImGuiSortDirection_Ascending << ( count << 1 ) ; count+ + ; }
776
if ( ( flags & ImGuiTableColumnFlags_PreferSortDescending) == 0 && ( flags & ImGuiTableColumnFlags_NoSortDescending) == 0 ) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << ( count << 1 ) ; count+ + ; }
777
if ( ( table-> Flags & ImGuiTableFlags_SortTristate) || count == 0 ) { mask |= 1 << ImGuiSortDirection_None; count+ + ; }
778
column-> SortDirectionsAvailList = ( ImU8) list;
779
column-> SortDirectionsAvailMask = ( ImU8) mask;
780
column-> SortDirectionsAvailCount = ( ImU8) count;
781
ImGui:: TableFixColumnSortDirection ( table, column ) ;
782
}
783
}
784
785
786
787
788
789
void ImGui:: TableUpdateLayout ( ImGuiTable* table )
790
{
791
ImGuiContext& g = * GImGui;
792
IM_ASSERT ( table-> IsLayoutLocked == false ) ;
793
794
const ImGuiTableFlags table_sizing_policy = ( table-> Flags & ImGuiTableFlags_SizingMask_) ;
795
table-> IsDefaultDisplayOrder = true ;
796
table-> ColumnsEnabledCount = 0 ;
797
ImBitArrayClearAllBits ( table-> EnabledMaskByIndex , table-> ColumnsCount ) ;
798
ImBitArrayClearAllBits ( table-> EnabledMaskByDisplayOrder , table-> ColumnsCount ) ;
799
table-> LeftMostEnabledColumn = - 1 ;
800
table-> MinColumnWidth = ImMax ( 1.0f , g. Style . FramePadding . x * 1.0f ) ;
801
802
803
804
int count_fixed = 0 ;
805
int count_stretch = 0 ;
806
int prev_visible_column_idx = - 1 ;
807
bool has_auto_fit_request = false ;
808
bool has_resizable = false ;
809
float stretch_sum_width_auto = 0.0f ;
810
float fixed_max_width_auto = 0.0f ;
811
for ( int order_n = 0 ; order_n < table-> ColumnsCount ; order_n+ + )
812
{
813
const int column_n = table-> DisplayOrderToIndex [ order_n] ;
814
if ( column_n != order_n)
815
table-> IsDefaultDisplayOrder = false ;
816
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
817
818
819
820
821
if ( table-> DeclColumnsCount <= column_n)
822
{
823
TableSetupColumnFlags ( table, column, ImGuiTableColumnFlags_None ) ;
824
column-> NameOffset = - 1 ;
825
column-> UserID = 0 ;
826
column-> InitStretchWeightOrWidth = - 1.0f ;
827
}
828
829
830
if ( ! ( table-> Flags & ImGuiTableFlags_Hideable) || ( column-> Flags & ImGuiTableColumnFlags_NoHide) )
831
column-> IsUserEnabledNextFrame = true ;
832
if ( column-> IsUserEnabled != column-> IsUserEnabledNextFrame )
833
{
834
column-> IsUserEnabled = column-> IsUserEnabledNextFrame ;
835
table-> IsSettingsDirty = true ;
836
}
837
column-> IsEnabled = column-> IsUserEnabled && ( column-> Flags & ImGuiTableColumnFlags_Disabled) == 0 ;
838
839
if ( column-> SortOrder != - 1 && ! column-> IsEnabled )
840
table-> IsSortSpecsDirty = true ;
841
if ( column-> SortOrder > 0 && ! ( table-> Flags & ImGuiTableFlags_SortMulti) )
842
table-> IsSortSpecsDirty = true ;
843
844
845
const bool start_auto_fit = ( column-> Flags & ImGuiTableColumnFlags_WidthFixed) ? ( column-> WidthRequest < 0.0f ) : ( column-> StretchWeight < 0.0f ) ;
846
if ( start_auto_fit)
847
column-> AutoFitQueue = column-> CannotSkipItemsQueue = ( 1 << 3 ) - 1 ;
848
849
if ( ! column-> IsEnabled )
850
{
851
column-> IndexWithinEnabledSet = - 1 ;
852
continue ;
853
}
854
855
856
column-> PrevEnabledColumn = ( ImGuiTableColumnIdx) prev_visible_column_idx;
857
column-> NextEnabledColumn = - 1 ;
858
if ( prev_visible_column_idx != - 1 )
859
table-> Columns [ prev_visible_column_idx] . NextEnabledColumn = ( ImGuiTableColumnIdx) column_n;
860
else
861
table-> LeftMostEnabledColumn = ( ImGuiTableColumnIdx) column_n;
862
column-> IndexWithinEnabledSet = table-> ColumnsEnabledCount + + ;
863
ImBitArraySetBit ( table-> EnabledMaskByIndex , column_n ) ;
864
ImBitArraySetBit ( table-> EnabledMaskByDisplayOrder , column-> DisplayOrder ) ;
865
prev_visible_column_idx = column_n;
866
IM_ASSERT ( column-> IndexWithinEnabledSet <= column-> DisplayOrder ) ;
867
868
869
870
if ( ! column-> IsPreserveWidthAuto && table-> InstanceCurrent == 0 )
871
column-> WidthAuto = TableGetColumnWidthAuto ( table, column ) ;
872
873
874
const bool column_is_resizable = ( column-> Flags & ImGuiTableColumnFlags_NoResize) == 0 ;
875
if ( column_is_resizable)
876
has_resizable = true ;
877
if ( ( column-> Flags & ImGuiTableColumnFlags_WidthFixed) && column-> InitStretchWeightOrWidth > 0.0f && ! column_is_resizable)
878
column-> WidthAuto = column-> InitStretchWeightOrWidth ;
879
880
if ( column-> AutoFitQueue != 0x00 )
881
has_auto_fit_request = true ;
882
if ( column-> Flags & ImGuiTableColumnFlags_WidthStretch)
883
{
884
stretch_sum_width_auto += column-> WidthAuto ;
885
count_stretch+ + ;
886
}
887
else
888
{
889
fixed_max_width_auto = ImMax ( fixed_max_width_auto, column-> WidthAuto ) ;
890
count_fixed+ + ;
891
}
892
}
893
if ( ( table-> Flags & ImGuiTableFlags_Sortable) && table-> SortSpecsCount == 0 && ! ( table-> Flags & ImGuiTableFlags_SortTristate) )
894
table-> IsSortSpecsDirty = true ;
895
table-> RightMostEnabledColumn = ( ImGuiTableColumnIdx) prev_visible_column_idx;
896
IM_ASSERT ( table-> LeftMostEnabledColumn >= 0 && table-> RightMostEnabledColumn >= 0 ) ;
897
898
899
900
901
if ( has_auto_fit_request && table-> OuterWindow != table-> InnerWindow )
902
table-> InnerWindow -> SkipItems = false ;
903
if ( has_auto_fit_request)
904
table-> IsSettingsDirty = true ;
905
906
907
float sum_width_requests = 0.0f ;
908
float stretch_sum_weights = 0.0f ;
909
table-> LeftMostStretchedColumn = table-> RightMostStretchedColumn = - 1 ;
910
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
911
{
912
if ( ! IM_BITARRAY_TESTBIT ( table-> EnabledMaskByIndex , column_n ) )
913
continue ;
914
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
915
916
const bool column_is_resizable = ( column-> Flags & ImGuiTableColumnFlags_NoResize) == 0 ;
917
if ( column-> Flags & ImGuiTableColumnFlags_WidthFixed)
918
{
919
920
float width_auto = column-> WidthAuto ;
921
if ( table_sizing_policy == ImGuiTableFlags_SizingFixedSame && ( column-> AutoFitQueue != 0x00 || ! column_is_resizable) )
922
width_auto = fixed_max_width_auto;
923
924
925
926
if ( column-> AutoFitQueue != 0x00 )
927
column-> WidthRequest = width_auto;
928
else if ( ( column-> Flags & ImGuiTableColumnFlags_WidthFixed) && ! column_is_resizable && column-> IsRequestOutput )
929
column-> WidthRequest = width_auto;
930
931
932
933
934
935
936
937
if ( column-> AutoFitQueue > 0x01 && table-> IsInitializing && ! column-> IsPreserveWidthAuto )
938
column-> WidthRequest = ImMax ( column-> WidthRequest , table-> MinColumnWidth * 4.0f ) ;
939
sum_width_requests += column-> WidthRequest ;
940
}
941
else
942
{
943
944
if ( column-> AutoFitQueue != 0x00 || column-> StretchWeight < 0.0f || ! column_is_resizable)
945
{
946
if ( column-> InitStretchWeightOrWidth > 0.0f )
947
column-> StretchWeight = column-> InitStretchWeightOrWidth ;
948
else if ( table_sizing_policy == ImGuiTableFlags_SizingStretchProp)
949
column-> StretchWeight = ( column-> WidthAuto / stretch_sum_width_auto) * count_stretch;
950
else
951
column-> StretchWeight = 1.0f ;
952
}
953
954
stretch_sum_weights += column-> StretchWeight ;
955
if ( table-> LeftMostStretchedColumn == - 1 || table-> Columns [ table-> LeftMostStretchedColumn ] . DisplayOrder > column-> DisplayOrder )
956
table-> LeftMostStretchedColumn = ( ImGuiTableColumnIdx) column_n;
957
if ( table-> RightMostStretchedColumn == - 1 || table-> Columns [ table-> RightMostStretchedColumn ] . DisplayOrder < column-> DisplayOrder )
958
table-> RightMostStretchedColumn = ( ImGuiTableColumnIdx) column_n;
959
}
960
column-> IsPreserveWidthAuto = false ;
961
sum_width_requests += table-> CellPaddingX * 2.0f ;
962
}
963
table-> ColumnsEnabledFixedCount = ( ImGuiTableColumnIdx) count_fixed;
964
table-> ColumnsStretchSumWeights = stretch_sum_weights;
965
966
967
const ImRect work_rect = table-> WorkRect ;
968
const float width_spacings = ( table-> OuterPaddingX * 2.0f ) + ( table-> CellSpacingX1 + table-> CellSpacingX2 ) * ( table-> ColumnsEnabledCount - 1 ) ;
969
const float width_removed = ( table-> HasScrollbarYPrev && ! table-> InnerWindow -> ScrollbarY ) ? g. Style . ScrollbarSize : 0.0f ;
970
const float width_avail = ImMax ( 1.0f , ( ( ( table-> Flags & ImGuiTableFlags_ScrollX) && table-> InnerWidth == 0.0f ) ? table-> InnerClipRect . GetWidth ( ) : work_rect. GetWidth ( ) ) - width_removed) ;
971
const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests;
972
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns;
973
table-> ColumnsGivenWidth = width_spacings + ( table-> CellPaddingX * 2.0f ) * table-> ColumnsEnabledCount ;
974
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
975
{
976
if ( ! IM_BITARRAY_TESTBIT ( table-> EnabledMaskByIndex , column_n ) )
977
continue ;
978
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
979
980
981
if ( column-> Flags & ImGuiTableColumnFlags_WidthStretch)
982
{
983
float weight_ratio = column-> StretchWeight / stretch_sum_weights;
984
column-> WidthRequest = IM_TRUNC ( ImMax ( width_avail_for_stretched_columns * weight_ratio, table-> MinColumnWidth ) + 0.01f ) ;
985
width_remaining_for_stretched_columns -= column-> WidthRequest ;
986
}
987
988
989
990
if ( column-> NextEnabledColumn == - 1 && table-> LeftMostStretchedColumn != - 1 )
991
column-> Flags |= ImGuiTableColumnFlags_NoDirectResize_;
992
993
994
column-> WidthGiven = ImTrunc ( ImMax ( column-> WidthRequest , table-> MinColumnWidth ) ) ;
995
table-> ColumnsGivenWidth += column-> WidthGiven ;
996
}
997
998
999
1000
if ( width_remaining_for_stretched_columns >= 1.0f && ! ( table-> Flags & ImGuiTableFlags_PreciseWidths) )
1001
for ( int order_n = table-> ColumnsCount - 1 ; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0 ; order_n- - )
1002
{
1003
if ( ! IM_BITARRAY_TESTBIT ( table-> EnabledMaskByDisplayOrder , order_n ) )
1004
continue ;
1005
ImGuiTableColumn* column = & table-> Columns [ table-> DisplayOrderToIndex [ order_n] ] ;
1006
if ( ! ( column-> Flags & ImGuiTableColumnFlags_WidthStretch) )
1007
continue ;
1008
column-> WidthRequest += 1.0f ;
1009
column-> WidthGiven += 1.0f ;
1010
width_remaining_for_stretched_columns -= 1.0f ;
1011
}
1012
1013
1014
1015
1016
1017
1018
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, table-> InstanceCurrent ) ;
1019
table_instance-> HoveredRowLast = table_instance-> HoveredRowNext ;
1020
table_instance-> HoveredRowNext = - 1 ;
1021
table-> HoveredColumnBody = table-> HoveredColumnBorder = - 1 ;
1022
const ImRect mouse_hit_rect ( table-> OuterRect . Min . x , table-> OuterRect . Min . y , table-> OuterRect . Max . x , ImMax ( table-> OuterRect . Max . y , table-> OuterRect . Min . y + table_instance-> LastOuterHeight ) ) ;
1023
const ImGuiID backup_active_id = g. ActiveId ;
1024
g. ActiveId = 0 ;
1025
const bool is_hovering_table = ItemHoverable ( mouse_hit_rect, 0 , ImGuiItemFlags_None ) ;
1026
g. ActiveId = backup_active_id;
1027
1028
1029
float mouse_skewed_x = g. IO . MousePos . x ;
1030
if ( table-> AngledHeadersHeight > 0.0f )
1031
if ( g. IO . MousePos . y >= table-> OuterRect . Min . y && g. IO . MousePos . y <= table-> OuterRect . Min . y + table-> AngledHeadersHeight )
1032
mouse_skewed_x += ImTrunc ( ( table-> OuterRect . Min . y + table-> AngledHeadersHeight - g. IO . MousePos . y ) * table-> AngledHeadersSlope ) ;
1033
1034
1035
1036
int visible_n = 0 ;
1037
bool has_at_least_one_column_requesting_output = false ;
1038
bool offset_x_frozen = ( table-> FreezeColumnsCount > 0 ) ;
1039
float offset_x = ( ( table-> FreezeColumnsCount > 0 ) ? table-> OuterRect . Min . x : work_rect. Min . x ) + table-> OuterPaddingX - table-> CellSpacingX1 ;
1040
ImRect host_clip_rect = table-> InnerClipRect ;
1041
1042
ImBitArrayClearAllBits ( table-> VisibleMaskByIndex , table-> ColumnsCount ) ;
1043
for ( int order_n = 0 ; order_n < table-> ColumnsCount ; order_n+ + )
1044
{
1045
const int column_n = table-> DisplayOrderToIndex [ order_n] ;
1046
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
1047
1048
column-> NavLayerCurrent = ( ImS8) ( table-> FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main) ;
1049
1050
if ( offset_x_frozen && table-> FreezeColumnsCount == visible_n)
1051
{
1052
offset_x += work_rect. Min . x - table-> OuterRect . Min . x ;
1053
offset_x_frozen = false ;
1054
}
1055
1056
1057
column-> Flags &= ~ ImGuiTableColumnFlags_StatusMask_;
1058
1059
if ( ! IM_BITARRAY_TESTBIT ( table-> EnabledMaskByDisplayOrder , order_n ) )
1060
{
1061
1062
1063
column-> MinX = column-> MaxX = column-> WorkMinX = column-> ClipRect . Min . x = column-> ClipRect . Max . x = offset_x;
1064
column-> WidthGiven = 0.0f ;
1065
column-> ClipRect . Min . y = work_rect. Min . y ;
1066
column-> ClipRect . Max . y = FLT_MAX;
1067
column-> ClipRect . ClipWithFull ( host_clip_rect ) ;
1068
column-> IsVisibleX = column-> IsVisibleY = column-> IsRequestOutput = false ;
1069
column-> IsSkipItems = true ;
1070
column-> ItemWidth = 1.0f ;
1071
continue ;
1072
}
1073
1074
1075
column-> MinX = offset_x;
1076
1077
1078
column-> WidthMax = TableCalcMaxColumnWidth ( table, column_n ) ;
1079
column-> WidthGiven = ImMin ( column-> WidthGiven , column-> WidthMax ) ;
1080
column-> WidthGiven = ImMax ( column-> WidthGiven , ImMin ( column-> WidthRequest , table-> MinColumnWidth ) ) ;
1081
column-> MaxX = offset_x + column-> WidthGiven + table-> CellSpacingX1 + table-> CellSpacingX2 + table-> CellPaddingX * 2.0f ;
1082
1083
1084
1085
1086
1087
1088
const float previous_instance_work_min_x = column-> WorkMinX ;
1089
column-> WorkMinX = column-> MinX + table-> CellPaddingX + table-> CellSpacingX1 ;
1090
column-> WorkMaxX = column-> MaxX - table-> CellPaddingX - table-> CellSpacingX2 ;
1091
column-> ItemWidth = ImTrunc ( column-> WidthGiven * 0.65f ) ;
1092
column-> ClipRect . Min . x = column-> MinX ;
1093
column-> ClipRect . Min . y = work_rect. Min . y ;
1094
column-> ClipRect . Max . x = column-> MaxX ;
1095
column-> ClipRect . Max . y = FLT_MAX;
1096
column-> ClipRect . ClipWithFull ( host_clip_rect ) ;
1097
1098
1099
1100
1101
1102
1103
1104
1105
column-> IsVisibleX = ( column-> ClipRect . Max . x > column-> ClipRect . Min . x ) ;
1106
column-> IsVisibleY = true ;
1107
const bool is_visible = column-> IsVisibleX ;
1108
if ( is_visible)
1109
ImBitArraySetBit ( table-> VisibleMaskByIndex , column_n ) ;
1110
1111
1112
column-> IsRequestOutput = is_visible || column-> AutoFitQueue != 0 || column-> CannotSkipItemsQueue != 0 ;
1113
1114
1115
1116
column-> IsSkipItems = ! column-> IsEnabled || table-> HostSkipItems ;
1117
if ( column-> IsSkipItems )
1118
IM_ASSERT ( ! is_visible) ;
1119
if ( column-> IsRequestOutput && ! column-> IsSkipItems )
1120
has_at_least_one_column_requesting_output = true ;
1121
1122
1123
column-> Flags |= ImGuiTableColumnFlags_IsEnabled;
1124
if ( is_visible)
1125
column-> Flags |= ImGuiTableColumnFlags_IsVisible;
1126
if ( column-> SortOrder != - 1 )
1127
column-> Flags |= ImGuiTableColumnFlags_IsSorted;
1128
1129
1130
if ( is_hovering_table && mouse_skewed_x >= column-> ClipRect . Min . x && mouse_skewed_x < column-> ClipRect . Max . x )
1131
{
1132
column-> Flags |= ImGuiTableColumnFlags_IsHovered;
1133
table-> HoveredColumnBody = ( ImGuiTableColumnIdx) column_n;
1134
}
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
if ( table-> InstanceCurrent == 0 )
1147
{
1148
column-> ContentMaxXFrozen = column-> WorkMinX ;
1149
column-> ContentMaxXUnfrozen = column-> WorkMinX ;
1150
column-> ContentMaxXHeadersUsed = column-> WorkMinX ;
1151
column-> ContentMaxXHeadersIdeal = column-> WorkMinX ;
1152
}
1153
else
1154
{
1155
1156
const float offset_from_previous_instance = column-> WorkMinX - previous_instance_work_min_x;
1157
column-> ContentMaxXFrozen += offset_from_previous_instance;
1158
column-> ContentMaxXUnfrozen += offset_from_previous_instance;
1159
column-> ContentMaxXHeadersUsed += offset_from_previous_instance;
1160
column-> ContentMaxXHeadersIdeal += offset_from_previous_instance;
1161
}
1162
1163
1164
if ( table-> HostSkipItems == false && table-> InstanceCurrent == 0 )
1165
{
1166
column-> AutoFitQueue >>= 1 ;
1167
column-> CannotSkipItemsQueue >>= 1 ;
1168
}
1169
1170
if ( visible_n < table-> FreezeColumnsCount )
1171
host_clip_rect. Min . x = ImClamp ( column-> MaxX + TABLE_BORDER_SIZE, host_clip_rect. Min . x , host_clip_rect. Max . x ) ;
1172
1173
offset_x += column-> WidthGiven + table-> CellSpacingX1 + table-> CellSpacingX2 + table-> CellPaddingX * 2.0f ;
1174
visible_n+ + ;
1175
}
1176
1177
1178
1179
if ( has_at_least_one_column_requesting_output == false )
1180
{
1181
table-> Columns [ table-> LeftMostEnabledColumn ] . IsRequestOutput = true ;
1182
table-> Columns [ table-> LeftMostEnabledColumn ] . IsSkipItems = false ;
1183
}
1184
1185
1186
1187
1188
const float unused_x1 = ImMax ( table-> WorkRect . Min . x , table-> Columns [ table-> RightMostEnabledColumn ] . ClipRect . Max . x ) ;
1189
if ( is_hovering_table && table-> HoveredColumnBody == - 1 )
1190
if ( mouse_skewed_x >= unused_x1)
1191
table-> HoveredColumnBody = ( ImGuiTableColumnIdx) table-> ColumnsCount ;
1192
if ( has_resizable == false && ( table-> Flags & ImGuiTableFlags_Resizable) )
1193
table-> Flags &= ~ ImGuiTableFlags_Resizable;
1194
1195
table-> IsActiveIdAliveBeforeTable = ( g. ActiveIdIsAlive != 0 ) ;
1196
1197
1198
1199
1200
if ( table-> RightMostStretchedColumn != - 1 )
1201
table-> Flags &= ~ ImGuiTableFlags_NoHostExtendX;
1202
if ( table-> Flags & ImGuiTableFlags_NoHostExtendX)
1203
{
1204
table-> OuterRect . Max . x = table-> WorkRect . Max . x = unused_x1;
1205
table-> InnerClipRect . Max . x = ImMin ( table-> InnerClipRect . Max . x , unused_x1 ) ;
1206
}
1207
table-> InnerWindow -> ParentWorkRect = table-> WorkRect ;
1208
table-> BorderX1 = table-> InnerClipRect . Min . x ;
1209
table-> BorderX2 = table-> InnerClipRect . Max . x ;
1210
1211
1212
float window_content_max_y;
1213
if ( table-> Flags & ImGuiTableFlags_NoHostExtendY)
1214
window_content_max_y = table-> OuterRect . Max . y ;
1215
else
1216
window_content_max_y = ImMax ( table-> InnerWindow -> ContentRegionRect . Max . y , ( table-> Flags & ImGuiTableFlags_ScrollY) ? 0.0f : table-> OuterRect . Max . y ) ;
1217
table-> InnerWindow -> WorkRect . Max . y = ImClamp ( window_content_max_y - g. Style . CellPadding . y , table-> InnerWindow -> WorkRect . Min . y , table-> InnerWindow -> WorkRect . Max . y ) ;
1218
1219
1220
TableSetupDrawChannels ( table ) ;
1221
1222
1223
if ( table-> Flags & ImGuiTableFlags_Resizable)
1224
TableUpdateBorders ( table ) ;
1225
table_instance-> LastTopHeadersRowHeight = 0.0f ;
1226
table-> IsLayoutLocked = true ;
1227
table-> IsUsingHeaders = false ;
1228
1229
1230
table-> HighlightColumnHeader = - 1 ;
1231
if ( table-> IsContextPopupOpen && table-> ContextPopupColumn != - 1 && table-> InstanceInteracted == table-> InstanceCurrent )
1232
table-> HighlightColumnHeader = table-> ContextPopupColumn ;
1233
else if ( ( table-> Flags & ImGuiTableFlags_HighlightHoveredColumn) && table-> HoveredColumnBody != - 1 && table-> HoveredColumnBody != table-> ColumnsCount && table-> HoveredColumnBorder == - 1 )
1234
if ( g. ActiveId == 0 || ( table-> IsActiveIdInTable || g. DragDropActive ) )
1235
table-> HighlightColumnHeader = table-> HoveredColumnBody ;
1236
1237
1238
1239
1240
1241
1242
if ( table-> DisableDefaultContextMenu == false && TableBeginContextMenuPopup ( table ) )
1243
{
1244
TableDrawDefaultContextMenu ( table, table-> Flags ) ;
1245
EndPopup ( ) ;
1246
}
1247
1248
1249
1250
if ( table-> IsSortSpecsDirty && ( table-> Flags & ImGuiTableFlags_Sortable) )
1251
TableSortSpecsBuild ( table ) ;
1252
1253
1254
if ( table-> FreezeColumnsRequest > 0 )
1255
table-> InnerWindow -> DecoInnerSizeX1 = table-> Columns [ table-> DisplayOrderToIndex [ table-> FreezeColumnsRequest - 1 ] ] . MaxX - table-> OuterRect . Min . x ;
1256
if ( table-> FreezeRowsRequest > 0 )
1257
table-> InnerWindow -> DecoInnerSizeY1 = table_instance-> LastFrozenHeight ;
1258
table_instance-> LastFrozenHeight = 0.0f ;
1259
1260
1261
ImGuiWindow* inner_window = table-> InnerWindow ;
1262
if ( table-> Flags & ImGuiTableFlags_NoClip)
1263
table-> DrawSplitter -> SetCurrentChannel ( inner_window-> DrawList , TABLE_DRAW_CHANNEL_NOCLIP ) ;
1264
else
1265
inner_window-> DrawList -> PushClipRect ( inner_window-> InnerClipRect . Min , inner_window-> InnerClipRect . Max , false ) ;
1266
}
1267
1268
1269
1270
void ImGui:: TableUpdateBorders ( ImGuiTable* table )
1271
{
1272
ImGuiContext& g = * GImGui;
1273
IM_ASSERT ( table-> Flags & ImGuiTableFlags_Resizable ) ;
1274
1275
1276
1277
1278
1279
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, table-> InstanceCurrent ) ;
1280
const float hit_half_width = ImTrunc ( TABLE_RESIZE_SEPARATOR_HALF_THICKNESS * g. CurrentDpiScale ) ;
1281
const float hit_y1 = ( table-> FreezeRowsCount >= 1 ? table-> OuterRect . Min . y : table-> WorkRect . Min . y ) + table-> AngledHeadersHeight ;
1282
const float hit_y2_body = ImMax ( table-> OuterRect . Max . y , hit_y1 + table_instance-> LastOuterHeight - table-> AngledHeadersHeight ) ;
1283
const float hit_y2_head = hit_y1 + table_instance-> LastTopHeadersRowHeight ;
1284
1285
for ( int order_n = 0 ; order_n < table-> ColumnsCount ; order_n+ + )
1286
{
1287
if ( ! IM_BITARRAY_TESTBIT ( table-> EnabledMaskByDisplayOrder , order_n ) )
1288
continue ;
1289
1290
const int column_n = table-> DisplayOrderToIndex [ order_n] ;
1291
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
1292
if ( column-> Flags & ( ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_) )
1293
continue ;
1294
1295
1296
const float border_y2_hit = ( table-> Flags & ImGuiTableFlags_NoBordersInBody) ? hit_y2_head : hit_y2_body;
1297
if ( ( table-> Flags & ImGuiTableFlags_NoBordersInBody) && table-> IsUsingHeaders == false )
1298
continue ;
1299
1300
if ( ! column-> IsVisibleX && table-> LastResizedColumn != column_n)
1301
continue ;
1302
1303
ImGuiID column_id = TableGetColumnResizeID ( table, column_n, table-> InstanceCurrent ) ;
1304
ImRect hit_rect ( column-> MaxX - hit_half_width, hit_y1, column-> MaxX + hit_half_width, border_y2_hit ) ;
1305
ItemAdd ( hit_rect, column_id, NULL , ImGuiItemFlags_NoNav ) ;
1306
1307
1308
bool hovered = false , held = false ;
1309
bool pressed = ButtonBehavior ( hit_rect, column_id, & hovered, & held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_NoNavFocus ) ;
1310
if ( pressed && IsMouseDoubleClicked ( 0 ) )
1311
{
1312
TableSetColumnWidthAutoSingle ( table, column_n ) ;
1313
ClearActiveID ( ) ;
1314
held = false ;
1315
}
1316
if ( held)
1317
{
1318
if ( table-> LastResizedColumn == - 1 )
1319
table-> ResizeLockMinContentsX2 = table-> RightMostEnabledColumn != - 1 ? table-> Columns [ table-> RightMostEnabledColumn ] . MaxX : - FLT_MAX;
1320
table-> ResizedColumn = ( ImGuiTableColumnIdx) column_n;
1321
table-> InstanceInteracted = table-> InstanceCurrent ;
1322
}
1323
if ( ( hovered && g. HoveredIdTimer > TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER) || held)
1324
{
1325
table-> HoveredColumnBorder = ( ImGuiTableColumnIdx) column_n;
1326
SetMouseCursor ( ImGuiMouseCursor_ResizeEW ) ;
1327
}
1328
}
1329
}
1330
1331
void ImGui:: EndTable ( )
1332
{
1333
ImGuiContext& g = * GImGui;
1334
ImGuiTable* table = g. CurrentTable ;
1335
IM_ASSERT ( table != NULL && " Only call EndTable() if BeginTable() returns true!" ) ;
1336
1337
1338
1339
1340
1341
1342
1343
if ( ! table-> IsLayoutLocked )
1344
TableUpdateLayout ( table ) ;
1345
1346
const ImGuiTableFlags flags = table-> Flags ;
1347
ImGuiWindow* inner_window = table-> InnerWindow ;
1348
ImGuiWindow* outer_window = table-> OuterWindow ;
1349
ImGuiTableTempData* temp_data = table-> TempData ;
1350
IM_ASSERT ( inner_window == g. CurrentWindow ) ;
1351
IM_ASSERT ( outer_window == inner_window || outer_window == inner_window-> ParentWindow ) ;
1352
1353
if ( table-> IsInsideRow )
1354
TableEndRow ( table ) ;
1355
1356
1357
if ( flags & ImGuiTableFlags_ContextMenuInBody)
1358
if ( table-> HoveredColumnBody != - 1 && ! IsAnyItemHovered ( ) && IsMouseReleased ( ImGuiMouseButton_Right ) )
1359
TableOpenContextMenu ( ( int ) table-> HoveredColumnBody ) ;
1360
1361
1362
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, table-> InstanceCurrent ) ;
1363
inner_window-> DC . PrevLineSize = temp_data-> HostBackupPrevLineSize ;
1364
inner_window-> DC . CurrLineSize = temp_data-> HostBackupCurrLineSize ;
1365
inner_window-> DC . CursorMaxPos = temp_data-> HostBackupCursorMaxPos ;
1366
const float inner_content_max_y = table-> RowPosY2 ;
1367
IM_ASSERT ( table-> RowPosY2 == inner_window-> DC . CursorPos . y ) ;
1368
if ( inner_window != outer_window)
1369
inner_window-> DC . CursorMaxPos . y = inner_content_max_y;
1370
else if ( ! ( flags & ImGuiTableFlags_NoHostExtendY) )
1371
table-> OuterRect . Max . y = table-> InnerRect . Max . y = ImMax ( table-> OuterRect . Max . y , inner_content_max_y ) ;
1372
table-> WorkRect . Max . y = ImMax ( table-> WorkRect . Max . y , table-> OuterRect . Max . y ) ;
1373
table_instance-> LastOuterHeight = table-> OuterRect . GetHeight ( ) ;
1374
1375
1376
1377
1378
if ( table-> Flags & ImGuiTableFlags_ScrollX)
1379
{
1380
const float outer_padding_for_border = ( table-> Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f ;
1381
float max_pos_x = table-> InnerWindow -> DC . CursorMaxPos . x ;
1382
if ( table-> RightMostEnabledColumn != - 1 )
1383
max_pos_x = ImMax ( max_pos_x, table-> Columns [ table-> RightMostEnabledColumn ] . WorkMaxX + table-> CellPaddingX + table-> OuterPaddingX - outer_padding_for_border ) ;
1384
if ( table-> ResizedColumn != - 1 )
1385
max_pos_x = ImMax ( max_pos_x, table-> ResizeLockMinContentsX2 ) ;
1386
table-> InnerWindow -> DC . CursorMaxPos . x = max_pos_x + table-> TempData -> AngledHeadersExtraWidth ;
1387
}
1388
1389
1390
if ( ! ( flags & ImGuiTableFlags_NoClip) )
1391
inner_window-> DrawList -> PopClipRect ( ) ;
1392
inner_window-> ClipRect = inner_window-> DrawList -> _ClipRectStack . back ( ) ;
1393
1394
1395
if ( ( flags & ImGuiTableFlags_Borders) != 0 )
1396
TableDrawBorders ( table ) ;
1397
1398
#if 0
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
#endif
1410
1411
1412
ImDrawListSplitter* splitter = table-> DrawSplitter ;
1413
splitter-> SetCurrentChannel ( inner_window-> DrawList , 0 ) ;
1414
if ( ( table-> Flags & ImGuiTableFlags_NoClip) == 0 )
1415
TableMergeDrawChannels ( table ) ;
1416
splitter-> Merge ( inner_window-> DrawList ) ;
1417
1418
1419
float auto_fit_width_for_fixed = 0.0f ;
1420
float auto_fit_width_for_stretched = 0.0f ;
1421
float auto_fit_width_for_stretched_min = 0.0f ;
1422
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
1423
if ( IM_BITARRAY_TESTBIT ( table-> EnabledMaskByIndex , column_n ) )
1424
{
1425
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
1426
float column_width_request = ( ( column-> Flags & ImGuiTableColumnFlags_WidthFixed) && ! ( column-> Flags & ImGuiTableColumnFlags_NoResize) ) ? column-> WidthRequest : TableGetColumnWidthAuto ( table, column ) ;
1427
if ( column-> Flags & ImGuiTableColumnFlags_WidthFixed)
1428
auto_fit_width_for_fixed += column_width_request;
1429
else
1430
auto_fit_width_for_stretched += column_width_request;
1431
if ( ( column-> Flags & ImGuiTableColumnFlags_WidthStretch) && ( column-> Flags & ImGuiTableColumnFlags_NoResize) != 0 )
1432
auto_fit_width_for_stretched_min = ImMax ( auto_fit_width_for_stretched_min, column_width_request / ( column-> StretchWeight / table-> ColumnsStretchSumWeights ) ) ;
1433
}
1434
const float width_spacings = ( table-> OuterPaddingX * 2.0f ) + ( table-> CellSpacingX1 + table-> CellSpacingX2 ) * ( table-> ColumnsEnabledCount - 1 ) ;
1435
table-> ColumnsAutoFitWidth = width_spacings + ( table-> CellPaddingX * 2.0f ) * table-> ColumnsEnabledCount + auto_fit_width_for_fixed + ImMax ( auto_fit_width_for_stretched, auto_fit_width_for_stretched_min ) ;
1436
1437
1438
if ( ( table-> Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window)
1439
{
1440
inner_window-> Scroll . x = 0.0f ;
1441
}
1442
else if ( table-> LastResizedColumn != - 1 && table-> ResizedColumn == - 1 && inner_window-> ScrollbarX && table-> InstanceInteracted == table-> InstanceCurrent )
1443
{
1444
1445
const float neighbor_width_to_keep_visible = table-> MinColumnWidth + table-> CellPaddingX * 2.0f ;
1446
ImGuiTableColumn* column = & table-> Columns [ table-> LastResizedColumn ] ;
1447
if ( column-> MaxX < table-> InnerClipRect . Min . x )
1448
SetScrollFromPosX ( inner_window, column-> MaxX - inner_window-> Pos . x - neighbor_width_to_keep_visible, 1.0f ) ;
1449
else if ( column-> MaxX > table-> InnerClipRect . Max . x )
1450
SetScrollFromPosX ( inner_window, column-> MaxX - inner_window-> Pos . x + neighbor_width_to_keep_visible, 1.0f ) ;
1451
}
1452
1453
1454
if ( table-> ResizedColumn != - 1 && table-> InstanceCurrent == table-> InstanceInteracted )
1455
{
1456
ImGuiTableColumn* column = & table-> Columns [ table-> ResizedColumn ] ;
1457
const float new_x2 = ( g. IO . MousePos . x - g. ActiveIdClickOffset . x + ImTrunc ( TABLE_RESIZE_SEPARATOR_HALF_THICKNESS * g. CurrentDpiScale ) ) ;
1458
const float new_width = ImTrunc ( new_x2 - column-> MinX - table-> CellSpacingX1 - table-> CellPaddingX * 2.0f ) ;
1459
table-> ResizedColumnNextWidth = new_width;
1460
}
1461
1462
table-> IsActiveIdInTable = ( g. ActiveIdIsAlive != 0 && table-> IsActiveIdAliveBeforeTable == false ) ;
1463
1464
1465
IM_ASSERT_USER_ERROR ( inner_window-> IDStack . back ( ) == table_instance-> TableInstanceID , " Mismatching PushID/PopID!" ) ;
1466
IM_ASSERT_USER_ERROR ( outer_window-> DC . ItemWidthStack . Size >= temp_data-> HostBackupItemWidthStackSize , " Too many PopItemWidth!" ) ;
1467
if ( table-> InstanceCurrent > 0 )
1468
PopID ( ) ;
1469
PopID ( ) ;
1470
1471
1472
const ImVec2 backup_outer_max_pos = outer_window-> DC . CursorMaxPos ;
1473
inner_window-> WorkRect = temp_data-> HostBackupWorkRect ;
1474
inner_window-> ParentWorkRect = temp_data-> HostBackupParentWorkRect ;
1475
inner_window-> SkipItems = table-> HostSkipItems ;
1476
outer_window-> DC . CursorPos = table-> OuterRect . Min ;
1477
outer_window-> DC . ItemWidth = temp_data-> HostBackupItemWidth ;
1478
outer_window-> DC . ItemWidthStack . Size = temp_data-> HostBackupItemWidthStackSize ;
1479
outer_window-> DC . ColumnsOffset = temp_data-> HostBackupColumnsOffset ;
1480
1481
1482
1483
1484
if ( inner_window != outer_window)
1485
{
1486
short backup_nav_layers_active_mask = inner_window-> DC . NavLayersActiveMask ;
1487
inner_window-> DC . NavLayersActiveMask |= 1 << ImGuiNavLayer_Main;
1488
g. CurrentTable = NULL ;
1489
EndChild ( ) ;
1490
g. CurrentTable = table;
1491
inner_window-> DC . NavLayersActiveMask = backup_nav_layers_active_mask;
1492
}
1493
else
1494
{
1495
ItemSize ( table-> OuterRect . GetSize ( ) ) ;
1496
ItemAdd ( table-> OuterRect , 0 ) ;
1497
}
1498
1499
1500
if ( table-> Flags & ImGuiTableFlags_NoHostExtendX)
1501
{
1502
1503
1504
IM_ASSERT ( ( table-> Flags & ImGuiTableFlags_ScrollX) == 0 ) ;
1505
outer_window-> DC . CursorMaxPos . x = ImMax ( backup_outer_max_pos. x , table-> OuterRect . Min . x + table-> ColumnsAutoFitWidth ) ;
1506
}
1507
else if ( temp_data-> UserOuterSize . x <= 0.0f )
1508
{
1509
1510
1511
1512
const float inner_content_max_x = table-> OuterRect . Min . x + table-> ColumnsAutoFitWidth ;
1513
const float decoration_size = table-> TempData -> AngledHeadersExtraWidth + ( ( table-> Flags & ImGuiTableFlags_ScrollY) ? inner_window-> ScrollbarSizes . x : 0.0f ) ;
1514
outer_window-> DC . IdealMaxPos . x = ImMax ( outer_window-> DC . IdealMaxPos . x , inner_content_max_x + decoration_size - temp_data-> UserOuterSize . x ) ;
1515
outer_window-> DC . CursorMaxPos . x = ImMax ( backup_outer_max_pos. x , ImMin ( table-> OuterRect . Max . x , inner_content_max_x + decoration_size ) ) ;
1516
}
1517
else
1518
{
1519
outer_window-> DC . CursorMaxPos . x = ImMax ( backup_outer_max_pos. x , table-> OuterRect . Max . x ) ;
1520
}
1521
if ( temp_data-> UserOuterSize . y <= 0.0f )
1522
{
1523
const float decoration_size = ( table-> Flags & ImGuiTableFlags_ScrollX) ? inner_window-> ScrollbarSizes . y : 0.0f ;
1524
outer_window-> DC . IdealMaxPos . y = ImMax ( outer_window-> DC . IdealMaxPos . y , inner_content_max_y + decoration_size - temp_data-> UserOuterSize . y ) ;
1525
outer_window-> DC . CursorMaxPos . y = ImMax ( backup_outer_max_pos. y , ImMin ( table-> OuterRect . Max . y , inner_content_max_y + decoration_size ) ) ;
1526
}
1527
else
1528
{
1529
1530
outer_window-> DC . CursorMaxPos . y = ImMax ( backup_outer_max_pos. y , table-> OuterRect . Max . y ) ;
1531
}
1532
1533
1534
if ( table-> IsSettingsDirty )
1535
TableSaveSettings ( table ) ;
1536
table-> IsInitializing = false ;
1537
1538
1539
IM_ASSERT ( g. CurrentWindow == outer_window && g. CurrentTable == table ) ;
1540
IM_ASSERT ( g. TablesTempDataStacked > 0 ) ;
1541
temp_data = ( - - g. TablesTempDataStacked > 0 ) ? & g. TablesTempData [ g. TablesTempDataStacked - 1 ] : NULL ;
1542
g. CurrentTable = temp_data ? g. Tables . GetByIndex ( temp_data-> TableIndex ) : NULL ;
1543
if ( g. CurrentTable )
1544
{
1545
g. CurrentTable -> TempData = temp_data;
1546
g. CurrentTable -> DrawSplitter = & temp_data-> DrawSplitter ;
1547
}
1548
outer_window-> DC . CurrentTableIdx = g. CurrentTable ? g. Tables . GetIndex ( g. CurrentTable ) : - 1 ;
1549
NavUpdateCurrentWindowIsScrollPushableX ( ) ;
1550
}
1551
1552
1553
1554
void ImGui:: TableSetupColumn ( const char * label , ImGuiTableColumnFlags flags , float init_width_or_weight , ImGuiID user_id )
1555
{
1556
ImGuiContext& g = * GImGui;
1557
ImGuiTable* table = g. CurrentTable ;
1558
IM_ASSERT ( table != NULL && " Need to call TableSetupColumn() after BeginTable()!" ) ;
1559
IM_ASSERT ( table-> IsLayoutLocked == false && " Need to call call TableSetupColumn() before first row!" ) ;
1560
IM_ASSERT ( ( flags & ImGuiTableColumnFlags_StatusMask_) == 0 && " Illegal to pass StatusMask values to TableSetupColumn()" ) ;
1561
if ( table-> DeclColumnsCount >= table-> ColumnsCount )
1562
{
1563
IM_ASSERT_USER_ERROR ( table-> DeclColumnsCount < table-> ColumnsCount , " Called TableSetupColumn() too many times!" ) ;
1564
return ;
1565
}
1566
1567
ImGuiTableColumn* column = & table-> Columns [ table-> DeclColumnsCount ] ;
1568
table-> DeclColumnsCount + + ;
1569
1570
1571
1572
if ( table-> IsDefaultSizingPolicy && ( flags & ImGuiTableColumnFlags_WidthMask_) == 0 && ( flags & ImGuiTableFlags_ScrollX) == 0 )
1573
IM_ASSERT ( init_width_or_weight <= 0.0f && " Can only specify width/weight if sizing policy is set explicitly in either Table or Column." ) ;
1574
1575
1576
1577
if ( ( flags & ImGuiTableColumnFlags_WidthMask_) == 0 && init_width_or_weight > 0.0f )
1578
if ( ( table-> Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedFit || ( table-> Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame)
1579
flags |= ImGuiTableColumnFlags_WidthFixed;
1580
if ( flags & ImGuiTableColumnFlags_AngledHeader)
1581
{
1582
flags |= ImGuiTableColumnFlags_NoHeaderLabel;
1583
table-> AngledHeadersCount + + ;
1584
}
1585
1586
TableSetupColumnFlags ( table, column, flags ) ;
1587
column-> UserID = user_id;
1588
flags = column-> Flags ;
1589
1590
1591
column-> InitStretchWeightOrWidth = init_width_or_weight;
1592
if ( table-> IsInitializing )
1593
{
1594
1595
if ( column-> WidthRequest < 0.0f && column-> StretchWeight < 0.0f )
1596
{
1597
if ( ( flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f )
1598
column-> WidthRequest = init_width_or_weight;
1599
if ( flags & ImGuiTableColumnFlags_WidthStretch)
1600
column-> StretchWeight = ( init_width_or_weight > 0.0f ) ? init_width_or_weight : - 1.0f ;
1601
1602
1603
if ( init_width_or_weight > 0.0f )
1604
column-> AutoFitQueue = 0x00 ;
1605
}
1606
1607
1608
if ( ( flags & ImGuiTableColumnFlags_DefaultHide) && ( table-> SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0 )
1609
column-> IsUserEnabled = column-> IsUserEnabledNextFrame = false ;
1610
if ( flags & ImGuiTableColumnFlags_DefaultSort && ( table-> SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0 )
1611
{
1612
column-> SortOrder = 0 ;
1613
column-> SortDirection = ( column-> Flags & ImGuiTableColumnFlags_PreferSortDescending) ? ( ImS8) ImGuiSortDirection_Descending : ( ImU8) ( ImGuiSortDirection_Ascending) ;
1614
}
1615
}
1616
1617
1618
1619
column-> NameOffset = - 1 ;
1620
if ( label != NULL && label[ 0 ] != 0 )
1621
{
1622
column-> NameOffset = ( ImS16) table-> ColumnsNames . size ( ) ;
1623
table-> ColumnsNames . append ( label, label + strlen ( label ) + 1 ) ;
1624
}
1625
}
1626
1627
1628
void ImGui:: TableSetupScrollFreeze ( int columns , int rows )
1629
{
1630
ImGuiContext& g = * GImGui;
1631
ImGuiTable* table = g. CurrentTable ;
1632
IM_ASSERT ( table != NULL && " Need to call TableSetupColumn() after BeginTable()!" ) ;
1633
IM_ASSERT ( table-> IsLayoutLocked == false && " Need to call TableSetupColumn() before first row!" ) ;
1634
IM_ASSERT ( columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS ) ;
1635
IM_ASSERT ( rows >= 0 && rows < 128 ) ;
1636
1637
table-> FreezeColumnsRequest = ( table-> Flags & ImGuiTableFlags_ScrollX) ? ( ImGuiTableColumnIdx) ImMin ( columns, table-> ColumnsCount ) : 0 ;
1638
table-> FreezeColumnsCount = ( table-> InnerWindow -> Scroll . x != 0.0f ) ? table-> FreezeColumnsRequest : 0 ;
1639
table-> FreezeRowsRequest = ( table-> Flags & ImGuiTableFlags_ScrollY) ? ( ImGuiTableColumnIdx) rows : 0 ;
1640
table-> FreezeRowsCount = ( table-> InnerWindow -> Scroll . y != 0.0f ) ? table-> FreezeRowsRequest : 0 ;
1641
table-> IsUnfrozenRows = ( table-> FreezeRowsCount == 0 ) ;
1642
1643
1644
1645
for ( int column_n = 0 ; column_n < table-> FreezeColumnsRequest ; column_n+ + )
1646
{
1647
int order_n = table-> DisplayOrderToIndex [ column_n] ;
1648
if ( order_n != column_n && order_n >= table-> FreezeColumnsRequest )
1649
{
1650
ImSwap ( table-> Columns [ table-> DisplayOrderToIndex [ order_n] ] . DisplayOrder , table-> Columns [ table-> DisplayOrderToIndex [ column_n] ] . DisplayOrder ) ;
1651
ImSwap ( table-> DisplayOrderToIndex [ order_n] , table-> DisplayOrderToIndex [ column_n] ) ;
1652
}
1653
}
1654
}
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
int ImGui:: TableGetColumnCount ( )
1672
{
1673
ImGuiContext& g = * GImGui;
1674
ImGuiTable* table = g. CurrentTable ;
1675
return table ? table-> ColumnsCount : 0 ;
1676
}
1677
1678
const char * ImGui:: TableGetColumnName ( int column_n )
1679
{
1680
ImGuiContext& g = * GImGui;
1681
ImGuiTable* table = g. CurrentTable ;
1682
if ( ! table)
1683
return NULL ;
1684
if ( column_n < 0 )
1685
column_n = table-> CurrentColumn ;
1686
return TableGetColumnName ( table, column_n ) ;
1687
}
1688
1689
const char * ImGui:: TableGetColumnName ( const ImGuiTable* table , int column_n )
1690
{
1691
if ( table-> IsLayoutLocked == false && column_n >= table-> DeclColumnsCount )
1692
return " " ;
1693
const ImGuiTableColumn* column = & table-> Columns [ column_n] ;
1694
if ( column-> NameOffset == - 1 )
1695
return " " ;
1696
return & table-> ColumnsNames . Buf [ column-> NameOffset ] ;
1697
}
1698
1699
1700
1701
1702
1703
1704
1705
void ImGui:: TableSetColumnEnabled ( int column_n , bool enabled )
1706
{
1707
ImGuiContext& g = * GImGui;
1708
ImGuiTable* table = g. CurrentTable ;
1709
IM_ASSERT ( table != NULL ) ;
1710
if ( ! table)
1711
return ;
1712
IM_ASSERT ( table-> Flags & ImGuiTableFlags_Hideable ) ;
1713
if ( column_n < 0 )
1714
column_n = table-> CurrentColumn ;
1715
IM_ASSERT ( column_n >= 0 && column_n < table-> ColumnsCount ) ;
1716
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
1717
column-> IsUserEnabledNextFrame = enabled;
1718
}
1719
1720
1721
ImGuiTableColumnFlags ImGui:: TableGetColumnFlags ( int column_n )
1722
{
1723
ImGuiContext& g = * GImGui;
1724
ImGuiTable* table = g. CurrentTable ;
1725
if ( ! table)
1726
return ImGuiTableColumnFlags_None;
1727
if ( column_n < 0 )
1728
column_n = table-> CurrentColumn ;
1729
if ( column_n == table-> ColumnsCount )
1730
return ( table-> HoveredColumnBody == column_n) ? ImGuiTableColumnFlags_IsHovered : ImGuiTableColumnFlags_None;
1731
return table-> Columns [ column_n] . Flags ;
1732
}
1733
1734
1735
1736
1737
1738
1739
1740
ImRect ImGui:: TableGetCellBgRect ( const ImGuiTable* table , int column_n )
1741
{
1742
const ImGuiTableColumn* column = & table-> Columns [ column_n] ;
1743
float x1 = column-> MinX ;
1744
float x2 = column-> MaxX ;
1745
1746
1747
1748
1749
x1 = ImMax ( x1, table-> WorkRect . Min . x ) ;
1750
x2 = ImMin ( x2, table-> WorkRect . Max . x ) ;
1751
return ImRect ( x1, table-> RowPosY1 , x2, table-> RowPosY2 ) ;
1752
}
1753
1754
1755
ImGuiID ImGui:: TableGetColumnResizeID ( ImGuiTable* table , int column_n , int instance_no )
1756
{
1757
IM_ASSERT ( column_n >= 0 && column_n < table-> ColumnsCount ) ;
1758
ImGuiID instance_id = TableGetInstanceID ( table, instance_no ) ;
1759
return instance_id + 1 + column_n;
1760
}
1761
1762
1763
int ImGui:: TableGetHoveredColumn ( )
1764
{
1765
ImGuiContext& g = * GImGui;
1766
ImGuiTable* table = g. CurrentTable ;
1767
if ( ! table)
1768
return - 1 ;
1769
return ( int ) table-> HoveredColumnBody ;
1770
}
1771
1772
1773
1774
1775
int ImGui:: TableGetHoveredRow ( )
1776
{
1777
ImGuiContext& g = * GImGui;
1778
ImGuiTable* table = g. CurrentTable ;
1779
if ( ! table)
1780
return - 1 ;
1781
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, table-> InstanceCurrent ) ;
1782
return ( int ) table_instance-> HoveredRowLast ;
1783
}
1784
1785
void ImGui:: TableSetBgColor ( ImGuiTableBgTarget target , ImU32 color , int column_n )
1786
{
1787
ImGuiContext& g = * GImGui;
1788
ImGuiTable* table = g. CurrentTable ;
1789
IM_ASSERT ( target != ImGuiTableBgTarget_None ) ;
1790
1791
if ( color == IM_COL32_DISABLE)
1792
color = 0 ;
1793
1794
1795
switch ( target)
1796
{
1797
case ImGuiTableBgTarget_CellBg:
1798
{
1799
if ( table-> RowPosY1 > table-> InnerClipRect . Max . y )
1800
return ;
1801
if ( column_n == - 1 )
1802
column_n = table-> CurrentColumn ;
1803
if ( ! IM_BITARRAY_TESTBIT ( table-> VisibleMaskByIndex , column_n ) )
1804
return ;
1805
if ( table-> RowCellDataCurrent < 0 || table-> RowCellData [ table-> RowCellDataCurrent ] . Column != column_n)
1806
table-> RowCellDataCurrent + + ;
1807
ImGuiTableCellData* cell_data = & table-> RowCellData [ table-> RowCellDataCurrent ] ;
1808
cell_data-> BgColor = color;
1809
cell_data-> Column = ( ImGuiTableColumnIdx) column_n;
1810
break ;
1811
}
1812
case ImGuiTableBgTarget_RowBg0:
1813
case ImGuiTableBgTarget_RowBg1:
1814
{
1815
if ( table-> RowPosY1 > table-> InnerClipRect . Max . y )
1816
return ;
1817
IM_ASSERT ( column_n == - 1 ) ;
1818
int bg_idx = ( target == ImGuiTableBgTarget_RowBg1) ? 1 : 0 ;
1819
table-> RowBgColor [ bg_idx] = color;
1820
break ;
1821
}
1822
default :
1823
IM_ASSERT ( 0 ) ;
1824
}
1825
}
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
int ImGui:: TableGetRowIndex ( )
1838
{
1839
ImGuiContext& g = * GImGui;
1840
ImGuiTable* table = g. CurrentTable ;
1841
if ( ! table)
1842
return 0 ;
1843
return table-> CurrentRow ;
1844
}
1845
1846
1847
void ImGui:: TableNextRow ( ImGuiTableRowFlags row_flags , float row_min_height )
1848
{
1849
ImGuiContext& g = * GImGui;
1850
ImGuiTable* table = g. CurrentTable ;
1851
1852
if ( ! table-> IsLayoutLocked )
1853
TableUpdateLayout ( table ) ;
1854
if ( table-> IsInsideRow )
1855
TableEndRow ( table ) ;
1856
1857
table-> LastRowFlags = table-> RowFlags ;
1858
table-> RowFlags = row_flags;
1859
table-> RowCellPaddingY = g. Style . CellPadding . y ;
1860
table-> RowMinHeight = row_min_height;
1861
TableBeginRow ( table ) ;
1862
1863
1864
1865
table-> RowPosY2 += table-> RowCellPaddingY * 2.0f ;
1866
table-> RowPosY2 = ImMax ( table-> RowPosY2 , table-> RowPosY1 + row_min_height ) ;
1867
1868
1869
table-> InnerWindow -> SkipItems = true ;
1870
}
1871
1872
1873
void ImGui:: TableBeginRow ( ImGuiTable* table )
1874
{
1875
ImGuiWindow* window = table-> InnerWindow ;
1876
IM_ASSERT ( ! table-> IsInsideRow ) ;
1877
1878
1879
table-> CurrentRow + + ;
1880
table-> CurrentColumn = - 1 ;
1881
table-> RowBgColor [ 0 ] = table-> RowBgColor [ 1 ] = IM_COL32_DISABLE;
1882
table-> RowCellDataCurrent = - 1 ;
1883
table-> IsInsideRow = true ;
1884
1885
1886
float next_y1 = table-> RowPosY2 ;
1887
if ( table-> CurrentRow == 0 && table-> FreezeRowsCount > 0 )
1888
next_y1 = window-> DC . CursorPos . y = table-> OuterRect . Min . y ;
1889
1890
table-> RowPosY1 = table-> RowPosY2 = next_y1;
1891
table-> RowTextBaseline = 0.0f ;
1892
table-> RowIndentOffsetX = window-> DC . Indent . x - table-> HostIndentX ;
1893
1894
window-> DC . PrevLineTextBaseOffset = 0.0f ;
1895
window-> DC . CursorPosPrevLine = ImVec2 ( window-> DC . CursorPos . x , window-> DC . CursorPos . y + table-> RowCellPaddingY ) ;
1896
window-> DC . PrevLineSize = window-> DC . CurrLineSize = ImVec2 ( 0.0f , 0.0f ) ;
1897
window-> DC . IsSameLine = window-> DC . IsSetPos = false ;
1898
window-> DC . CursorMaxPos . y = next_y1;
1899
1900
1901
if ( table-> RowFlags & ImGuiTableRowFlags_Headers)
1902
{
1903
TableSetBgColor ( ImGuiTableBgTarget_RowBg0, GetColorU32 ( ImGuiCol_TableHeaderBg ) ) ;
1904
if ( table-> CurrentRow == 0 )
1905
table-> IsUsingHeaders = true ;
1906
}
1907
}
1908
1909
1910
void ImGui:: TableEndRow ( ImGuiTable* table )
1911
{
1912
ImGuiContext& g = * GImGui;
1913
ImGuiWindow* window = g. CurrentWindow ;
1914
IM_ASSERT ( window == table-> InnerWindow ) ;
1915
IM_ASSERT ( table-> IsInsideRow ) ;
1916
1917
if ( table-> CurrentColumn != - 1 )
1918
TableEndCell ( table ) ;
1919
1920
1921
if ( g. LogEnabled )
1922
LogRenderedText ( NULL , " |" ) ;
1923
1924
1925
1926
window-> DC . CursorPos . y = table-> RowPosY2 ;
1927
1928
1929
const float bg_y1 = table-> RowPosY1 ;
1930
const float bg_y2 = table-> RowPosY2 ;
1931
const bool unfreeze_rows_actual = ( table-> CurrentRow + 1 == table-> FreezeRowsCount ) ;
1932
const bool unfreeze_rows_request = ( table-> CurrentRow + 1 == table-> FreezeRowsRequest ) ;
1933
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, table-> InstanceCurrent ) ;
1934
if ( ( table-> RowFlags & ImGuiTableRowFlags_Headers) && ( table-> CurrentRow == 0 || ( table-> LastRowFlags & ImGuiTableRowFlags_Headers) ) )
1935
table_instance-> LastTopHeadersRowHeight += bg_y2 - bg_y1;
1936
1937
const bool is_visible = ( bg_y2 >= table-> InnerClipRect . Min . y && bg_y1 <= table-> InnerClipRect . Max . y ) ;
1938
if ( is_visible)
1939
{
1940
1941
if ( table-> HoveredColumnBody != - 1 && g. IO . MousePos . y >= bg_y1 && g. IO . MousePos . y < bg_y2 && table_instance-> HoveredRowNext < 0 )
1942
table_instance-> HoveredRowNext = table-> CurrentRow ;
1943
1944
1945
ImU32 bg_col0 = 0 ;
1946
ImU32 bg_col1 = 0 ;
1947
if ( table-> RowBgColor [ 0 ] != IM_COL32_DISABLE)
1948
bg_col0 = table-> RowBgColor [ 0 ] ;
1949
else if ( table-> Flags & ImGuiTableFlags_RowBg)
1950
bg_col0 = GetColorU32 ( ( table-> RowBgColorCounter & 1 ) ? ImGuiCol_TableRowBgAlt : ImGuiCol_TableRowBg) ;
1951
if ( table-> RowBgColor [ 1 ] != IM_COL32_DISABLE)
1952
bg_col1 = table-> RowBgColor [ 1 ] ;
1953
1954
1955
ImU32 top_border_col = 0 ;
1956
const float border_size = TABLE_BORDER_SIZE;
1957
if ( table-> CurrentRow > 0 && ( table-> Flags & ImGuiTableFlags_BordersInnerH) )
1958
top_border_col = ( table-> LastRowFlags & ImGuiTableRowFlags_Headers) ? table-> BorderColorStrong : table-> BorderColorLight ;
1959
1960
const bool draw_cell_bg_color = table-> RowCellDataCurrent >= 0 ;
1961
const bool draw_strong_bottom_border = unfreeze_rows_actual;
1962
if ( ( bg_col0 | bg_col1 | top_border_col) != 0 || draw_strong_bottom_border || draw_cell_bg_color)
1963
{
1964
1965
1966
if ( ( table-> Flags & ImGuiTableFlags_NoClip) == 0 )
1967
window-> DrawList -> _CmdHeader . ClipRect = table-> Bg0ClipRectForDrawCmd . ToVec4 ( ) ;
1968
table-> DrawSplitter -> SetCurrentChannel ( window-> DrawList , TABLE_DRAW_CHANNEL_BG0 ) ;
1969
}
1970
1971
1972
1973
if ( bg_col0 || bg_col1)
1974
{
1975
ImRect row_rect ( table-> WorkRect . Min . x , bg_y1, table-> WorkRect . Max . x , bg_y2 ) ;
1976
row_rect. ClipWith ( table-> BgClipRect ) ;
1977
if ( bg_col0 != 0 && row_rect. Min . y < row_rect. Max . y )
1978
window-> DrawList -> AddRectFilled ( row_rect. Min , row_rect. Max , bg_col0 ) ;
1979
if ( bg_col1 != 0 && row_rect. Min . y < row_rect. Max . y )
1980
window-> DrawList -> AddRectFilled ( row_rect. Min , row_rect. Max , bg_col1 ) ;
1981
}
1982
1983
1984
if ( draw_cell_bg_color)
1985
{
1986
ImGuiTableCellData* cell_data_end = & table-> RowCellData [ table-> RowCellDataCurrent ] ;
1987
for ( ImGuiTableCellData* cell_data = & table-> RowCellData [ 0 ] ; cell_data <= cell_data_end; cell_data+ + )
1988
{
1989
1990
1991
const ImGuiTableColumn* column = & table-> Columns [ cell_data-> Column ] ;
1992
ImRect cell_bg_rect = TableGetCellBgRect ( table, cell_data-> Column ) ;
1993
cell_bg_rect. ClipWith ( table-> BgClipRect ) ;
1994
cell_bg_rect. Min . x = ImMax ( cell_bg_rect. Min . x , column-> ClipRect . Min . x ) ;
1995
cell_bg_rect. Max . x = ImMin ( cell_bg_rect. Max . x , column-> MaxX ) ;
1996
if ( cell_bg_rect. Min . y < cell_bg_rect. Max . y )
1997
window-> DrawList -> AddRectFilled ( cell_bg_rect. Min , cell_bg_rect. Max , cell_data-> BgColor ) ;
1998
}
1999
}
2000
2001
2002
if ( top_border_col && bg_y1 >= table-> BgClipRect . Min . y && bg_y1 < table-> BgClipRect . Max . y )
2003
window-> DrawList -> AddLine ( ImVec2 ( table-> BorderX1 , bg_y1 ) , ImVec2 ( table-> BorderX2 , bg_y1 ) , top_border_col, border_size) ;
2004
2005
2006
if ( draw_strong_bottom_border && bg_y2 >= table-> BgClipRect . Min . y && bg_y2 < table-> BgClipRect . Max . y )
2007
window-> DrawList -> AddLine ( ImVec2 ( table-> BorderX1 , bg_y2 ) , ImVec2 ( table-> BorderX2 , bg_y2 ) , table-> BorderColorStrong , border_size) ;
2008
}
2009
2010
2011
2012
2013
if ( unfreeze_rows_request)
2014
{
2015
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2016
table-> Columns [ column_n] . NavLayerCurrent = ImGuiNavLayer_Main;
2017
const float y0 = ImMax ( table-> RowPosY2 + 1 , table-> InnerClipRect . Min . y ) ;
2018
table_instance-> LastFrozenHeight = y0 - table-> OuterRect . Min . y ;
2019
2020
if ( unfreeze_rows_actual)
2021
{
2022
IM_ASSERT ( table-> IsUnfrozenRows == false ) ;
2023
table-> IsUnfrozenRows = true ;
2024
2025
2026
table-> BgClipRect . Min . y = table-> Bg2ClipRectForDrawCmd . Min . y = ImMin ( y0, table-> InnerClipRect . Max . y ) ;
2027
table-> BgClipRect . Max . y = table-> Bg2ClipRectForDrawCmd . Max . y = table-> InnerClipRect . Max . y ;
2028
table-> Bg2DrawChannelCurrent = table-> Bg2DrawChannelUnfrozen ;
2029
IM_ASSERT ( table-> Bg2ClipRectForDrawCmd . Min . y <= table-> Bg2ClipRectForDrawCmd . Max . y ) ;
2030
2031
float row_height = table-> RowPosY2 - table-> RowPosY1 ;
2032
table-> RowPosY2 = window-> DC . CursorPos . y = table-> WorkRect . Min . y + table-> RowPosY2 - table-> OuterRect . Min . y ;
2033
table-> RowPosY1 = table-> RowPosY2 - row_height;
2034
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2035
{
2036
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2037
column-> DrawChannelCurrent = column-> DrawChannelUnfrozen ;
2038
column-> ClipRect . Min . y = table-> Bg2ClipRectForDrawCmd . Min . y ;
2039
}
2040
2041
2042
SetWindowClipRectBeforeSetChannel ( window, table-> Columns [ 0 ] . ClipRect ) ;
2043
table-> DrawSplitter -> SetCurrentChannel ( window-> DrawList , table-> Columns [ 0 ] . DrawChannelCurrent ) ;
2044
}
2045
}
2046
2047
if ( ! ( table-> RowFlags & ImGuiTableRowFlags_Headers) )
2048
table-> RowBgColorCounter + + ;
2049
table-> IsInsideRow = false ;
2050
}
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
int ImGui:: TableGetColumnIndex ( )
2063
{
2064
ImGuiContext& g = * GImGui;
2065
ImGuiTable* table = g. CurrentTable ;
2066
if ( ! table)
2067
return 0 ;
2068
return table-> CurrentColumn ;
2069
}
2070
2071
2072
bool ImGui:: TableSetColumnIndex ( int column_n )
2073
{
2074
ImGuiContext& g = * GImGui;
2075
ImGuiTable* table = g. CurrentTable ;
2076
if ( ! table)
2077
return false ;
2078
2079
if ( table-> CurrentColumn != column_n)
2080
{
2081
if ( table-> CurrentColumn != - 1 )
2082
TableEndCell ( table ) ;
2083
IM_ASSERT ( column_n >= 0 && table-> ColumnsCount ) ;
2084
TableBeginCell ( table, column_n ) ;
2085
}
2086
2087
2088
2089
return table-> Columns [ column_n] . IsRequestOutput ;
2090
}
2091
2092
2093
bool ImGui:: TableNextColumn ( )
2094
{
2095
ImGuiContext& g = * GImGui;
2096
ImGuiTable* table = g. CurrentTable ;
2097
if ( ! table)
2098
return false ;
2099
2100
if ( table-> IsInsideRow && table-> CurrentColumn + 1 < table-> ColumnsCount )
2101
{
2102
if ( table-> CurrentColumn != - 1 )
2103
TableEndCell ( table ) ;
2104
TableBeginCell ( table, table-> CurrentColumn + 1 ) ;
2105
}
2106
else
2107
{
2108
TableNextRow ( ) ;
2109
TableBeginCell ( table, 0 ) ;
2110
}
2111
2112
2113
2114
return table-> Columns [ table-> CurrentColumn ] . IsRequestOutput ;
2115
}
2116
2117
2118
2119
2120
2121
void ImGui:: TableBeginCell ( ImGuiTable* table , int column_n )
2122
{
2123
ImGuiContext& g = * GImGui;
2124
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2125
ImGuiWindow* window = table-> InnerWindow ;
2126
table-> CurrentColumn = column_n;
2127
2128
2129
float start_x = column-> WorkMinX ;
2130
if ( column-> Flags & ImGuiTableColumnFlags_IndentEnable)
2131
start_x += table-> RowIndentOffsetX ;
2132
2133
window-> DC . CursorPos . x = start_x;
2134
window-> DC . CursorPos . y = table-> RowPosY1 + table-> RowCellPaddingY ;
2135
window-> DC . CursorMaxPos . x = window-> DC . CursorPos . x ;
2136
window-> DC . ColumnsOffset . x = start_x - window-> Pos . x - window-> DC . Indent . x ;
2137
window-> DC . CursorPosPrevLine . x = window-> DC . CursorPos . x ;
2138
window-> DC . CurrLineTextBaseOffset = table-> RowTextBaseline ;
2139
window-> DC . NavLayerCurrent = ( ImGuiNavLayer) column-> NavLayerCurrent ;
2140
2141
2142
window-> WorkRect . Min . y = window-> DC . CursorPos . y ;
2143
window-> WorkRect . Min . x = column-> WorkMinX ;
2144
window-> WorkRect . Max . x = column-> WorkMaxX ;
2145
window-> DC . ItemWidth = column-> ItemWidth ;
2146
2147
window-> SkipItems = column-> IsSkipItems ;
2148
if ( column-> IsSkipItems )
2149
{
2150
g. LastItemData . ID = 0 ;
2151
g. LastItemData . StatusFlags = 0 ;
2152
}
2153
2154
if ( table-> Flags & ImGuiTableFlags_NoClip)
2155
{
2156
2157
table-> DrawSplitter -> SetCurrentChannel ( window-> DrawList , TABLE_DRAW_CHANNEL_NOCLIP ) ;
2158
2159
}
2160
else
2161
{
2162
2163
SetWindowClipRectBeforeSetChannel ( window, column-> ClipRect ) ;
2164
table-> DrawSplitter -> SetCurrentChannel ( window-> DrawList , column-> DrawChannelCurrent ) ;
2165
}
2166
2167
2168
if ( g. LogEnabled && ! column-> IsSkipItems )
2169
{
2170
LogRenderedText ( & window-> DC . CursorPos , " |" ) ;
2171
g. LogLinePosY = FLT_MAX;
2172
}
2173
}
2174
2175
2176
void ImGui:: TableEndCell ( ImGuiTable* table )
2177
{
2178
ImGuiTableColumn* column = & table-> Columns [ table-> CurrentColumn ] ;
2179
ImGuiWindow* window = table-> InnerWindow ;
2180
2181
if ( window-> DC . IsSetPos )
2182
ErrorCheckUsingSetCursorPosToExtendParentBoundaries ( ) ;
2183
2184
2185
float * p_max_pos_x;
2186
if ( table-> RowFlags & ImGuiTableRowFlags_Headers)
2187
p_max_pos_x = & column-> ContentMaxXHeadersUsed ;
2188
else
2189
p_max_pos_x = table-> IsUnfrozenRows ? & column-> ContentMaxXUnfrozen : & column-> ContentMaxXFrozen ;
2190
* p_max_pos_x = ImMax ( * p_max_pos_x, window-> DC . CursorMaxPos . x ) ;
2191
if ( column-> IsEnabled )
2192
table-> RowPosY2 = ImMax ( table-> RowPosY2 , window-> DC . CursorMaxPos . y + table-> RowCellPaddingY ) ;
2193
column-> ItemWidth = window-> DC . ItemWidth ;
2194
2195
2196
2197
table-> RowTextBaseline = ImMax ( table-> RowTextBaseline , window-> DC . PrevLineTextBaseOffset ) ;
2198
}
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
float ImGui:: TableCalcMaxColumnWidth ( const ImGuiTable* table , int column_n )
2215
{
2216
const ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2217
float max_width = FLT_MAX;
2218
const float min_column_distance = table-> MinColumnWidth + table-> CellPaddingX * 2.0f + table-> CellSpacingX1 + table-> CellSpacingX2 ;
2219
if ( table-> Flags & ImGuiTableFlags_ScrollX)
2220
{
2221
2222
2223
if ( column-> DisplayOrder < table-> FreezeColumnsRequest )
2224
{
2225
max_width = ( table-> InnerClipRect . Max . x - ( table-> FreezeColumnsRequest - column-> DisplayOrder ) * min_column_distance) - column-> MinX ;
2226
max_width = max_width - table-> OuterPaddingX - table-> CellPaddingX - table-> CellSpacingX2 ;
2227
}
2228
}
2229
else if ( ( table-> Flags & ImGuiTableFlags_NoKeepColumnsVisible) == 0 )
2230
{
2231
2232
2233
2234
2235
2236
max_width = table-> WorkRect . Max . x - ( table-> ColumnsEnabledCount - column-> IndexWithinEnabledSet - 1 ) * min_column_distance - column-> MinX ;
2237
2238
max_width -= table-> CellSpacingX2 ;
2239
max_width -= table-> CellPaddingX * 2.0f ;
2240
max_width -= table-> OuterPaddingX ;
2241
}
2242
return max_width;
2243
}
2244
2245
2246
float ImGui:: TableGetColumnWidthAuto ( ImGuiTable* table , ImGuiTableColumn* column )
2247
{
2248
const float content_width_body = ImMax ( column-> ContentMaxXFrozen , column-> ContentMaxXUnfrozen ) - column-> WorkMinX ;
2249
const float content_width_headers = column-> ContentMaxXHeadersIdeal - column-> WorkMinX ;
2250
float width_auto = content_width_body;
2251
if ( ! ( column-> Flags & ImGuiTableColumnFlags_NoHeaderWidth) )
2252
width_auto = ImMax ( width_auto, content_width_headers ) ;
2253
2254
2255
if ( ( column-> Flags & ImGuiTableColumnFlags_WidthFixed) && column-> InitStretchWeightOrWidth > 0.0f )
2256
if ( ! ( table-> Flags & ImGuiTableFlags_Resizable) || ( column-> Flags & ImGuiTableColumnFlags_NoResize) )
2257
width_auto = column-> InitStretchWeightOrWidth ;
2258
2259
return ImMax ( width_auto, table-> MinColumnWidth ) ;
2260
}
2261
2262
2263
void ImGui:: TableSetColumnWidth ( int column_n , float width )
2264
{
2265
ImGuiContext& g = * GImGui;
2266
ImGuiTable* table = g. CurrentTable ;
2267
IM_ASSERT ( table != NULL && table-> IsLayoutLocked == false ) ;
2268
IM_ASSERT ( column_n >= 0 && column_n < table-> ColumnsCount ) ;
2269
ImGuiTableColumn* column_0 = & table-> Columns [ column_n] ;
2270
float column_0_width = width;
2271
2272
2273
2274
IM_ASSERT ( table-> MinColumnWidth > 0.0f ) ;
2275
const float min_width = table-> MinColumnWidth ;
2276
const float max_width = ImMax ( min_width, column_0-> WidthMax ) ;
2277
column_0_width = ImClamp ( column_0_width, min_width, max_width ) ;
2278
if ( column_0-> WidthGiven == column_0_width || column_0-> WidthRequest == column_0_width)
2279
return ;
2280
2281
2282
ImGuiTableColumn* column_1 = ( column_0-> NextEnabledColumn != - 1 ) ? & table-> Columns [ column_0-> NextEnabledColumn ] : NULL ;
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
if ( column_0-> Flags & ImGuiTableColumnFlags_WidthFixed)
2319
if ( ! column_1 || table-> LeftMostStretchedColumn == - 1 || table-> Columns [ table-> LeftMostStretchedColumn ] . DisplayOrder >= column_0-> DisplayOrder )
2320
{
2321
column_0-> WidthRequest = column_0_width;
2322
table-> IsSettingsDirty = true ;
2323
return ;
2324
}
2325
2326
2327
if ( column_1 == NULL )
2328
column_1 = ( column_0-> PrevEnabledColumn != - 1 ) ? & table-> Columns [ column_0-> PrevEnabledColumn ] : NULL ;
2329
if ( column_1 == NULL )
2330
return ;
2331
2332
2333
2334
float column_1_width = ImMax ( column_1-> WidthRequest - ( column_0_width - column_0-> WidthRequest ) , min_width ) ;
2335
column_0_width = column_0-> WidthRequest + column_1-> WidthRequest - column_1_width;
2336
IM_ASSERT ( column_0_width > 0.0f && column_1_width > 0.0f ) ;
2337
column_0-> WidthRequest = column_0_width;
2338
column_1-> WidthRequest = column_1_width;
2339
if ( ( column_0-> Flags | column_1-> Flags ) & ImGuiTableColumnFlags_WidthStretch)
2340
TableUpdateColumnsWeightFromWidth ( table ) ;
2341
table-> IsSettingsDirty = true ;
2342
}
2343
2344
2345
2346
void ImGui:: TableSetColumnWidthAutoSingle ( ImGuiTable* table , int column_n )
2347
{
2348
2349
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2350
if ( ! column-> IsEnabled )
2351
return ;
2352
column-> CannotSkipItemsQueue = ( 1 << 0 ) ;
2353
table-> AutoFitSingleColumn = ( ImGuiTableColumnIdx) column_n;
2354
}
2355
2356
void ImGui:: TableSetColumnWidthAutoAll ( ImGuiTable* table )
2357
{
2358
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2359
{
2360
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2361
if ( ! column-> IsEnabled && ! ( column-> Flags & ImGuiTableColumnFlags_WidthStretch) )
2362
continue ;
2363
column-> CannotSkipItemsQueue = ( 1 << 0 ) ;
2364
column-> AutoFitQueue = ( 1 << 1 ) ;
2365
}
2366
}
2367
2368
void ImGui:: TableUpdateColumnsWeightFromWidth ( ImGuiTable* table )
2369
{
2370
IM_ASSERT ( table-> LeftMostStretchedColumn != - 1 && table-> RightMostStretchedColumn != - 1 ) ;
2371
2372
2373
float visible_weight = 0.0f ;
2374
float visible_width = 0.0f ;
2375
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2376
{
2377
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2378
if ( ! column-> IsEnabled || ! ( column-> Flags & ImGuiTableColumnFlags_WidthStretch) )
2379
continue ;
2380
IM_ASSERT ( column-> StretchWeight > 0.0f ) ;
2381
visible_weight += column-> StretchWeight ;
2382
visible_width += column-> WidthRequest ;
2383
}
2384
IM_ASSERT ( visible_weight > 0.0f && visible_width > 0.0f ) ;
2385
2386
2387
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2388
{
2389
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2390
if ( ! column-> IsEnabled || ! ( column-> Flags & ImGuiTableColumnFlags_WidthStretch) )
2391
continue ;
2392
column-> StretchWeight = ( column-> WidthRequest / visible_width) * visible_weight;
2393
IM_ASSERT ( column-> StretchWeight > 0.0f ) ;
2394
}
2395
}
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
void ImGui:: TablePushBackgroundChannel ( )
2411
{
2412
ImGuiContext& g = * GImGui;
2413
ImGuiWindow* window = g. CurrentWindow ;
2414
ImGuiTable* table = g. CurrentTable ;
2415
2416
2417
table-> HostBackupInnerClipRect = window-> ClipRect ;
2418
SetWindowClipRectBeforeSetChannel ( window, table-> Bg2ClipRectForDrawCmd ) ;
2419
table-> DrawSplitter -> SetCurrentChannel ( window-> DrawList , table-> Bg2DrawChannelCurrent ) ;
2420
}
2421
2422
void ImGui:: TablePopBackgroundChannel ( )
2423
{
2424
ImGuiContext& g = * GImGui;
2425
ImGuiWindow* window = g. CurrentWindow ;
2426
ImGuiTable* table = g. CurrentTable ;
2427
ImGuiTableColumn* column = & table-> Columns [ table-> CurrentColumn ] ;
2428
2429
2430
SetWindowClipRectBeforeSetChannel ( window, table-> HostBackupInnerClipRect ) ;
2431
table-> DrawSplitter -> SetCurrentChannel ( window-> DrawList , column-> DrawChannelCurrent ) ;
2432
}
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
void ImGui:: TableSetupDrawChannels ( ImGuiTable* table )
2451
{
2452
const int freeze_row_multiplier = ( table-> FreezeRowsCount > 0 ) ? 2 : 1 ;
2453
const int channels_for_row = ( table-> Flags & ImGuiTableFlags_NoClip) ? 1 : table-> ColumnsEnabledCount ;
2454
const int channels_for_bg = 1 + 1 * freeze_row_multiplier;
2455
const int channels_for_dummy = ( table-> ColumnsEnabledCount < table-> ColumnsCount || ( memcmp ( table-> VisibleMaskByIndex , table-> EnabledMaskByIndex , ImBitArrayGetStorageSizeInBytes ( table-> ColumnsCount ) ) != 0 ) ) ? + 1 : 0 ;
2456
const int channels_total = channels_for_bg + ( channels_for_row * freeze_row_multiplier) + channels_for_dummy;
2457
table-> DrawSplitter -> Split ( table-> InnerWindow -> DrawList , channels_total ) ;
2458
table-> DummyDrawChannel = ( ImGuiTableDrawChannelIdx) ( ( channels_for_dummy > 0 ) ? channels_total - 1 : - 1 ) ;
2459
table-> Bg2DrawChannelCurrent = TABLE_DRAW_CHANNEL_BG2_FROZEN;
2460
table-> Bg2DrawChannelUnfrozen = ( ImGuiTableDrawChannelIdx) ( ( table-> FreezeRowsCount > 0 ) ? 2 + channels_for_row : TABLE_DRAW_CHANNEL_BG2_FROZEN) ;
2461
2462
int draw_channel_current = 2 ;
2463
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2464
{
2465
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2466
if ( column-> IsVisibleX && column-> IsVisibleY )
2467
{
2468
column-> DrawChannelFrozen = ( ImGuiTableDrawChannelIdx) ( draw_channel_current) ;
2469
column-> DrawChannelUnfrozen = ( ImGuiTableDrawChannelIdx) ( draw_channel_current + ( table-> FreezeRowsCount > 0 ? channels_for_row + 1 : 0 ) ) ;
2470
if ( ! ( table-> Flags & ImGuiTableFlags_NoClip) )
2471
draw_channel_current+ + ;
2472
}
2473
else
2474
{
2475
column-> DrawChannelFrozen = column-> DrawChannelUnfrozen = table-> DummyDrawChannel ;
2476
}
2477
column-> DrawChannelCurrent = column-> DrawChannelFrozen ;
2478
}
2479
2480
2481
2482
2483
table-> BgClipRect = table-> InnerClipRect ;
2484
table-> Bg0ClipRectForDrawCmd = table-> OuterWindow -> ClipRect ;
2485
table-> Bg2ClipRectForDrawCmd = table-> HostClipRect ;
2486
IM_ASSERT ( table-> BgClipRect . Min . y <= table-> BgClipRect . Max . y ) ;
2487
}
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
void ImGui:: TableMergeDrawChannels ( ImGuiTable* table )
2519
{
2520
ImGuiContext& g = * GImGui;
2521
ImDrawListSplitter* splitter = table-> DrawSplitter ;
2522
const bool has_freeze_v = ( table-> FreezeRowsCount > 0 ) ;
2523
const bool has_freeze_h = ( table-> FreezeColumnsCount > 0 ) ;
2524
IM_ASSERT ( splitter-> _Current == 0 ) ;
2525
2526
2527
struct MergeGroup
2528
{
2529
ImRect ClipRect;
2530
int ChannelsCount = 0 ;
2531
ImBitArrayPtr ChannelsMask = NULL ;
2532
} ;
2533
int merge_group_mask = 0x00 ;
2534
MergeGroup merge_groups[ 4 ] ;
2535
2536
2537
const int max_draw_channels = ( 4 + table-> ColumnsCount * 2 ) ;
2538
const int size_for_masks_bitarrays_one = ( int ) ImBitArrayGetStorageSizeInBytes ( max_draw_channels ) ;
2539
g. TempBuffer . reserve ( size_for_masks_bitarrays_one * 5 ) ;
2540
memset ( g. TempBuffer . Data , 0 , size_for_masks_bitarrays_one * 5 ) ;
2541
for ( int n = 0 ; n < IM_ARRAYSIZE ( merge_groups ) ; n+ + )
2542
merge_groups[ n] . ChannelsMask = ( ImBitArrayPtr) ( void * ) ( g. TempBuffer . Data + ( size_for_masks_bitarrays_one * n) ) ;
2543
ImBitArrayPtr remaining_mask = ( ImBitArrayPtr) ( void * ) ( g. TempBuffer . Data + ( size_for_masks_bitarrays_one * 4 ) ) ;
2544
2545
2546
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2547
{
2548
if ( ! IM_BITARRAY_TESTBIT ( table-> VisibleMaskByIndex , column_n ) )
2549
continue ;
2550
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2551
2552
const int merge_group_sub_count = has_freeze_v ? 2 : 1 ;
2553
for ( int merge_group_sub_n = 0 ; merge_group_sub_n < merge_group_sub_count; merge_group_sub_n+ + )
2554
{
2555
const int channel_no = ( merge_group_sub_n == 0 ) ? column-> DrawChannelFrozen : column-> DrawChannelUnfrozen ;
2556
2557
2558
ImDrawChannel* src_channel = & splitter-> _Channels [ channel_no] ;
2559
if ( src_channel-> _CmdBuffer . Size > 0 && src_channel-> _CmdBuffer . back ( ) . ElemCount == 0 && src_channel-> _CmdBuffer . back ( ) . UserCallback == NULL )
2560
src_channel-> _CmdBuffer . pop_back ( ) ;
2561
if ( src_channel-> _CmdBuffer . Size != 1 )
2562
continue ;
2563
2564
2565
2566
if ( ! ( column-> Flags & ImGuiTableColumnFlags_NoClip) )
2567
{
2568
float content_max_x;
2569
if ( ! has_freeze_v)
2570
content_max_x = ImMax ( column-> ContentMaxXUnfrozen , column-> ContentMaxXHeadersUsed ) ;
2571
else if ( merge_group_sub_n == 0 )
2572
content_max_x = ImMax ( column-> ContentMaxXFrozen , column-> ContentMaxXHeadersUsed ) ;
2573
else
2574
content_max_x = column-> ContentMaxXUnfrozen ;
2575
if ( content_max_x > column-> ClipRect . Max . x )
2576
continue ;
2577
}
2578
2579
const int merge_group_n = ( has_freeze_h && column_n < table-> FreezeColumnsCount ? 0 : 1 ) + ( has_freeze_v && merge_group_sub_n == 0 ? 0 : 2 ) ;
2580
IM_ASSERT ( channel_no < max_draw_channels ) ;
2581
MergeGroup* merge_group = & merge_groups[ merge_group_n] ;
2582
if ( merge_group-> ChannelsCount == 0 )
2583
merge_group-> ClipRect = ImRect ( + FLT_MAX, + FLT_MAX, - FLT_MAX, - FLT_MAX) ;
2584
ImBitArraySetBit ( merge_group-> ChannelsMask , channel_no ) ;
2585
merge_group-> ChannelsCount + + ;
2586
merge_group-> ClipRect . Add ( src_channel-> _CmdBuffer [ 0 ] . ClipRect ) ;
2587
merge_group_mask |= ( 1 << merge_group_n) ;
2588
}
2589
2590
2591
2592
column-> DrawChannelCurrent = ( ImGuiTableDrawChannelIdx) - 1 ;
2593
}
2594
2595
2596
#if 0
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
#endif
2612
2613
2614
if ( merge_group_mask != 0 )
2615
{
2616
2617
const int LEADING_DRAW_CHANNELS = 2 ;
2618
g. DrawChannelsTempMergeBuffer . resize ( splitter-> _Count - LEADING_DRAW_CHANNELS ) ;
2619
ImDrawChannel* dst_tmp = g. DrawChannelsTempMergeBuffer . Data ;
2620
ImBitArraySetBitRange ( remaining_mask, LEADING_DRAW_CHANNELS, splitter-> _Count ) ;
2621
ImBitArrayClearBit ( remaining_mask, table-> Bg2DrawChannelUnfrozen ) ;
2622
IM_ASSERT ( has_freeze_v == false || table-> Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN ) ;
2623
int remaining_count = splitter-> _Count - ( has_freeze_v ? LEADING_DRAW_CHANNELS + 1 : LEADING_DRAW_CHANNELS) ;
2624
2625
ImRect host_rect = table-> HostClipRect ;
2626
for ( int merge_group_n = 0 ; merge_group_n < IM_ARRAYSIZE ( merge_groups ) ; merge_group_n+ + )
2627
{
2628
if ( int merge_channels_count = merge_groups[ merge_group_n] . ChannelsCount )
2629
{
2630
MergeGroup* merge_group = & merge_groups[ merge_group_n] ;
2631
ImRect merge_clip_rect = merge_group-> ClipRect ;
2632
2633
2634
2635
2636
2637
2638
2639
2640
if ( ( merge_group_n & 1 ) == 0 || ! has_freeze_h)
2641
merge_clip_rect. Min . x = ImMin ( merge_clip_rect. Min . x , host_rect. Min . x ) ;
2642
if ( ( merge_group_n & 2 ) == 0 || ! has_freeze_v)
2643
merge_clip_rect. Min . y = ImMin ( merge_clip_rect. Min . y , host_rect. Min . y ) ;
2644
if ( ( merge_group_n & 1 ) != 0 )
2645
merge_clip_rect. Max . x = ImMax ( merge_clip_rect. Max . x , host_rect. Max . x ) ;
2646
if ( ( merge_group_n & 2 ) != 0 && ( table-> Flags & ImGuiTableFlags_NoHostExtendY) == 0 )
2647
merge_clip_rect. Max . y = ImMax ( merge_clip_rect. Max . y , host_rect. Max . y ) ;
2648
2649
2650
2651
remaining_count -= merge_group-> ChannelsCount ;
2652
for ( int n = 0 ; n < ( size_for_masks_bitarrays_one >> 2 ) ; n+ + )
2653
remaining_mask[ n] &= ~ merge_group-> ChannelsMask [ n] ;
2654
for ( int n = 0 ; n < splitter-> _Count && merge_channels_count != 0 ; n+ + )
2655
{
2656
2657
if ( ! IM_BITARRAY_TESTBIT ( merge_group-> ChannelsMask , n ) )
2658
continue ;
2659
IM_BITARRAY_CLEARBIT ( merge_group-> ChannelsMask , n ) ;
2660
merge_channels_count- - ;
2661
2662
ImDrawChannel* channel = & splitter-> _Channels [ n] ;
2663
IM_ASSERT ( channel-> _CmdBuffer . Size == 1 && merge_clip_rect. Contains ( ImRect ( channel-> _CmdBuffer [ 0 ] . ClipRect ) ) ) ;
2664
channel-> _CmdBuffer [ 0 ] . ClipRect = merge_clip_rect. ToVec4 ( ) ;
2665
memcpy ( dst_tmp+ + , channel, sizeof ( ImDrawChannel ) ) ;
2666
}
2667
}
2668
2669
2670
if ( merge_group_n == 1 && has_freeze_v)
2671
memcpy ( dst_tmp+ + , & splitter-> _Channels [ table-> Bg2DrawChannelUnfrozen ] , sizeof ( ImDrawChannel ) ) ;
2672
}
2673
2674
2675
for ( int n = 0 ; n < splitter-> _Count && remaining_count != 0 ; n+ + )
2676
{
2677
if ( ! IM_BITARRAY_TESTBIT ( remaining_mask, n ) )
2678
continue ;
2679
ImDrawChannel* channel = & splitter-> _Channels [ n] ;
2680
memcpy ( dst_tmp+ + , channel, sizeof ( ImDrawChannel ) ) ;
2681
remaining_count- - ;
2682
}
2683
IM_ASSERT ( dst_tmp == g. DrawChannelsTempMergeBuffer . Data + g. DrawChannelsTempMergeBuffer . Size ) ;
2684
memcpy ( splitter-> _Channels . Data + LEADING_DRAW_CHANNELS, g. DrawChannelsTempMergeBuffer . Data , ( splitter-> _Count - LEADING_DRAW_CHANNELS) * sizeof ( ImDrawChannel ) ) ;
2685
}
2686
}
2687
2688
static ImU32 TableGetColumnBorderCol ( ImGuiTable* table , int order_n , int column_n )
2689
{
2690
const bool is_hovered = ( table-> HoveredColumnBorder == column_n) ;
2691
const bool is_resized = ( table-> ResizedColumn == column_n) && ( table-> InstanceInteracted == table-> InstanceCurrent ) ;
2692
const bool is_frozen_separator = ( table-> FreezeColumnsCount == order_n + 1 ) ;
2693
if ( is_resized || is_hovered)
2694
return ImGui:: GetColorU32 ( is_resized ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered ) ;
2695
if ( is_frozen_separator || ( table-> Flags & ( ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize) ) )
2696
return table-> BorderColorStrong ;
2697
return table-> BorderColorLight ;
2698
}
2699
2700
2701
void ImGui:: TableDrawBorders ( ImGuiTable* table )
2702
{
2703
ImGuiWindow* inner_window = table-> InnerWindow ;
2704
if ( ! table-> OuterWindow -> ClipRect . Overlaps ( table-> OuterRect ) )
2705
return ;
2706
2707
ImDrawList* inner_drawlist = inner_window-> DrawList ;
2708
table-> DrawSplitter -> SetCurrentChannel ( inner_drawlist, TABLE_DRAW_CHANNEL_BG0 ) ;
2709
inner_drawlist-> PushClipRect ( table-> Bg0ClipRectForDrawCmd . Min , table-> Bg0ClipRectForDrawCmd . Max , false ) ;
2710
2711
2712
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, table-> InstanceCurrent ) ;
2713
const float border_size = TABLE_BORDER_SIZE;
2714
const float draw_y1 = ImMax ( table-> InnerRect . Min . y , ( table-> FreezeRowsCount >= 1 ? table-> InnerRect . Min . y : table-> WorkRect . Min . y ) + table-> AngledHeadersHeight ) + ( ( table-> Flags & ImGuiTableFlags_BordersOuterH) ? 1.0f : 0.0f ) ;
2715
const float draw_y2_body = table-> InnerRect . Max . y ;
2716
const float draw_y2_head = table-> IsUsingHeaders ? ImMin ( table-> InnerRect . Max . y , ( table-> FreezeRowsCount >= 1 ? table-> InnerRect . Min . y : table-> WorkRect . Min . y ) + table_instance-> LastTopHeadersRowHeight ) : draw_y1;
2717
if ( table-> Flags & ImGuiTableFlags_BordersInnerV)
2718
{
2719
for ( int order_n = 0 ; order_n < table-> ColumnsCount ; order_n+ + )
2720
{
2721
if ( ! IM_BITARRAY_TESTBIT ( table-> EnabledMaskByDisplayOrder , order_n ) )
2722
continue ;
2723
2724
const int column_n = table-> DisplayOrderToIndex [ order_n] ;
2725
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2726
const bool is_hovered = ( table-> HoveredColumnBorder == column_n) ;
2727
const bool is_resized = ( table-> ResizedColumn == column_n) && ( table-> InstanceInteracted == table-> InstanceCurrent ) ;
2728
const bool is_resizable = ( column-> Flags & ( ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_) ) == 0 ;
2729
const bool is_frozen_separator = ( table-> FreezeColumnsCount == order_n + 1 ) ;
2730
if ( column-> MaxX > table-> InnerClipRect . Max . x && ! is_resized)
2731
continue ;
2732
2733
2734
if ( column-> NextEnabledColumn == - 1 && ! is_resizable)
2735
if ( ( table-> Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame || ( table-> Flags & ImGuiTableFlags_NoHostExtendX) )
2736
continue ;
2737
if ( column-> MaxX <= column-> ClipRect . Min . x )
2738
continue ;
2739
2740
2741
2742
float draw_y2 = ( is_hovered || is_resized || is_frozen_separator || ( table-> Flags & ( ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize) ) == 0 ) ? draw_y2_body : draw_y2_head;
2743
if ( draw_y2 > draw_y1)
2744
inner_drawlist-> AddLine ( ImVec2 ( column-> MaxX , draw_y1 ) , ImVec2 ( column-> MaxX , draw_y2 ) , TableGetColumnBorderCol ( table, order_n, column_n ) , border_size) ;
2745
}
2746
}
2747
2748
2749
2750
if ( table-> Flags & ImGuiTableFlags_BordersOuter)
2751
{
2752
2753
2754
2755
2756
2757
const ImRect outer_border = table-> OuterRect ;
2758
const ImU32 outer_col = table-> BorderColorStrong ;
2759
if ( ( table-> Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
2760
{
2761
inner_drawlist-> AddRect ( outer_border. Min , outer_border. Max , outer_col, 0.0f , 0 , border_size ) ;
2762
}
2763
else if ( table-> Flags & ImGuiTableFlags_BordersOuterV)
2764
{
2765
inner_drawlist-> AddLine ( outer_border. Min , ImVec2 ( outer_border. Min . x , outer_border. Max . y ) , outer_col, border_size ) ;
2766
inner_drawlist-> AddLine ( ImVec2 ( outer_border. Max . x , outer_border. Min . y ) , outer_border. Max , outer_col, border_size) ;
2767
}
2768
else if ( table-> Flags & ImGuiTableFlags_BordersOuterH)
2769
{
2770
inner_drawlist-> AddLine ( outer_border. Min , ImVec2 ( outer_border. Max . x , outer_border. Min . y ) , outer_col, border_size ) ;
2771
inner_drawlist-> AddLine ( ImVec2 ( outer_border. Min . x , outer_border. Max . y ) , outer_border. Max , outer_col, border_size) ;
2772
}
2773
}
2774
if ( ( table-> Flags & ImGuiTableFlags_BordersInnerH) && table-> RowPosY2 < table-> OuterRect . Max . y )
2775
{
2776
2777
const float border_y = table-> RowPosY2 ;
2778
if ( border_y >= table-> BgClipRect . Min . y && border_y < table-> BgClipRect . Max . y )
2779
inner_drawlist-> AddLine ( ImVec2 ( table-> BorderX1 , border_y ) , ImVec2 ( table-> BorderX2 , border_y ) , table-> BorderColorLight , border_size) ;
2780
}
2781
2782
inner_drawlist-> PopClipRect ( ) ;
2783
}
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
ImGuiTableSortSpecs* ImGui:: TableGetSortSpecs ( )
2802
{
2803
ImGuiContext& g = * GImGui;
2804
ImGuiTable* table = g. CurrentTable ;
2805
IM_ASSERT ( table != NULL ) ;
2806
2807
if ( ! ( table-> Flags & ImGuiTableFlags_Sortable) )
2808
return NULL ;
2809
2810
2811
if ( ! table-> IsLayoutLocked )
2812
TableUpdateLayout ( table ) ;
2813
2814
TableSortSpecsBuild ( table ) ;
2815
return & table-> SortSpecs ;
2816
}
2817
2818
static inline ImGuiSortDirection TableGetColumnAvailSortDirection ( ImGuiTableColumn* column , int n )
2819
{
2820
IM_ASSERT ( n < column-> SortDirectionsAvailCount ) ;
2821
return ( ImGuiSortDirection) ( ( column-> SortDirectionsAvailList >> ( n << 1 ) ) & 0x03 ) ;
2822
}
2823
2824
2825
void ImGui:: TableFixColumnSortDirection ( ImGuiTable* table , ImGuiTableColumn* column )
2826
{
2827
if ( column-> SortOrder == - 1 || ( column-> SortDirectionsAvailMask & ( 1 << column-> SortDirection ) ) != 0 )
2828
return ;
2829
column-> SortDirection = ( ImU8) TableGetColumnAvailSortDirection ( column, 0 ) ;
2830
table-> IsSortSpecsDirty = true ;
2831
}
2832
2833
2834
2835
2836
IM_STATIC_ASSERT ( ImGuiSortDirection_None == 0 && ImGuiSortDirection_Ascending == 1 && ImGuiSortDirection_Descending == 2 ) ;
2837
ImGuiSortDirection ImGui:: TableGetColumnNextSortDirection ( ImGuiTableColumn* column )
2838
{
2839
IM_ASSERT ( column-> SortDirectionsAvailCount > 0 ) ;
2840
if ( column-> SortOrder == - 1 )
2841
return TableGetColumnAvailSortDirection ( column, 0 ) ;
2842
for ( int n = 0 ; n < 3 ; n+ + )
2843
if ( column-> SortDirection == TableGetColumnAvailSortDirection ( column, n ) )
2844
return TableGetColumnAvailSortDirection ( column, ( n + 1 ) % column-> SortDirectionsAvailCount ) ;
2845
IM_ASSERT ( 0 ) ;
2846
return ImGuiSortDirection_None;
2847
}
2848
2849
2850
2851
void ImGui:: TableSetColumnSortDirection ( int column_n , ImGuiSortDirection sort_direction , bool append_to_sort_specs )
2852
{
2853
ImGuiContext& g = * GImGui;
2854
ImGuiTable* table = g. CurrentTable ;
2855
2856
if ( ! ( table-> Flags & ImGuiTableFlags_SortMulti) )
2857
append_to_sort_specs = false ;
2858
if ( ! ( table-> Flags & ImGuiTableFlags_SortTristate) )
2859
IM_ASSERT ( sort_direction != ImGuiSortDirection_None ) ;
2860
2861
ImGuiTableColumnIdx sort_order_max = 0 ;
2862
if ( append_to_sort_specs)
2863
for ( int other_column_n = 0 ; other_column_n < table-> ColumnsCount ; other_column_n+ + )
2864
sort_order_max = ImMax ( sort_order_max, table-> Columns [ other_column_n] . SortOrder ) ;
2865
2866
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2867
column-> SortDirection = ( ImU8) sort_direction;
2868
if ( column-> SortDirection == ImGuiSortDirection_None)
2869
column-> SortOrder = - 1 ;
2870
else if ( column-> SortOrder == - 1 || ! append_to_sort_specs)
2871
column-> SortOrder = append_to_sort_specs ? sort_order_max + 1 : 0 ;
2872
2873
for ( int other_column_n = 0 ; other_column_n < table-> ColumnsCount ; other_column_n+ + )
2874
{
2875
ImGuiTableColumn* other_column = & table-> Columns [ other_column_n] ;
2876
if ( other_column != column && ! append_to_sort_specs)
2877
other_column-> SortOrder = - 1 ;
2878
TableFixColumnSortDirection ( table, other_column ) ;
2879
}
2880
table-> IsSettingsDirty = true ;
2881
table-> IsSortSpecsDirty = true ;
2882
}
2883
2884
void ImGui:: TableSortSpecsSanitize ( ImGuiTable* table )
2885
{
2886
IM_ASSERT ( table-> Flags & ImGuiTableFlags_Sortable ) ;
2887
2888
2889
int sort_order_count = 0 ;
2890
ImU64 sort_order_mask = 0x00 ;
2891
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2892
{
2893
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2894
if ( column-> SortOrder != - 1 && ! column-> IsEnabled )
2895
column-> SortOrder = - 1 ;
2896
if ( column-> SortOrder == - 1 )
2897
continue ;
2898
sort_order_count+ + ;
2899
sort_order_mask |= ( ( ImU64) 1 << column-> SortOrder ) ;
2900
IM_ASSERT ( sort_order_count < ( int ) sizeof ( sort_order_mask ) * 8 ) ;
2901
}
2902
2903
const bool need_fix_linearize = ( ( ImU64) 1 << sort_order_count) != ( sort_order_mask + 1 ) ;
2904
const bool need_fix_single_sort_order = ( sort_order_count > 1 ) && ! ( table-> Flags & ImGuiTableFlags_SortMulti) ;
2905
if ( need_fix_linearize || need_fix_single_sort_order)
2906
{
2907
ImU64 fixed_mask = 0x00 ;
2908
for ( int sort_n = 0 ; sort_n < sort_order_count; sort_n+ + )
2909
{
2910
2911
2912
int column_with_smallest_sort_order = - 1 ;
2913
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2914
if ( ( fixed_mask & ( ( ImU64) 1 << ( ImU64) column_n) ) == 0 && table-> Columns [ column_n] . SortOrder != - 1 )
2915
if ( column_with_smallest_sort_order == - 1 || table-> Columns [ column_n] . SortOrder < table-> Columns [ column_with_smallest_sort_order] . SortOrder )
2916
column_with_smallest_sort_order = column_n;
2917
IM_ASSERT ( column_with_smallest_sort_order != - 1 ) ;
2918
fixed_mask |= ( ( ImU64) 1 << column_with_smallest_sort_order) ;
2919
table-> Columns [ column_with_smallest_sort_order] . SortOrder = ( ImGuiTableColumnIdx) sort_n;
2920
2921
2922
if ( need_fix_single_sort_order)
2923
{
2924
sort_order_count = 1 ;
2925
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2926
if ( column_n != column_with_smallest_sort_order)
2927
table-> Columns [ column_n] . SortOrder = - 1 ;
2928
break ;
2929
}
2930
}
2931
}
2932
2933
2934
if ( sort_order_count == 0 && ! ( table-> Flags & ImGuiTableFlags_SortTristate) )
2935
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2936
{
2937
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2938
if ( column-> IsEnabled && ! ( column-> Flags & ImGuiTableColumnFlags_NoSort) )
2939
{
2940
sort_order_count = 1 ;
2941
column-> SortOrder = 0 ;
2942
column-> SortDirection = ( ImU8) TableGetColumnAvailSortDirection ( column, 0 ) ;
2943
break ;
2944
}
2945
}
2946
2947
table-> SortSpecsCount = ( ImGuiTableColumnIdx) sort_order_count;
2948
}
2949
2950
void ImGui:: TableSortSpecsBuild ( ImGuiTable* table )
2951
{
2952
bool dirty = table-> IsSortSpecsDirty ;
2953
if ( dirty)
2954
{
2955
TableSortSpecsSanitize ( table ) ;
2956
table-> SortSpecsMulti . resize ( table-> SortSpecsCount <= 1 ? 0 : table-> SortSpecsCount ) ;
2957
table-> SortSpecs . SpecsDirty = true ;
2958
table-> IsSortSpecsDirty = false ;
2959
}
2960
2961
2962
2963
ImGuiTableColumnSortSpecs* sort_specs = ( table-> SortSpecsCount == 0 ) ? NULL : ( table-> SortSpecsCount == 1 ) ? & table-> SortSpecsSingle : table-> SortSpecsMulti . Data ;
2964
if ( dirty && sort_specs != NULL )
2965
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
2966
{
2967
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
2968
if ( column-> SortOrder == - 1 )
2969
continue ;
2970
IM_ASSERT ( column-> SortOrder < table-> SortSpecsCount ) ;
2971
ImGuiTableColumnSortSpecs* sort_spec = & sort_specs[ column-> SortOrder ] ;
2972
sort_spec-> ColumnUserID = column-> UserID ;
2973
sort_spec-> ColumnIndex = ( ImGuiTableColumnIdx) column_n;
2974
sort_spec-> SortOrder = ( ImGuiTableColumnIdx) column-> SortOrder ;
2975
sort_spec-> SortDirection = ( ImGuiSortDirection) column-> SortDirection ;
2976
}
2977
2978
table-> SortSpecs . Specs = sort_specs;
2979
table-> SortSpecs . SpecsCount = table-> SortSpecsCount ;
2980
}
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
float ImGui:: TableGetHeaderRowHeight ( )
2994
{
2995
2996
2997
2998
2999
ImGuiContext& g = * GImGui;
3000
ImGuiTable* table = g. CurrentTable ;
3001
float row_height = g. FontSize ;
3002
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
3003
if ( IM_BITARRAY_TESTBIT ( table-> EnabledMaskByIndex , column_n ) )
3004
if ( ( table-> Columns [ column_n] . Flags & ImGuiTableColumnFlags_NoHeaderLabel) == 0 )
3005
row_height = ImMax ( row_height, CalcTextSize ( TableGetColumnName ( table, column_n ) ) . y ) ;
3006
return row_height + g. Style . CellPadding . y * 2.0f ;
3007
}
3008
3009
float ImGui:: TableGetHeaderAngledMaxLabelWidth ( )
3010
{
3011
ImGuiContext& g = * GImGui;
3012
ImGuiTable* table = g. CurrentTable ;
3013
float width = 0.0f ;
3014
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
3015
if ( IM_BITARRAY_TESTBIT ( table-> EnabledMaskByIndex , column_n ) )
3016
if ( table-> Columns [ column_n] . Flags & ImGuiTableColumnFlags_AngledHeader)
3017
width = ImMax ( width, CalcTextSize ( TableGetColumnName ( table, column_n ) , NULL , true ) . x ) ;
3018
return width + g. Style . CellPadding . y * 2.0f ;
3019
}
3020
3021
3022
3023
3024
3025
3026
3027
3028
void ImGui:: TableHeadersRow ( )
3029
{
3030
ImGuiContext& g = * GImGui;
3031
ImGuiTable* table = g. CurrentTable ;
3032
IM_ASSERT ( table != NULL && " Need to call TableHeadersRow() after BeginTable()!" ) ;
3033
3034
3035
3036
if ( ! table-> IsLayoutLocked )
3037
TableUpdateLayout ( table ) ;
3038
3039
3040
const float row_height = TableGetHeaderRowHeight ( ) ;
3041
TableNextRow ( ImGuiTableRowFlags_Headers, row_height ) ;
3042
const float row_y1 = GetCursorScreenPos ( ) . y ;
3043
if ( table-> HostSkipItems )
3044
return ;
3045
3046
const int columns_count = TableGetColumnCount ( ) ;
3047
for ( int column_n = 0 ; column_n < columns_count; column_n+ + )
3048
{
3049
if ( ! TableSetColumnIndex ( column_n ) )
3050
continue ;
3051
3052
3053
const char * name = ( TableGetColumnFlags ( column_n ) & ImGuiTableColumnFlags_NoHeaderLabel) ? " " : TableGetColumnName ( column_n ) ;
3054
PushID ( column_n ) ;
3055
TableHeader ( name ) ;
3056
PopID ( ) ;
3057
}
3058
3059
3060
ImVec2 mouse_pos = ImGui:: GetMousePos ( ) ;
3061
if ( IsMouseReleased ( 1 ) && TableGetHoveredColumn ( ) == columns_count)
3062
if ( mouse_pos. y >= row_y1 && mouse_pos. y < row_y1 + row_height)
3063
TableOpenContextMenu ( columns_count ) ;
3064
}
3065
3066
3067
3068
3069
void ImGui:: TableHeader ( const char * label )
3070
{
3071
ImGuiContext& g = * GImGui;
3072
ImGuiWindow* window = g. CurrentWindow ;
3073
if ( window-> SkipItems )
3074
return ;
3075
3076
ImGuiTable* table = g. CurrentTable ;
3077
IM_ASSERT ( table != NULL && " Need to call TableHeader() after BeginTable()!" ) ;
3078
IM_ASSERT ( table-> CurrentColumn != - 1 ) ;
3079
const int column_n = table-> CurrentColumn ;
3080
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
3081
3082
3083
if ( label == NULL )
3084
label = " " ;
3085
const char * label_end = FindRenderedTextEnd ( label ) ;
3086
ImVec2 label_size = CalcTextSize ( label, label_end, true ) ;
3087
ImVec2 label_pos = window-> DC . CursorPos ;
3088
3089
3090
3091
ImRect cell_r = TableGetCellBgRect ( table, column_n ) ;
3092
float label_height = ImMax ( label_size. y , table-> RowMinHeight - table-> RowCellPaddingY * 2.0f ) ;
3093
3094
3095
float w_arrow = 0.0f ;
3096
float w_sort_text = 0.0f ;
3097
bool sort_arrow = false ;
3098
char sort_order_suf[ 4 ] = " " ;
3099
const float ARROW_SCALE = 0.65f ;
3100
if ( ( table-> Flags & ImGuiTableFlags_Sortable) && ! ( column-> Flags & ImGuiTableColumnFlags_NoSort) )
3101
{
3102
w_arrow = ImTrunc ( g. FontSize * ARROW_SCALE + g. Style . FramePadding . x ) ;
3103
if ( column-> SortOrder != - 1 )
3104
sort_arrow = true ;
3105
if ( column-> SortOrder > 0 )
3106
{
3107
ImFormatString ( sort_order_suf, IM_ARRAYSIZE ( sort_order_suf ) , " %d " , column-> SortOrder + 1 ) ;
3108
w_sort_text = g. Style . ItemInnerSpacing . x + CalcTextSize ( sort_order_suf ) . x ;
3109
}
3110
}
3111
3112
3113
float max_pos_x = label_pos. x + label_size. x + w_sort_text + w_arrow;
3114
column-> ContentMaxXHeadersUsed = ImMax ( column-> ContentMaxXHeadersUsed , sort_arrow ? cell_r. Max . x : ImMin ( max_pos_x, cell_r. Max . x ) ) ;
3115
column-> ContentMaxXHeadersIdeal = ImMax ( column-> ContentMaxXHeadersIdeal , max_pos_x ) ;
3116
3117
3118
ImGuiID id = window-> GetID ( label ) ;
3119
ImRect bb ( cell_r. Min . x , cell_r. Min . y , cell_r. Max . x , ImMax ( cell_r. Max . y , cell_r. Min . y + label_height + g. Style . CellPadding . y * 2.0f ) ) ;
3120
ItemSize ( ImVec2 ( 0.0f , label_height) ) ;
3121
if ( ! ItemAdd ( bb, id ) )
3122
return ;
3123
3124
3125
3126
3127
3128
const bool highlight = ( table-> HighlightColumnHeader == column_n) ;
3129
bool hovered, held;
3130
bool pressed = ButtonBehavior ( bb, id, & hovered, & held, ImGuiButtonFlags_AllowOverlap ) ;
3131
if ( held || hovered || highlight)
3132
{
3133
const ImU32 col = GetColorU32 ( held ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header ) ;
3134
3135
TableSetBgColor ( ImGuiTableBgTarget_CellBg, col, table-> CurrentColumn ) ;
3136
}
3137
else
3138
{
3139
3140
if ( ( table-> RowFlags & ImGuiTableRowFlags_Headers) == 0 )
3141
TableSetBgColor ( ImGuiTableBgTarget_CellBg, GetColorU32 ( ImGuiCol_TableHeaderBg ) , table-> CurrentColumn ) ;
3142
}
3143
RenderNavCursor ( bb, id, ImGuiNavRenderCursorFlags_Compact | ImGuiNavRenderCursorFlags_NoRounding ) ;
3144
if ( held)
3145
table-> HeldHeaderColumn = ( ImGuiTableColumnIdx) column_n;
3146
window-> DC . CursorPos . y -= g. Style . ItemSpacing . y * 0.5f ;
3147
3148
3149
3150
if ( held && ( table-> Flags & ImGuiTableFlags_Reorderable) && IsMouseDragging ( 0 ) && ! g. DragDropActive )
3151
{
3152
3153
table-> ReorderColumn = ( ImGuiTableColumnIdx) column_n;
3154
table-> InstanceInteracted = table-> InstanceCurrent ;
3155
3156
3157
if ( g. IO . MouseDelta . x < 0.0f && g. IO . MousePos . x < cell_r. Min . x )
3158
if ( ImGuiTableColumn* prev_column = ( column-> PrevEnabledColumn != - 1 ) ? & table-> Columns [ column-> PrevEnabledColumn ] : NULL )
3159
if ( ! ( ( column-> Flags | prev_column-> Flags ) & ImGuiTableColumnFlags_NoReorder) )
3160
if ( ( column-> IndexWithinEnabledSet < table-> FreezeColumnsRequest ) == ( prev_column-> IndexWithinEnabledSet < table-> FreezeColumnsRequest ) )
3161
table-> ReorderColumnDir = - 1 ;
3162
if ( g. IO . MouseDelta . x > 0.0f && g. IO . MousePos . x > cell_r. Max . x )
3163
if ( ImGuiTableColumn* next_column = ( column-> NextEnabledColumn != - 1 ) ? & table-> Columns [ column-> NextEnabledColumn ] : NULL )
3164
if ( ! ( ( column-> Flags | next_column-> Flags ) & ImGuiTableColumnFlags_NoReorder) )
3165
if ( ( column-> IndexWithinEnabledSet < table-> FreezeColumnsRequest ) == ( next_column-> IndexWithinEnabledSet < table-> FreezeColumnsRequest ) )
3166
table-> ReorderColumnDir = + 1 ;
3167
}
3168
3169
3170
const float ellipsis_max = ImMax ( cell_r. Max . x - w_arrow - w_sort_text, label_pos. x ) ;
3171
if ( ( table-> Flags & ImGuiTableFlags_Sortable) && ! ( column-> Flags & ImGuiTableColumnFlags_NoSort) )
3172
{
3173
if ( column-> SortOrder != - 1 )
3174
{
3175
float x = ImMax ( cell_r. Min . x , cell_r. Max . x - w_arrow - w_sort_text ) ;
3176
float y = label_pos. y ;
3177
if ( column-> SortOrder > 0 )
3178
{
3179
PushStyleColor ( ImGuiCol_Text, GetColorU32 ( ImGuiCol_Text, 0.70f ) ) ;
3180
RenderText ( ImVec2 ( x + g. Style . ItemInnerSpacing . x , y ) , sort_order_suf) ;
3181
PopStyleColor ( ) ;
3182
x += w_sort_text;
3183
}
3184
RenderArrow ( window-> DrawList , ImVec2 ( x, y ) , GetColorU32 ( ImGuiCol_Text ) , column-> SortDirection == ImGuiSortDirection_Ascending ? ImGuiDir_Up : ImGuiDir_Down, ARROW_SCALE ) ;
3185
}
3186
3187
3188
if ( pressed && table-> ReorderColumn != column_n)
3189
{
3190
ImGuiSortDirection sort_direction = TableGetColumnNextSortDirection ( column ) ;
3191
TableSetColumnSortDirection ( column_n, sort_direction, g. IO . KeyShift ) ;
3192
}
3193
}
3194
3195
3196
3197
3198
RenderTextEllipsis ( window-> DrawList , label_pos, ImVec2 ( ellipsis_max, label_pos. y + label_height + g. Style . FramePadding . y ) , ellipsis_max, ellipsis_max, label, label_end, & label_size ) ;
3199
3200
const bool text_clipped = label_size. x > ( ellipsis_max - label_pos. x ) ;
3201
if ( text_clipped && hovered && g. ActiveId == 0 )
3202
SetItemTooltip ( " %.*s " , ( int ) ( label_end - label) , label) ;
3203
3204
3205
if ( IsMouseReleased ( 1 ) && IsItemHovered ( ) )
3206
TableOpenContextMenu ( column_n ) ;
3207
}
3208
3209
3210
3211
void ImGui:: TableAngledHeadersRow ( )
3212
{
3213
ImGuiContext& g = * GImGui;
3214
ImGuiTable* table = g. CurrentTable ;
3215
ImGuiTableTempData* temp_data = table-> TempData ;
3216
temp_data-> AngledHeadersRequests . resize ( 0 ) ;
3217
temp_data-> AngledHeadersRequests . reserve ( table-> ColumnsEnabledCount ) ;
3218
3219
3220
const ImGuiID row_id = GetID ( " ##AngledHeaders" ) ;
3221
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, table-> InstanceCurrent ) ;
3222
int highlight_column_n = table-> HighlightColumnHeader ;
3223
if ( highlight_column_n == - 1 && table-> HoveredColumnBody != - 1 )
3224
if ( table_instance-> HoveredRowLast == 0 && table-> HoveredColumnBorder == - 1 && ( g. ActiveId == 0 || g. ActiveId == row_id || ( table-> IsActiveIdInTable || g. DragDropActive ) ) )
3225
highlight_column_n = table-> HoveredColumnBody ;
3226
3227
3228
ImU32 col_header_bg = GetColorU32 ( ImGuiCol_TableHeaderBg ) ;
3229
ImU32 col_text = GetColorU32 ( ImGuiCol_Text ) ;
3230
for ( int order_n = 0 ; order_n < table-> ColumnsCount ; order_n+ + )
3231
if ( IM_BITARRAY_TESTBIT ( table-> EnabledMaskByDisplayOrder , order_n ) )
3232
{
3233
const int column_n = table-> DisplayOrderToIndex [ order_n] ;
3234
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
3235
if ( ( column-> Flags & ImGuiTableColumnFlags_AngledHeader) == 0 )
3236
continue ;
3237
ImGuiTableHeaderData request = { ( ImGuiTableColumnIdx) column_n, col_text, col_header_bg, ( column_n == highlight_column_n) ? GetColorU32 ( ImGuiCol_Header ) : 0 } ;
3238
temp_data-> AngledHeadersRequests . push_back ( request ) ;
3239
}
3240
3241
3242
TableAngledHeadersRowEx ( row_id, g. Style . TableAngledHeadersAngle , 0.0f , temp_data-> AngledHeadersRequests . Data , temp_data-> AngledHeadersRequests . Size ) ;
3243
}
3244
3245
3246
void ImGui:: TableAngledHeadersRowEx ( ImGuiID row_id , float angle , float max_label_width , const ImGuiTableHeaderData* data , int data_count )
3247
{
3248
ImGuiContext& g = * GImGui;
3249
ImGuiTable* table = g. CurrentTable ;
3250
ImGuiWindow* window = g. CurrentWindow ;
3251
ImDrawList* draw_list = window-> DrawList ;
3252
IM_ASSERT ( table != NULL && " Need to call TableHeadersRow() after BeginTable()!" ) ;
3253
IM_ASSERT ( table-> CurrentRow == - 1 && " Must be first row" ) ;
3254
3255
if ( max_label_width == 0.0f )
3256
max_label_width = TableGetHeaderAngledMaxLabelWidth ( ) ;
3257
3258
3259
const bool flip_label = ( angle < 0.0f ) ;
3260
angle -= IM_PI * 0.5f ;
3261
const float cos_a = ImCos ( angle ) ;
3262
const float sin_a = ImSin ( angle ) ;
3263
const float label_cos_a = flip_label ? ImCos ( angle + IM_PI ) : cos_a;
3264
const float label_sin_a = flip_label ? ImSin ( angle + IM_PI ) : sin_a;
3265
const ImVec2 unit_right = ImVec2 ( cos_a, sin_a ) ;
3266
3267
3268
3269
const float header_height = g. FontSize + g. Style . CellPadding . x * 2.0f ;
3270
const float row_height = ImTrunc ( ImFabs ( ImRotate ( ImVec2 ( max_label_width, flip_label ? + header_height : - header_height ) , cos_a, sin_a) . y ) ) ;
3271
table-> AngledHeadersHeight = row_height;
3272
table-> AngledHeadersSlope = ( sin_a != 0.0f ) ? ( cos_a / sin_a) : 0.0f ;
3273
const ImVec2 header_angled_vector = unit_right * ( row_height / - sin_a) ;
3274
3275
3276
TableNextRow ( ImGuiTableRowFlags_Headers, row_height ) ;
3277
TableNextColumn ( ) ;
3278
const ImRect row_r ( table-> WorkRect . Min . x , table-> BgClipRect . Min . y , table-> WorkRect . Max . x , table-> RowPosY2 ) ;
3279
table-> DrawSplitter -> SetCurrentChannel ( draw_list, TABLE_DRAW_CHANNEL_BG0 ) ;
3280
float clip_rect_min_x = table-> BgClipRect . Min . x ;
3281
if ( table-> FreezeColumnsCount > 0 )
3282
clip_rect_min_x = ImMax ( clip_rect_min_x, table-> Columns [ table-> FreezeColumnsCount - 1 ] . MaxX ) ;
3283
TableSetBgColor ( ImGuiTableBgTarget_RowBg0, 0 ) ;
3284
PushClipRect ( table-> BgClipRect . Min , table-> BgClipRect . Max , false ) ;
3285
draw_list-> AddRectFilled ( ImVec2 ( table-> BgClipRect . Min . x , row_r. Min . y ) , ImVec2 ( table-> BgClipRect . Max . x , row_r. Max . y ) , GetColorU32 ( ImGuiCol_TableHeaderBg, 0.25f ) ) ;
3286
PushClipRect ( ImVec2 ( clip_rect_min_x, table-> BgClipRect . Min . y ) , table-> BgClipRect . Max , true ) ;
3287
3288
ButtonBehavior ( row_r, row_id, NULL , NULL ) ;
3289
KeepAliveID ( row_id ) ;
3290
3291
const float ascent_scaled = g. Font -> Ascent * g. FontScale ;
3292
const float line_off_for_ascent_x = ( ImMax ( ( g. FontSize - ascent_scaled) * 0.5f , 0.0f ) / - sin_a) * ( flip_label ? - 1.0f : 1.0f ) ;
3293
const ImVec2 padding = g. Style . CellPadding ;
3294
const ImVec2 align = g. Style . TableAngledHeadersTextAlign ;
3295
3296
3297
float max_x = 0.0f ;
3298
for ( int pass = 0 ; pass < 2 ; pass+ + )
3299
for ( int order_n = 0 ; order_n < data_count; order_n+ + )
3300
{
3301
const ImGuiTableHeaderData* request = & data[ order_n] ;
3302
const int column_n = request-> Index ;
3303
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
3304
3305
ImVec2 bg_shape[ 4 ] ;
3306
bg_shape[ 0 ] = ImVec2 ( column-> MaxX , row_r. Max . y ) ;
3307
bg_shape[ 1 ] = ImVec2 ( column-> MinX , row_r. Max . y ) ;
3308
bg_shape[ 2 ] = bg_shape[ 1 ] + header_angled_vector;
3309
bg_shape[ 3 ] = bg_shape[ 0 ] + header_angled_vector;
3310
if ( pass == 0 )
3311
{
3312
3313
draw_list-> AddQuadFilled ( bg_shape[ 0 ] , bg_shape[ 1 ] , bg_shape[ 2 ] , bg_shape[ 3 ] , request-> BgColor0 ) ;
3314
draw_list-> AddQuadFilled ( bg_shape[ 0 ] , bg_shape[ 1 ] , bg_shape[ 2 ] , bg_shape[ 3 ] , request-> BgColor1 ) ;
3315
max_x = ImMax ( max_x, bg_shape[ 3 ] . x ) ;
3316
3317
3318
3319
3320
const char * label_name = TableGetColumnName ( table, column_n ) ;
3321
const char * label_name_end = FindRenderedTextEnd ( label_name ) ;
3322
const float line_off_step_x = ( g. FontSize / - sin_a) ;
3323
const int label_lines = ImTextCountLines ( label_name, label_name_end ) ;
3324
3325
3326
float line_off_curr_x = flip_label ? ( label_lines - 1 ) * line_off_step_x : 0.0f ;
3327
float line_off_for_align_x = ImMax ( ( ( ( column-> MaxX - column-> MinX ) - padding. x * 2.0f ) - ( label_lines * line_off_step_x) ) , 0.0f ) * align. x ;
3328
line_off_curr_x += line_off_for_align_x - line_off_for_ascent_x;
3329
3330
3331
column-> ContentMaxXHeadersUsed = column-> ContentMaxXHeadersIdeal = column-> WorkMinX + ImCeil ( label_lines * line_off_step_x - line_off_for_align_x ) ;
3332
3333
while ( label_name < label_name_end)
3334
{
3335
const char * label_name_eol = strchr ( label_name, ' \n ' ) ;
3336
if ( label_name_eol == NULL )
3337
label_name_eol = label_name_end;
3338
3339
3340
ImVec2 label_size = CalcTextSize ( label_name, label_name_eol ) ;
3341
float clip_width = max_label_width - padding. y ;
3342
float clip_height = ImMin ( label_size. y , column-> ClipRect . Max . x - column-> WorkMinX - line_off_curr_x ) ;
3343
ImRect clip_r ( window-> ClipRect . Min , window-> ClipRect . Min + ImVec2 ( clip_width, clip_height ) ) ;
3344
int vtx_idx_begin = draw_list-> _VtxCurrentIdx ;
3345
PushStyleColor ( ImGuiCol_Text, request-> TextColor ) ;
3346
RenderTextEllipsis ( draw_list, clip_r. Min , clip_r. Max , clip_r. Max . x , clip_r. Max . x , label_name, label_name_eol, & label_size ) ;
3347
PopStyleColor ( ) ;
3348
int vtx_idx_end = draw_list-> _VtxCurrentIdx ;
3349
3350
3351
const float available_space = ImMax ( clip_width - label_size. x + ImAbs ( padding. x * cos_a ) * 2.0f - ImAbs ( padding. y * sin_a ) * 2.0f , 0.0f ) ;
3352
const float vertical_offset = available_space * align. y * ( flip_label ? - 1.0f : 1.0f ) ;
3353
3354
3355
ImVec2 pivot_in = ImVec2 ( window-> ClipRect . Min . x - vertical_offset, window-> ClipRect . Min . y + label_size. y ) ;
3356
ImVec2 pivot_out = ImVec2 ( column-> WorkMinX , row_r. Max . y ) ;
3357
line_off_curr_x += flip_label ? - line_off_step_x : line_off_step_x;
3358
pivot_out += unit_right * padding. y ;
3359
if ( flip_label)
3360
pivot_out += unit_right * ( clip_width - ImMax ( 0.0f , clip_width - label_size. x ) ) ;
3361
pivot_out. x += flip_label ? line_off_curr_x + line_off_step_x : line_off_curr_x;
3362
ShadeVertsTransformPos ( draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out ) ;
3363
3364
3365
label_name = label_name_eol + 1 ;
3366
}
3367
}
3368
if ( pass == 1 )
3369
{
3370
3371
draw_list-> AddLine ( bg_shape[ 0 ] , bg_shape[ 3 ] , TableGetColumnBorderCol ( table, order_n, column_n ) ) ;
3372
}
3373
}
3374
PopClipRect ( ) ;
3375
PopClipRect ( ) ;
3376
table-> TempData -> AngledHeadersExtraWidth = ImMax ( 0.0f , max_x - table-> Columns [ table-> RightMostEnabledColumn ] . MaxX ) ;
3377
}
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
void ImGui:: TableOpenContextMenu ( int column_n )
3389
{
3390
ImGuiContext& g = * GImGui;
3391
ImGuiTable* table = g. CurrentTable ;
3392
if ( column_n == - 1 && table-> CurrentColumn != - 1 )
3393
column_n = table-> CurrentColumn ;
3394
if ( column_n == table-> ColumnsCount )
3395
column_n = - 1 ;
3396
IM_ASSERT ( column_n >= - 1 && column_n < table-> ColumnsCount ) ;
3397
if ( table-> Flags & ( ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable) )
3398
{
3399
table-> IsContextPopupOpen = true ;
3400
table-> ContextPopupColumn = ( ImGuiTableColumnIdx) column_n;
3401
table-> InstanceInteracted = table-> InstanceCurrent ;
3402
const ImGuiID context_menu_id = ImHashStr ( " ##ContextMenu" , 0 , table-> ID ) ;
3403
OpenPopupEx ( context_menu_id, ImGuiPopupFlags_None ) ;
3404
}
3405
}
3406
3407
bool ImGui:: TableBeginContextMenuPopup ( ImGuiTable* table )
3408
{
3409
if ( ! table-> IsContextPopupOpen || table-> InstanceCurrent != table-> InstanceInteracted )
3410
return false ;
3411
const ImGuiID context_menu_id = ImHashStr ( " ##ContextMenu" , 0 , table-> ID ) ;
3412
if ( BeginPopupEx ( context_menu_id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings ) )
3413
return true ;
3414
table-> IsContextPopupOpen = false ;
3415
return false ;
3416
}
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
void ImGui:: TableDrawDefaultContextMenu ( ImGuiTable* table , ImGuiTableFlags flags_for_section_to_display )
3427
{
3428
ImGuiContext& g = * GImGui;
3429
ImGuiWindow* window = g. CurrentWindow ;
3430
if ( window-> SkipItems )
3431
return ;
3432
3433
bool want_separator = false ;
3434
const int column_n = ( table-> ContextPopupColumn >= 0 && table-> ContextPopupColumn < table-> ColumnsCount ) ? table-> ContextPopupColumn : - 1 ;
3435
ImGuiTableColumn* column = ( column_n != - 1 ) ? & table-> Columns [ column_n] : NULL ;
3436
3437
3438
if ( flags_for_section_to_display & ImGuiTableFlags_Resizable)
3439
{
3440
if ( column != NULL )
3441
{
3442
const bool can_resize = ! ( column-> Flags & ImGuiTableColumnFlags_NoResize) && column-> IsEnabled ;
3443
if ( MenuItem ( LocalizeGetMsg ( ImGuiLocKey_TableSizeOne ) , NULL , false , can_resize) )
3444
TableSetColumnWidthAutoSingle ( table, column_n ) ;
3445
}
3446
3447
const char * size_all_desc;
3448
if ( table-> ColumnsEnabledFixedCount == table-> ColumnsEnabledCount && ( table-> Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame)
3449
size_all_desc = LocalizeGetMsg ( ImGuiLocKey_TableSizeAllFit ) ;
3450
else
3451
size_all_desc = LocalizeGetMsg ( ImGuiLocKey_TableSizeAllDefault ) ;
3452
if ( MenuItem ( size_all_desc, NULL ) )
3453
TableSetColumnWidthAutoAll ( table ) ;
3454
want_separator = true ;
3455
}
3456
3457
3458
if ( flags_for_section_to_display & ImGuiTableFlags_Reorderable)
3459
{
3460
if ( MenuItem ( LocalizeGetMsg ( ImGuiLocKey_TableResetOrder ) , NULL , false , ! table-> IsDefaultDisplayOrder ) )
3461
table-> IsResetDisplayOrderRequest = true ;
3462
want_separator = true ;
3463
}
3464
3465
3466
3467
3468
3469
3470
3471
#if 0
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
#endif
3485
3486
3487
if ( flags_for_section_to_display & ImGuiTableFlags_Hideable)
3488
{
3489
if ( want_separator)
3490
Separator ( ) ;
3491
want_separator = true ;
3492
3493
PushItemFlag ( ImGuiItemFlags_AutoClosePopups, false ) ;
3494
for ( int other_column_n = 0 ; other_column_n < table-> ColumnsCount ; other_column_n+ + )
3495
{
3496
ImGuiTableColumn* other_column = & table-> Columns [ other_column_n] ;
3497
if ( other_column-> Flags & ImGuiTableColumnFlags_Disabled)
3498
continue ;
3499
3500
const char * name = TableGetColumnName ( table, other_column_n ) ;
3501
if ( name == NULL || name[ 0 ] == 0 )
3502
name = " <Unknown>" ;
3503
3504
3505
bool menu_item_active = ( other_column-> Flags & ImGuiTableColumnFlags_NoHide) ? false : true ;
3506
if ( other_column-> IsUserEnabled && table-> ColumnsEnabledCount <= 1 )
3507
menu_item_active = false ;
3508
if ( MenuItem ( name, NULL , other_column-> IsUserEnabled , menu_item_active ) )
3509
other_column-> IsUserEnabledNextFrame = ! other_column-> IsUserEnabled ;
3510
}
3511
PopItemFlag ( ) ;
3512
}
3513
}
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
static void TableSettingsInit ( ImGuiTableSettings* settings , ImGuiID id , int columns_count , int columns_count_max )
3543
{
3544
IM_PLACEMENT_NEW ( settings ) ImGuiTableSettings ( ) ;
3545
ImGuiTableColumnSettings* settings_column = settings-> GetColumnSettings ( ) ;
3546
for ( int n = 0 ; n < columns_count_max; n+ + , settings_column+ + )
3547
IM_PLACEMENT_NEW ( settings_column ) ImGuiTableColumnSettings ( ) ;
3548
settings-> ID = id;
3549
settings-> ColumnsCount = ( ImGuiTableColumnIdx) columns_count;
3550
settings-> ColumnsCountMax = ( ImGuiTableColumnIdx) columns_count_max;
3551
settings-> WantApply = true ;
3552
}
3553
3554
static size_t TableSettingsCalcChunkSize ( int columns_count )
3555
{
3556
return sizeof ( ImGuiTableSettings ) + ( size_t ) columns_count * sizeof ( ImGuiTableColumnSettings ) ;
3557
}
3558
3559
ImGuiTableSettings* ImGui:: TableSettingsCreate ( ImGuiID id , int columns_count )
3560
{
3561
ImGuiContext& g = * GImGui;
3562
ImGuiTableSettings* settings = g. SettingsTables . alloc_chunk ( TableSettingsCalcChunkSize ( columns_count ) ) ;
3563
TableSettingsInit ( settings, id, columns_count, columns_count ) ;
3564
return settings;
3565
}
3566
3567
3568
ImGuiTableSettings* ImGui:: TableSettingsFindByID ( ImGuiID id )
3569
{
3570
3571
ImGuiContext& g = * GImGui;
3572
for ( ImGuiTableSettings* settings = g. SettingsTables . begin ( ) ; settings != NULL ; settings = g. SettingsTables . next_chunk ( settings ) )
3573
if ( settings-> ID == id)
3574
return settings;
3575
return NULL ;
3576
}
3577
3578
3579
ImGuiTableSettings* ImGui:: TableGetBoundSettings ( ImGuiTable* table )
3580
{
3581
if ( table-> SettingsOffset != - 1 )
3582
{
3583
ImGuiContext& g = * GImGui;
3584
ImGuiTableSettings* settings = g. SettingsTables . ptr_from_offset ( table-> SettingsOffset ) ;
3585
IM_ASSERT ( settings-> ID == table-> ID ) ;
3586
if ( settings-> ColumnsCountMax >= table-> ColumnsCount )
3587
return settings;
3588
settings-> ID = 0 ;
3589
}
3590
return NULL ;
3591
}
3592
3593
3594
void ImGui:: TableResetSettings ( ImGuiTable* table )
3595
{
3596
table-> IsInitializing = table-> IsSettingsDirty = true ;
3597
table-> IsResetAllRequest = false ;
3598
table-> IsSettingsRequestLoad = false ;
3599
table-> SettingsLoadedFlags = ImGuiTableFlags_None;
3600
}
3601
3602
void ImGui:: TableSaveSettings ( ImGuiTable* table )
3603
{
3604
table-> IsSettingsDirty = false ;
3605
if ( table-> Flags & ImGuiTableFlags_NoSavedSettings)
3606
return ;
3607
3608
3609
ImGuiContext& g = * GImGui;
3610
ImGuiTableSettings* settings = TableGetBoundSettings ( table ) ;
3611
if ( settings == NULL )
3612
{
3613
settings = TableSettingsCreate ( table-> ID , table-> ColumnsCount ) ;
3614
table-> SettingsOffset = g. SettingsTables . offset_from_ptr ( settings ) ;
3615
}
3616
settings-> ColumnsCount = ( ImGuiTableColumnIdx) table-> ColumnsCount ;
3617
3618
3619
IM_ASSERT ( settings-> ID == table-> ID ) ;
3620
IM_ASSERT ( settings-> ColumnsCount == table-> ColumnsCount && settings-> ColumnsCountMax >= settings-> ColumnsCount ) ;
3621
ImGuiTableColumn* column = table-> Columns . Data ;
3622
ImGuiTableColumnSettings* column_settings = settings-> GetColumnSettings ( ) ;
3623
3624
bool save_ref_scale = false ;
3625
settings-> SaveFlags = ImGuiTableFlags_None;
3626
for ( int n = 0 ; n < table-> ColumnsCount ; n+ + , column+ + , column_settings+ + )
3627
{
3628
const float width_or_weight = ( column-> Flags & ImGuiTableColumnFlags_WidthStretch) ? column-> StretchWeight : column-> WidthRequest ;
3629
column_settings-> WidthOrWeight = width_or_weight;
3630
column_settings-> Index = ( ImGuiTableColumnIdx) n;
3631
column_settings-> DisplayOrder = column-> DisplayOrder ;
3632
column_settings-> SortOrder = column-> SortOrder ;
3633
column_settings-> SortDirection = column-> SortDirection ;
3634
column_settings-> IsEnabled = column-> IsUserEnabled ;
3635
column_settings-> IsStretch = ( column-> Flags & ImGuiTableColumnFlags_WidthStretch) ? 1 : 0 ;
3636
if ( ( column-> Flags & ImGuiTableColumnFlags_WidthStretch) == 0 )
3637
save_ref_scale = true ;
3638
3639
3640
3641
3642
if ( width_or_weight != column-> InitStretchWeightOrWidth )
3643
settings-> SaveFlags |= ImGuiTableFlags_Resizable;
3644
if ( column-> DisplayOrder != n)
3645
settings-> SaveFlags |= ImGuiTableFlags_Reorderable;
3646
if ( column-> SortOrder != - 1 )
3647
settings-> SaveFlags |= ImGuiTableFlags_Sortable;
3648
if ( column-> IsUserEnabled != ( ( column-> Flags & ImGuiTableColumnFlags_DefaultHide) == 0 ) )
3649
settings-> SaveFlags |= ImGuiTableFlags_Hideable;
3650
}
3651
settings-> SaveFlags &= table-> Flags ;
3652
settings-> RefScale = save_ref_scale ? table-> RefScale : 0.0f ;
3653
3654
MarkIniSettingsDirty ( ) ;
3655
}
3656
3657
void ImGui:: TableLoadSettings ( ImGuiTable* table )
3658
{
3659
ImGuiContext& g = * GImGui;
3660
table-> IsSettingsRequestLoad = false ;
3661
if ( table-> Flags & ImGuiTableFlags_NoSavedSettings)
3662
return ;
3663
3664
3665
ImGuiTableSettings* settings;
3666
if ( table-> SettingsOffset == - 1 )
3667
{
3668
settings = TableSettingsFindByID ( table-> ID ) ;
3669
if ( settings == NULL )
3670
return ;
3671
if ( settings-> ColumnsCount != table-> ColumnsCount )
3672
table-> IsSettingsDirty = true ;
3673
table-> SettingsOffset = g. SettingsTables . offset_from_ptr ( settings ) ;
3674
}
3675
else
3676
{
3677
settings = TableGetBoundSettings ( table ) ;
3678
}
3679
3680
table-> SettingsLoadedFlags = settings-> SaveFlags ;
3681
table-> RefScale = settings-> RefScale ;
3682
3683
3684
ImGuiTableColumnSettings* column_settings = settings-> GetColumnSettings ( ) ;
3685
ImU64 display_order_mask = 0 ;
3686
for ( int data_n = 0 ; data_n < settings-> ColumnsCount ; data_n+ + , column_settings+ + )
3687
{
3688
int column_n = column_settings-> Index ;
3689
if ( column_n < 0 || column_n >= table-> ColumnsCount )
3690
continue ;
3691
3692
ImGuiTableColumn* column = & table-> Columns [ column_n] ;
3693
if ( settings-> SaveFlags & ImGuiTableFlags_Resizable)
3694
{
3695
if ( column_settings-> IsStretch )
3696
column-> StretchWeight = column_settings-> WidthOrWeight ;
3697
else
3698
column-> WidthRequest = column_settings-> WidthOrWeight ;
3699
column-> AutoFitQueue = 0x00 ;
3700
}
3701
if ( settings-> SaveFlags & ImGuiTableFlags_Reorderable)
3702
column-> DisplayOrder = column_settings-> DisplayOrder ;
3703
else
3704
column-> DisplayOrder = ( ImGuiTableColumnIdx) column_n;
3705
display_order_mask |= ( ImU64) 1 << column-> DisplayOrder ;
3706
column-> IsUserEnabled = column-> IsUserEnabledNextFrame = column_settings-> IsEnabled ;
3707
column-> SortOrder = column_settings-> SortOrder ;
3708
column-> SortDirection = column_settings-> SortDirection ;
3709
}
3710
3711
3712
const ImU64 expected_display_order_mask = ( settings-> ColumnsCount == 64 ) ? ~ 0 : ( ( ImU64) 1 << settings-> ColumnsCount ) - 1 ;
3713
if ( display_order_mask != expected_display_order_mask)
3714
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
3715
table-> Columns [ column_n] . DisplayOrder = ( ImGuiTableColumnIdx) column_n;
3716
3717
3718
for ( int column_n = 0 ; column_n < table-> ColumnsCount ; column_n+ + )
3719
table-> DisplayOrderToIndex [ table-> Columns [ column_n] . DisplayOrder ] = ( ImGuiTableColumnIdx) column_n;
3720
}
3721
3722
static void TableSettingsHandler_ClearAll ( ImGuiContext* ctx , ImGuiSettingsHandler* )
3723
{
3724
ImGuiContext& g = * ctx;
3725
for ( int i = 0 ; i != g. Tables . GetMapSize ( ) ; i+ + )
3726
if ( ImGuiTable* table = g. Tables . TryGetMapData ( i ) )
3727
table-> SettingsOffset = - 1 ;
3728
g. SettingsTables . clear ( ) ;
3729
}
3730
3731
3732
static void TableSettingsHandler_ApplyAll ( ImGuiContext* ctx , ImGuiSettingsHandler* )
3733
{
3734
ImGuiContext& g = * ctx;
3735
for ( int i = 0 ; i != g. Tables . GetMapSize ( ) ; i+ + )
3736
if ( ImGuiTable* table = g. Tables . TryGetMapData ( i ) )
3737
{
3738
table-> IsSettingsRequestLoad = true ;
3739
table-> SettingsOffset = - 1 ;
3740
}
3741
}
3742
3743
static void * TableSettingsHandler_ReadOpen ( ImGuiContext* , ImGuiSettingsHandler* , const char * name )
3744
{
3745
ImGuiID id = 0 ;
3746
int columns_count = 0 ;
3747
if ( sscanf ( name, " 0x%08X ,%d " , & id, & columns_count ) < 2 )
3748
return NULL ;
3749
3750
if ( ImGuiTableSettings* settings = ImGui:: TableSettingsFindByID ( id ) )
3751
{
3752
if ( settings-> ColumnsCountMax >= columns_count)
3753
{
3754
TableSettingsInit ( settings, id, columns_count, settings-> ColumnsCountMax ) ;
3755
return settings;
3756
}
3757
settings-> ID = 0 ;
3758
}
3759
return ImGui:: TableSettingsCreate ( id, columns_count ) ;
3760
}
3761
3762
static void TableSettingsHandler_ReadLine ( ImGuiContext* , ImGuiSettingsHandler* , void * entry , const char * line )
3763
{
3764
3765
ImGuiTableSettings* settings = ( ImGuiTableSettings* ) entry;
3766
float f = 0.0f ;
3767
int column_n = 0 , r = 0 , n = 0 ;
3768
3769
if ( sscanf ( line, " RefScale=%f " , & f ) == 1 ) { settings-> RefScale = f; return ; }
3770
3771
if ( sscanf ( line, " Column %d %n " , & column_n, & r ) == 1 )
3772
{
3773
if ( column_n < 0 || column_n >= settings-> ColumnsCount )
3774
return ;
3775
line = ImStrSkipBlank ( line + r ) ;
3776
char c = 0 ;
3777
ImGuiTableColumnSettings* column = settings-> GetColumnSettings ( ) + column_n;
3778
column-> Index = ( ImGuiTableColumnIdx) column_n;
3779
if ( sscanf ( line, " UserID=0x%08X %n " , ( ImU32* ) & n, & r ) == 1 ) { line = ImStrSkipBlank ( line + r ) ; column-> UserID = ( ImGuiID) n; }
3780
if ( sscanf ( line, " Width=%d %n " , & n, & r ) == 1 ) { line = ImStrSkipBlank ( line + r ) ; column-> WidthOrWeight = ( float ) n; column-> IsStretch = 0 ; settings-> SaveFlags |= ImGuiTableFlags_Resizable; }
3781
if ( sscanf ( line, " Weight=%f %n " , & f, & r ) == 1 ) { line = ImStrSkipBlank ( line + r ) ; column-> WidthOrWeight = f; column-> IsStretch = 1 ; settings-> SaveFlags |= ImGuiTableFlags_Resizable; }
3782
if ( sscanf ( line, " Visible=%d %n " , & n, & r ) == 1 ) { line = ImStrSkipBlank ( line + r ) ; column-> IsEnabled = ( ImU8) n; settings-> SaveFlags |= ImGuiTableFlags_Hideable; }
3783
if ( sscanf ( line, " Order=%d %n " , & n, & r ) == 1 ) { line = ImStrSkipBlank ( line + r ) ; column-> DisplayOrder = ( ImGuiTableColumnIdx) n; settings-> SaveFlags |= ImGuiTableFlags_Reorderable; }
3784
if ( sscanf ( line, " Sort=%d %c %n " , & n, & c, & r ) == 2 ) { line = ImStrSkipBlank ( line + r ) ; column-> SortOrder = ( ImGuiTableColumnIdx) n; column-> SortDirection = ( c == ' ^' ) ? ImGuiSortDirection_Descending : ImGuiSortDirection_Ascending; settings-> SaveFlags |= ImGuiTableFlags_Sortable; }
3785
}
3786
}
3787
3788
static void TableSettingsHandler_WriteAll ( ImGuiContext* ctx , ImGuiSettingsHandler* handler , ImGuiTextBuffer* buf )
3789
{
3790
ImGuiContext& g = * ctx;
3791
for ( ImGuiTableSettings* settings = g. SettingsTables . begin ( ) ; settings != NULL ; settings = g. SettingsTables . next_chunk ( settings ) )
3792
{
3793
if ( settings-> ID == 0 )
3794
continue ;
3795
3796
3797
3798
const bool save_size = ( settings-> SaveFlags & ImGuiTableFlags_Resizable) != 0 ;
3799
const bool save_visible = ( settings-> SaveFlags & ImGuiTableFlags_Hideable) != 0 ;
3800
const bool save_order = ( settings-> SaveFlags & ImGuiTableFlags_Reorderable) != 0 ;
3801
const bool save_sort = ( settings-> SaveFlags & ImGuiTableFlags_Sortable) != 0 ;
3802
if ( ! save_size && ! save_visible && ! save_order && ! save_sort)
3803
continue ;
3804
3805
buf-> reserve ( buf-> size ( ) + 30 + settings-> ColumnsCount * 50 ) ;
3806
buf-> appendf ( " [%s ][0x%08X ,%d ]\n " , handler-> TypeName , settings-> ID , settings-> ColumnsCount ) ;
3807
if ( settings-> RefScale != 0.0f )
3808
buf-> appendf ( " RefScale=%g \n " , settings-> RefScale ) ;
3809
ImGuiTableColumnSettings* column = settings-> GetColumnSettings ( ) ;
3810
for ( int column_n = 0 ; column_n < settings-> ColumnsCount ; column_n+ + , column+ + )
3811
{
3812
3813
bool save_column = column-> UserID != 0 || save_size || save_visible || save_order || ( save_sort && column-> SortOrder != - 1 ) ;
3814
if ( ! save_column)
3815
continue ;
3816
buf-> appendf ( " Column %-2d " , column_n) ;
3817
if ( column-> UserID != 0 ) { buf-> appendf ( " UserID=%08X " , column-> UserID ) ; }
3818
if ( save_size && column-> IsStretch ) { buf-> appendf ( " Weight=%.4f " , column-> WidthOrWeight ) ; }
3819
if ( save_size && ! column-> IsStretch ) { buf-> appendf ( " Width=%d " , ( int ) column-> WidthOrWeight ) ; }
3820
if ( save_visible) { buf-> appendf ( " Visible=%d " , column-> IsEnabled ) ; }
3821
if ( save_order) { buf-> appendf ( " Order=%d " , column-> DisplayOrder ) ; }
3822
if ( save_sort && column-> SortOrder != - 1 ) { buf-> appendf ( " Sort=%d %c " , column-> SortOrder , ( column-> SortDirection == ImGuiSortDirection_Ascending) ? ' v' : ' ^' ) ; }
3823
buf-> append ( " \n " ) ;
3824
}
3825
buf-> append ( " \n " ) ;
3826
}
3827
}
3828
3829
void ImGui:: TableSettingsAddSettingsHandler ( )
3830
{
3831
ImGuiSettingsHandler ini_handler;
3832
ini_handler. TypeName = " Table" ;
3833
ini_handler. TypeHash = ImHashStr ( " Table" ) ;
3834
ini_handler. ClearAllFn = TableSettingsHandler_ClearAll;
3835
ini_handler. ReadOpenFn = TableSettingsHandler_ReadOpen;
3836
ini_handler. ReadLineFn = TableSettingsHandler_ReadLine;
3837
ini_handler. ApplyAllFn = TableSettingsHandler_ApplyAll;
3838
ini_handler. WriteAllFn = TableSettingsHandler_WriteAll;
3839
AddSettingsHandler ( & ini_handler) ;
3840
}
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
void ImGui:: TableRemove ( ImGuiTable* table )
3852
{
3853
3854
ImGuiContext& g = * GImGui;
3855
int table_idx = g. Tables . GetIndex ( table ) ;
3856
3857
3858
g. Tables . Remove ( table-> ID , table ) ;
3859
g. TablesLastTimeActive [ table_idx] = - 1.0f ;
3860
}
3861
3862
3863
void ImGui:: TableGcCompactTransientBuffers ( ImGuiTable* table )
3864
{
3865
3866
ImGuiContext& g = * GImGui;
3867
IM_ASSERT ( table-> MemoryCompacted == false ) ;
3868
table-> SortSpecs . Specs = NULL ;
3869
table-> SortSpecsMulti . clear ( ) ;
3870
table-> IsSortSpecsDirty = true ;
3871
table-> ColumnsNames . clear ( ) ;
3872
table-> MemoryCompacted = true ;
3873
for ( int n = 0 ; n < table-> ColumnsCount ; n+ + )
3874
table-> Columns [ n] . NameOffset = - 1 ;
3875
g. TablesLastTimeActive [ g. Tables . GetIndex ( table ) ] = - 1.0f ;
3876
}
3877
3878
void ImGui:: TableGcCompactTransientBuffers ( ImGuiTableTempData* temp_data )
3879
{
3880
temp_data-> DrawSplitter . ClearFreeMemory ( ) ;
3881
temp_data-> LastTimeActive = - 1.0f ;
3882
}
3883
3884
3885
void ImGui:: TableGcCompactSettings ( )
3886
{
3887
ImGuiContext& g = * GImGui;
3888
int required_memory = 0 ;
3889
for ( ImGuiTableSettings* settings = g. SettingsTables . begin ( ) ; settings != NULL ; settings = g. SettingsTables . next_chunk ( settings ) )
3890
if ( settings-> ID != 0 )
3891
required_memory += ( int ) TableSettingsCalcChunkSize ( settings-> ColumnsCount ) ;
3892
if ( required_memory == g. SettingsTables . Buf . Size )
3893
return ;
3894
ImChunkStream< ImGuiTableSettings> new_chunk_stream;
3895
new_chunk_stream. Buf . reserve ( required_memory ) ;
3896
for ( ImGuiTableSettings* settings = g. SettingsTables . begin ( ) ; settings != NULL ; settings = g. SettingsTables . next_chunk ( settings ) )
3897
if ( settings-> ID != 0 )
3898
memcpy ( new_chunk_stream. alloc_chunk ( TableSettingsCalcChunkSize ( settings-> ColumnsCount ) ) , settings, TableSettingsCalcChunkSize ( settings-> ColumnsCount ) ) ;
3899
g. SettingsTables . swap ( new_chunk_stream ) ;
3900
}
3901
3902
3903
3904
3905
3906
3907
3908
3909
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
3910
3911
static const char * DebugNodeTableGetSizingPolicyDesc ( ImGuiTableFlags sizing_policy )
3912
{
3913
sizing_policy &= ImGuiTableFlags_SizingMask_;
3914
if ( sizing_policy == ImGuiTableFlags_SizingFixedFit) { return " FixedFit" ; }
3915
if ( sizing_policy == ImGuiTableFlags_SizingFixedSame) { return " FixedSame" ; }
3916
if ( sizing_policy == ImGuiTableFlags_SizingStretchProp) { return " StretchProp" ; }
3917
if ( sizing_policy == ImGuiTableFlags_SizingStretchSame) { return " StretchSame" ; }
3918
return " N/A" ;
3919
}
3920
3921
void ImGui:: DebugNodeTable ( ImGuiTable* table )
3922
{
3923
ImGuiContext& g = * GImGui;
3924
const bool is_active = ( table-> LastFrameActive >= g. FrameCount - 2 ) ;
3925
if ( ! is_active) { PushStyleColor ( ImGuiCol_Text, GetStyleColorVec4 ( ImGuiCol_TextDisabled ) ) ; }
3926
bool open = TreeNode ( table, " Table 0x%08X (%d columns, in '%s ')%s " , table-> ID , table-> ColumnsCount , table-> OuterWindow -> Name , is_active ? " " : " *Inactive*" ) ;
3927
if ( ! is_active) { PopStyleColor ( ) ; }
3928
if ( IsItemHovered ( ) )
3929
GetForegroundDrawList ( ) -> AddRect ( table-> OuterRect . Min , table-> OuterRect . Max , IM_COL32 ( 255 , 255 , 0 , 255 ) ) ;
3930
if ( IsItemVisible ( ) && table-> HoveredColumnBody != - 1 )
3931
GetForegroundDrawList ( ) -> AddRect ( GetItemRectMin ( ) , GetItemRectMax ( ) , IM_COL32 ( 255 , 255 , 0 , 255 ) ) ;
3932
if ( ! open)
3933
return ;
3934
if ( table-> InstanceCurrent > 0 )
3935
Text ( " ** %d instances of same table! Some data below will refer to last instance." , table-> InstanceCurrent + 1 ) ;
3936
if ( g. IO . ConfigDebugIsDebuggerPresent )
3937
{
3938
if ( DebugBreakButton ( " **DebugBreak**" , " in BeginTable()" ) )
3939
g. DebugBreakInTable = table-> ID ;
3940
SameLine ( ) ;
3941
}
3942
3943
bool clear_settings = SmallButton ( " Clear settings" ) ;
3944
BulletText ( " OuterRect: Pos: (%.1f ,%.1f ) Size: (%.1f ,%.1f ) Sizing: '%s '" , table-> OuterRect . Min . x , table-> OuterRect . Min . y , table-> OuterRect . GetWidth ( ) , table-> OuterRect . GetHeight ( ) , DebugNodeTableGetSizingPolicyDesc ( table-> Flags ) ) ;
3945
BulletText ( " ColumnsGivenWidth: %.1f , ColumnsAutoFitWidth: %.1f , InnerWidth: %.1f %s " , table-> ColumnsGivenWidth , table-> ColumnsAutoFitWidth , table-> InnerWidth , table-> InnerWidth == 0.0f ? " (auto)" : " " ) ;
3946
BulletText ( " CellPaddingX: %.1f , CellSpacingX: %.1f /%.1f , OuterPaddingX: %.1f " , table-> CellPaddingX , table-> CellSpacingX1 , table-> CellSpacingX2 , table-> OuterPaddingX ) ;
3947
BulletText ( " HoveredColumnBody: %d , HoveredColumnBorder: %d " , table-> HoveredColumnBody , table-> HoveredColumnBorder ) ;
3948
BulletText ( " ResizedColumn: %d , ReorderColumn: %d , HeldHeaderColumn: %d " , table-> ResizedColumn , table-> ReorderColumn , table-> HeldHeaderColumn ) ;
3949
for ( int n = 0 ; n < table-> InstanceCurrent + 1 ; n+ + )
3950
{
3951
ImGuiTableInstanceData* table_instance = TableGetInstanceData ( table, n ) ;
3952
BulletText ( " Instance %d : HoveredRow: %d , LastOuterHeight: %.2f " , n, table_instance-> HoveredRowLast , table_instance-> LastOuterHeight ) ;
3953
}
3954
3955
float sum_weights = 0.0f ;
3956
for ( int n = 0 ; n < table-> ColumnsCount ; n+ + )
3957
if ( table-> Columns [ n] . Flags & ImGuiTableColumnFlags_WidthStretch)
3958
sum_weights += table-> Columns [ n] . StretchWeight ;
3959
for ( int n = 0 ; n < table-> ColumnsCount ; n+ + )
3960
{
3961
ImGuiTableColumn* column = & table-> Columns [ n] ;
3962
const char * name = TableGetColumnName ( table, n ) ;
3963
char buf[ 512 ] ;
3964
ImFormatString ( buf, IM_ARRAYSIZE ( buf ) ,
3965
" Column %d order %d '%s ': offset %+.2f to %+.2f %s \n "
3966
" Enabled: %d , VisibleX/Y: %d /%d , RequestOutput: %d , SkipItems: %d , DrawChannels: %d ,%d \n "
3967
" WidthGiven: %.1f , Request/Auto: %.1f /%.1f , StretchWeight: %.3f (%.1f %% )\n "
3968
" MinX: %.1f , MaxX: %.1f (%+.1f ), ClipRect: %.1f to %.1f (+%.1f )\n "
3969
" ContentWidth: %.1f ,%.1f , HeadersUsed/Ideal %.1f /%.1f \n "
3970
" Sort: %d %s , UserID: 0x%08X , Flags: 0x%04X : %s %s %s .." ,
3971
n, column-> DisplayOrder , name, column-> MinX - table-> WorkRect . Min . x , column-> MaxX - table-> WorkRect . Min . x , ( n < table-> FreezeColumnsRequest ) ? " (Frozen)" : " " ,
3972
column-> IsEnabled , column-> IsVisibleX , column-> IsVisibleY , column-> IsRequestOutput , column-> IsSkipItems , column-> DrawChannelFrozen , column-> DrawChannelUnfrozen ,
3973
column-> WidthGiven , column-> WidthRequest , column-> WidthAuto , column-> StretchWeight , column-> StretchWeight > 0.0f ? ( column-> StretchWeight / sum_weights) * 100.0f : 0.0f ,
3974
column-> MinX , column-> MaxX , column-> MaxX - column-> MinX , column-> ClipRect . Min . x , column-> ClipRect . Max . x , column-> ClipRect . Max . x - column-> ClipRect . Min . x ,
3975
column-> ContentMaxXFrozen - column-> WorkMinX , column-> ContentMaxXUnfrozen - column-> WorkMinX , column-> ContentMaxXHeadersUsed - column-> WorkMinX , column-> ContentMaxXHeadersIdeal - column-> WorkMinX ,
3976
column-> SortOrder , ( column-> SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : ( column-> SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : " " , column-> UserID , column-> Flags ,
3977
( column-> Flags & ImGuiTableColumnFlags_WidthStretch) ? " WidthStretch " : " " ,
3978
( column-> Flags & ImGuiTableColumnFlags_WidthFixed) ? " WidthFixed " : " " ,
3979
( column-> Flags & ImGuiTableColumnFlags_NoResize) ? " NoResize " : " " ) ;
3980
Bullet ( ) ;
3981
Selectable ( buf ) ;
3982
if ( IsItemHovered ( ) )
3983
{
3984
ImRect r ( column-> MinX , table-> OuterRect . Min . y , column-> MaxX , table-> OuterRect . Max . y ) ;
3985
GetForegroundDrawList ( ) -> AddRect ( r. Min , r. Max , IM_COL32 ( 255 , 255 , 0 , 255 ) ) ;
3986
}
3987
}
3988
if ( ImGuiTableSettings* settings = TableGetBoundSettings ( table ) )
3989
DebugNodeTableSettings ( settings ) ;
3990
if ( clear_settings)
3991
table-> IsResetAllRequest = true ;
3992
TreePop ( ) ;
3993
}
3994
3995
void ImGui:: DebugNodeTableSettings ( ImGuiTableSettings* settings )
3996
{
3997
if ( ! TreeNode ( ( void * ) ( intptr_t ) settings-> ID , " Settings 0x%08X (%d columns)" , settings-> ID , settings-> ColumnsCount ) )
3998
return ;
3999
BulletText ( " SaveFlags: 0x%08X " , settings-> SaveFlags ) ;
4000
BulletText ( " ColumnsCount: %d (max %d )" , settings-> ColumnsCount , settings-> ColumnsCountMax ) ;
4001
for ( int n = 0 ; n < settings-> ColumnsCount ; n+ + )
4002
{
4003
ImGuiTableColumnSettings* column_settings = & settings-> GetColumnSettings ( ) [ n] ;
4004
ImGuiSortDirection sort_dir = ( column_settings-> SortOrder != - 1 ) ? ( ImGuiSortDirection) column_settings-> SortDirection : ImGuiSortDirection_None;
4005
BulletText ( " Column %d Order %d SortOrder %d %s Vis %d %s %7.3f UserID 0x%08X " ,
4006
n, column_settings-> DisplayOrder , column_settings-> SortOrder ,
4007
( sort_dir == ImGuiSortDirection_Ascending) ? " Asc" : ( sort_dir == ImGuiSortDirection_Descending) ? " Des" : " ---" ,
4008
column_settings-> IsEnabled , column_settings-> IsStretch ? " Weight" : " Width " , column_settings-> WidthOrWeight , column_settings-> UserID ) ;
4009
}
4010
TreePop ( ) ;
4011
}
4012
4013
#else
4014
4015
void ImGui:: DebugNodeTable ( ImGuiTable* ) { }
4016
void ImGui:: DebugNodeTableSettings ( ImGuiTableSettings* ) { }
4017
4018
#endif
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
void ImGui:: SetWindowClipRectBeforeSetChannel ( ImGuiWindow* window , const ImRect& clip_rect )
4050
{
4051
ImVec4 clip_rect_vec4 = clip_rect. ToVec4 ( ) ;
4052
window-> ClipRect = clip_rect;
4053
window-> DrawList -> _CmdHeader . ClipRect = clip_rect_vec4;
4054
window-> DrawList -> _ClipRectStack . Data [ window-> DrawList -> _ClipRectStack . Size - 1 ] = clip_rect_vec4;
4055
}
4056
4057
int ImGui:: GetColumnIndex ( )
4058
{
4059
ImGuiWindow* window = GetCurrentWindowRead ( ) ;
4060
return window-> DC . CurrentColumns ? window-> DC . CurrentColumns -> Current : 0 ;
4061
}
4062
4063
int ImGui:: GetColumnsCount ( )
4064
{
4065
ImGuiWindow* window = GetCurrentWindowRead ( ) ;
4066
return window-> DC . CurrentColumns ? window-> DC . CurrentColumns -> Count : 1 ;
4067
}
4068
4069
float ImGui:: GetColumnOffsetFromNorm ( const ImGuiOldColumns* columns , float offset_norm )
4070
{
4071
return offset_norm * ( columns-> OffMaxX - columns-> OffMinX ) ;
4072
}
4073
4074
float ImGui:: GetColumnNormFromOffset ( const ImGuiOldColumns* columns , float offset )
4075
{
4076
return offset / ( columns-> OffMaxX - columns-> OffMinX ) ;
4077
}
4078
4079
static const float COLUMNS_HIT_RECT_HALF_THICKNESS = 4.0f ;
4080
4081
static float GetDraggedColumnOffset ( ImGuiOldColumns* columns , int column_index )
4082
{
4083
4084
4085
ImGuiContext& g = * GImGui;
4086
ImGuiWindow* window = g. CurrentWindow ;
4087
IM_ASSERT ( column_index > 0 ) ;
4088
IM_ASSERT ( g. ActiveId == columns-> ID + ImGuiID ( column_index ) ) ;
4089
4090
float x = g. IO . MousePos . x - g. ActiveIdClickOffset . x + ImTrunc ( COLUMNS_HIT_RECT_HALF_THICKNESS * g. CurrentDpiScale ) - window-> Pos . x ;
4091
x = ImMax ( x, ImGui:: GetColumnOffset ( column_index - 1 ) + g. Style . ColumnsMinSpacing ) ;
4092
if ( ( columns-> Flags & ImGuiOldColumnFlags_NoPreserveWidths) )
4093
x = ImMin ( x, ImGui:: GetColumnOffset ( column_index + 1 ) - g. Style . ColumnsMinSpacing ) ;
4094
4095
return x;
4096
}
4097
4098
float ImGui:: GetColumnOffset ( int column_index )
4099
{
4100
ImGuiWindow* window = GetCurrentWindowRead ( ) ;
4101
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4102
if ( columns == NULL )
4103
return 0.0f ;
4104
4105
if ( column_index < 0 )
4106
column_index = columns-> Current ;
4107
IM_ASSERT ( column_index < columns-> Columns . Size ) ;
4108
4109
const float t = columns-> Columns [ column_index] . OffsetNorm ;
4110
const float x_offset = ImLerp ( columns-> OffMinX , columns-> OffMaxX , t ) ;
4111
return x_offset;
4112
}
4113
4114
static float GetColumnWidthEx ( ImGuiOldColumns* columns , int column_index , bool before_resize = false )
4115
{
4116
if ( column_index < 0 )
4117
column_index = columns-> Current ;
4118
4119
float offset_norm;
4120
if ( before_resize)
4121
offset_norm = columns-> Columns [ column_index + 1 ] . OffsetNormBeforeResize - columns-> Columns [ column_index] . OffsetNormBeforeResize ;
4122
else
4123
offset_norm = columns-> Columns [ column_index + 1 ] . OffsetNorm - columns-> Columns [ column_index] . OffsetNorm ;
4124
return ImGui:: GetColumnOffsetFromNorm ( columns, offset_norm ) ;
4125
}
4126
4127
float ImGui:: GetColumnWidth ( int column_index )
4128
{
4129
ImGuiContext& g = * GImGui;
4130
ImGuiWindow* window = g. CurrentWindow ;
4131
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4132
if ( columns == NULL )
4133
return GetContentRegionAvail ( ) . x ;
4134
4135
if ( column_index < 0 )
4136
column_index = columns-> Current ;
4137
return GetColumnOffsetFromNorm ( columns, columns-> Columns [ column_index + 1 ] . OffsetNorm - columns-> Columns [ column_index] . OffsetNorm ) ;
4138
}
4139
4140
void ImGui:: SetColumnOffset ( int column_index , float offset )
4141
{
4142
ImGuiContext& g = * GImGui;
4143
ImGuiWindow* window = g. CurrentWindow ;
4144
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4145
IM_ASSERT ( columns != NULL ) ;
4146
4147
if ( column_index < 0 )
4148
column_index = columns-> Current ;
4149
IM_ASSERT ( column_index < columns-> Columns . Size ) ;
4150
4151
const bool preserve_width = ! ( columns-> Flags & ImGuiOldColumnFlags_NoPreserveWidths) && ( column_index < columns-> Count - 1 ) ;
4152
const float width = preserve_width ? GetColumnWidthEx ( columns, column_index, columns-> IsBeingResized ) : 0.0f ;
4153
4154
if ( ! ( columns-> Flags & ImGuiOldColumnFlags_NoForceWithinWindow) )
4155
offset = ImMin ( offset, columns-> OffMaxX - g. Style . ColumnsMinSpacing * ( columns-> Count - column_index) ) ;
4156
columns-> Columns [ column_index] . OffsetNorm = GetColumnNormFromOffset ( columns, offset - columns-> OffMinX ) ;
4157
4158
if ( preserve_width)
4159
SetColumnOffset ( column_index + 1 , offset + ImMax ( g. Style . ColumnsMinSpacing , width ) ) ;
4160
}
4161
4162
void ImGui:: SetColumnWidth ( int column_index , float width )
4163
{
4164
ImGuiWindow* window = GetCurrentWindowRead ( ) ;
4165
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4166
IM_ASSERT ( columns != NULL ) ;
4167
4168
if ( column_index < 0 )
4169
column_index = columns-> Current ;
4170
SetColumnOffset ( column_index + 1 , GetColumnOffset ( column_index ) + width ) ;
4171
}
4172
4173
void ImGui:: PushColumnClipRect ( int column_index )
4174
{
4175
ImGuiWindow* window = GetCurrentWindowRead ( ) ;
4176
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4177
if ( column_index < 0 )
4178
column_index = columns-> Current ;
4179
4180
ImGuiOldColumnData* column = & columns-> Columns [ column_index] ;
4181
PushClipRect ( column-> ClipRect . Min , column-> ClipRect . Max , false ) ;
4182
}
4183
4184
4185
void ImGui:: PushColumnsBackground ( )
4186
{
4187
ImGuiWindow* window = GetCurrentWindowRead ( ) ;
4188
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4189
if ( columns-> Count == 1 )
4190
return ;
4191
4192
4193
columns-> HostBackupClipRect = window-> ClipRect ;
4194
SetWindowClipRectBeforeSetChannel ( window, columns-> HostInitialClipRect ) ;
4195
columns-> Splitter . SetCurrentChannel ( window-> DrawList , 0 ) ;
4196
}
4197
4198
void ImGui:: PopColumnsBackground ( )
4199
{
4200
ImGuiWindow* window = GetCurrentWindowRead ( ) ;
4201
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4202
if ( columns-> Count == 1 )
4203
return ;
4204
4205
4206
SetWindowClipRectBeforeSetChannel ( window, columns-> HostBackupClipRect ) ;
4207
columns-> Splitter . SetCurrentChannel ( window-> DrawList , columns-> Current + 1 ) ;
4208
}
4209
4210
ImGuiOldColumns* ImGui:: FindOrCreateColumns ( ImGuiWindow* window , ImGuiID id )
4211
{
4212
4213
for ( int n = 0 ; n < window-> ColumnsStorage . Size ; n+ + )
4214
if ( window-> ColumnsStorage [ n] . ID == id)
4215
return & window-> ColumnsStorage [ n] ;
4216
4217
window-> ColumnsStorage . push_back ( ImGuiOldColumns ( ) ) ;
4218
ImGuiOldColumns* columns = & window-> ColumnsStorage . back ( ) ;
4219
columns-> ID = id;
4220
return columns;
4221
}
4222
4223
ImGuiID ImGui:: GetColumnsID ( const char * str_id , int columns_count )
4224
{
4225
ImGuiWindow* window = GetCurrentWindow ( ) ;
4226
4227
4228
4229
PushID ( 0x11223347 + ( str_id ? 0 : columns_count) ) ;
4230
ImGuiID id = window-> GetID ( str_id ? str_id : " columns" ) ;
4231
PopID ( ) ;
4232
4233
return id;
4234
}
4235
4236
void ImGui:: BeginColumns ( const char * str_id , int columns_count , ImGuiOldColumnFlags flags )
4237
{
4238
ImGuiContext& g = * GImGui;
4239
ImGuiWindow* window = GetCurrentWindow ( ) ;
4240
4241
IM_ASSERT ( columns_count >= 1 ) ;
4242
IM_ASSERT ( window-> DC . CurrentColumns == NULL ) ;
4243
4244
4245
ImGuiID id = GetColumnsID ( str_id, columns_count ) ;
4246
ImGuiOldColumns* columns = FindOrCreateColumns ( window, id ) ;
4247
IM_ASSERT ( columns-> ID == id ) ;
4248
columns-> Current = 0 ;
4249
columns-> Count = columns_count;
4250
columns-> Flags = flags;
4251
window-> DC . CurrentColumns = columns;
4252
window-> DC . NavIsScrollPushableX = false ;
4253
4254
columns-> HostCursorPosY = window-> DC . CursorPos . y ;
4255
columns-> HostCursorMaxPosX = window-> DC . CursorMaxPos . x ;
4256
columns-> HostInitialClipRect = window-> ClipRect ;
4257
columns-> HostBackupParentWorkRect = window-> ParentWorkRect ;
4258
window-> ParentWorkRect = window-> WorkRect ;
4259
4260
4261
4262
const float column_padding = g. Style . ItemSpacing . x ;
4263
const float half_clip_extend_x = ImTrunc ( ImMax ( window-> WindowPadding . x * 0.5f , window-> WindowBorderSize ) ) ;
4264
const float max_1 = window-> WorkRect . Max . x + column_padding - ImMax ( column_padding - window-> WindowPadding . x , 0.0f ) ;
4265
const float max_2 = window-> WorkRect . Max . x + half_clip_extend_x;
4266
columns-> OffMinX = window-> DC . Indent . x - column_padding + ImMax ( column_padding - window-> WindowPadding . x , 0.0f ) ;
4267
columns-> OffMaxX = ImMax ( ImMin ( max_1, max_2 ) - window-> Pos . x , columns-> OffMinX + 1.0f ) ;
4268
columns-> LineMinY = columns-> LineMaxY = window-> DC . CursorPos . y ;
4269
4270
4271
if ( columns-> Columns . Size != 0 && columns-> Columns . Size != columns_count + 1 )
4272
columns-> Columns . resize ( 0 ) ;
4273
4274
4275
columns-> IsFirstFrame = ( columns-> Columns . Size == 0 ) ;
4276
if ( columns-> Columns . Size == 0 )
4277
{
4278
columns-> Columns . reserve ( columns_count + 1 ) ;
4279
for ( int n = 0 ; n < columns_count + 1 ; n+ + )
4280
{
4281
ImGuiOldColumnData column;
4282
column. OffsetNorm = n / ( float ) columns_count;
4283
columns-> Columns . push_back ( column ) ;
4284
}
4285
}
4286
4287
for ( int n = 0 ; n < columns_count; n+ + )
4288
{
4289
4290
ImGuiOldColumnData* column = & columns-> Columns [ n] ;
4291
float clip_x1 = IM_ROUND ( window-> Pos . x + GetColumnOffset ( n ) ) ;
4292
float clip_x2 = IM_ROUND ( window-> Pos . x + GetColumnOffset ( n + 1 ) - 1.0f ) ;
4293
column-> ClipRect = ImRect ( clip_x1, - FLT_MAX, clip_x2, + FLT_MAX ) ;
4294
column-> ClipRect . ClipWithFull ( window-> ClipRect ) ;
4295
}
4296
4297
if ( columns-> Count > 1 )
4298
{
4299
columns-> Splitter . Split ( window-> DrawList , 1 + columns-> Count ) ;
4300
columns-> Splitter . SetCurrentChannel ( window-> DrawList , 1 ) ;
4301
PushColumnClipRect ( 0 ) ;
4302
}
4303
4304
4305
float offset_0 = GetColumnOffset ( columns-> Current ) ;
4306
float offset_1 = GetColumnOffset ( columns-> Current + 1 ) ;
4307
float width = offset_1 - offset_0;
4308
PushItemWidth ( width * 0.65f ) ;
4309
window-> DC . ColumnsOffset . x = ImMax ( column_padding - window-> WindowPadding . x , 0.0f ) ;
4310
window-> DC . CursorPos . x = IM_TRUNC ( window-> Pos . x + window-> DC . Indent . x + window-> DC . ColumnsOffset . x ) ;
4311
window-> WorkRect . Max . x = window-> Pos . x + offset_1 - column_padding;
4312
window-> WorkRect . Max . y = window-> ContentRegionRect . Max . y ;
4313
}
4314
4315
void ImGui:: NextColumn ( )
4316
{
4317
ImGuiWindow* window = GetCurrentWindow ( ) ;
4318
if ( window-> SkipItems || window-> DC . CurrentColumns == NULL )
4319
return ;
4320
4321
ImGuiContext& g = * GImGui;
4322
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4323
4324
if ( columns-> Count == 1 )
4325
{
4326
window-> DC . CursorPos . x = IM_TRUNC ( window-> Pos . x + window-> DC . Indent . x + window-> DC . ColumnsOffset . x ) ;
4327
IM_ASSERT ( columns-> Current == 0 ) ;
4328
return ;
4329
}
4330
4331
4332
if ( + + columns-> Current == columns-> Count )
4333
columns-> Current = 0 ;
4334
4335
PopItemWidth ( ) ;
4336
4337
4338
4339
ImGuiOldColumnData* column = & columns-> Columns [ columns-> Current ] ;
4340
SetWindowClipRectBeforeSetChannel ( window, column-> ClipRect ) ;
4341
columns-> Splitter . SetCurrentChannel ( window-> DrawList , columns-> Current + 1 ) ;
4342
4343
const float column_padding = g. Style . ItemSpacing . x ;
4344
columns-> LineMaxY = ImMax ( columns-> LineMaxY , window-> DC . CursorPos . y ) ;
4345
if ( columns-> Current > 0 )
4346
{
4347
4348
4349
window-> DC . ColumnsOffset . x = GetColumnOffset ( columns-> Current ) - window-> DC . Indent . x + column_padding;
4350
}
4351
else
4352
{
4353
4354
window-> DC . ColumnsOffset . x = ImMax ( column_padding - window-> WindowPadding . x , 0.0f ) ;
4355
window-> DC . IsSameLine = false ;
4356
columns-> LineMinY = columns-> LineMaxY ;
4357
}
4358
window-> DC . CursorPos . x = IM_TRUNC ( window-> Pos . x + window-> DC . Indent . x + window-> DC . ColumnsOffset . x ) ;
4359
window-> DC . CursorPos . y = columns-> LineMinY ;
4360
window-> DC . CurrLineSize = ImVec2 ( 0.0f , 0.0f ) ;
4361
window-> DC . CurrLineTextBaseOffset = 0.0f ;
4362
4363
4364
float offset_0 = GetColumnOffset ( columns-> Current ) ;
4365
float offset_1 = GetColumnOffset ( columns-> Current + 1 ) ;
4366
float width = offset_1 - offset_0;
4367
PushItemWidth ( width * 0.65f ) ;
4368
window-> WorkRect . Max . x = window-> Pos . x + offset_1 - column_padding;
4369
}
4370
4371
void ImGui:: EndColumns ( )
4372
{
4373
ImGuiContext& g = * GImGui;
4374
ImGuiWindow* window = GetCurrentWindow ( ) ;
4375
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4376
IM_ASSERT ( columns != NULL ) ;
4377
4378
PopItemWidth ( ) ;
4379
if ( columns-> Count > 1 )
4380
{
4381
PopClipRect ( ) ;
4382
columns-> Splitter . Merge ( window-> DrawList ) ;
4383
}
4384
4385
const ImGuiOldColumnFlags flags = columns-> Flags ;
4386
columns-> LineMaxY = ImMax ( columns-> LineMaxY , window-> DC . CursorPos . y ) ;
4387
window-> DC . CursorPos . y = columns-> LineMaxY ;
4388
if ( ! ( flags & ImGuiOldColumnFlags_GrowParentContentsSize) )
4389
window-> DC . CursorMaxPos . x = columns-> HostCursorMaxPosX ;
4390
4391
4392
4393
bool is_being_resized = false ;
4394
if ( ! ( flags & ImGuiOldColumnFlags_NoBorder) && ! window-> SkipItems )
4395
{
4396
4397
const float y1 = ImMax ( columns-> HostCursorPosY , window-> ClipRect . Min . y ) ;
4398
const float y2 = ImMin ( window-> DC . CursorPos . y , window-> ClipRect . Max . y ) ;
4399
int dragging_column = - 1 ;
4400
for ( int n = 1 ; n < columns-> Count ; n+ + )
4401
{
4402
ImGuiOldColumnData* column = & columns-> Columns [ n] ;
4403
float x = window-> Pos . x + GetColumnOffset ( n ) ;
4404
const ImGuiID column_id = columns-> ID + ImGuiID ( n ) ;
4405
const float column_hit_hw = ImTrunc ( COLUMNS_HIT_RECT_HALF_THICKNESS * g. CurrentDpiScale ) ;
4406
const ImRect column_hit_rect ( ImVec2 ( x - column_hit_hw, y1 ) , ImVec2 ( x + column_hit_hw, y2 ) ) ;
4407
if ( ! ItemAdd ( column_hit_rect, column_id, NULL , ImGuiItemFlags_NoNav ) )
4408
continue ;
4409
4410
bool hovered = false , held = false ;
4411
if ( ! ( flags & ImGuiOldColumnFlags_NoResize) )
4412
{
4413
ButtonBehavior ( column_hit_rect, column_id, & hovered, & held ) ;
4414
if ( hovered || held)
4415
SetMouseCursor ( ImGuiMouseCursor_ResizeEW ) ;
4416
if ( held && ! ( column-> Flags & ImGuiOldColumnFlags_NoResize) )
4417
dragging_column = n;
4418
}
4419
4420
4421
const ImU32 col = GetColorU32 ( held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator ) ;
4422
const float xi = IM_TRUNC ( x ) ;
4423
window-> DrawList -> AddLine ( ImVec2 ( xi, y1 + 1.0f ) , ImVec2 ( xi, y2 ) , col) ;
4424
}
4425
4426
4427
if ( dragging_column != - 1 )
4428
{
4429
if ( ! columns-> IsBeingResized )
4430
for ( int n = 0 ; n < columns-> Count + 1 ; n+ + )
4431
columns-> Columns [ n] . OffsetNormBeforeResize = columns-> Columns [ n] . OffsetNorm ;
4432
columns-> IsBeingResized = is_being_resized = true ;
4433
float x = GetDraggedColumnOffset ( columns, dragging_column ) ;
4434
SetColumnOffset ( dragging_column, x ) ;
4435
}
4436
}
4437
columns-> IsBeingResized = is_being_resized;
4438
4439
window-> WorkRect = window-> ParentWorkRect ;
4440
window-> ParentWorkRect = columns-> HostBackupParentWorkRect ;
4441
window-> DC . CurrentColumns = NULL ;
4442
window-> DC . ColumnsOffset . x = 0.0f ;
4443
window-> DC . CursorPos . x = IM_TRUNC ( window-> Pos . x + window-> DC . Indent . x + window-> DC . ColumnsOffset . x ) ;
4444
NavUpdateCurrentWindowIsScrollPushableX ( ) ;
4445
}
4446
4447
void ImGui:: Columns ( int columns_count , const char * id , bool borders )
4448
{
4449
ImGuiWindow* window = GetCurrentWindow ( ) ;
4450
IM_ASSERT ( columns_count >= 1 ) ;
4451
4452
ImGuiOldColumnFlags flags = ( borders ? 0 : ImGuiOldColumnFlags_NoBorder) ;
4453
4454
ImGuiOldColumns* columns = window-> DC . CurrentColumns ;
4455
if ( columns != NULL && columns-> Count == columns_count && columns-> Flags == flags)
4456
return ;
4457
4458
if ( columns != NULL )
4459
EndColumns ( ) ;
4460
4461
if ( columns_count != 1 )
4462
BeginColumns ( id, columns_count, flags ) ;
4463
}
4464
4465
4466
4467
#endif