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