Skip to content

Commit e5969f6

Browse files
authored
implementation of ImGui Tables (#135)
1 parent f066d03 commit e5969f6

File tree

4 files changed

+446
-1
lines changed

4 files changed

+446
-1
lines changed

src/DearImGui.hs

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,37 @@ module DearImGui
183183
, colorPicker3
184184
, colorButton
185185

186+
-- ** Tables
187+
, beginTable
188+
, Raw.endTable
189+
, withTable
190+
, TableOptions(..)
191+
, defTableOptions
192+
, tableNextRow
193+
, tableNextRowWith
194+
, TableRowOptions(..)
195+
, defTableRowOptions
196+
, Raw.tableNextColumn
197+
, tableSetColumnIndex
198+
199+
, tableSetupColumn
200+
, TableColumnOptions(..)
201+
, defTableColumnOptions
202+
, tableSetupScrollFreeze
203+
, Raw.tableHeadersRow
204+
, Raw.tableHeader
205+
206+
, withSortableTable
207+
, TableSortingSpecs(..)
208+
209+
, tableGetColumnCount
210+
, tableGetColumnIndex
211+
, tableGetRowIndex
212+
, tableGetColumnName
213+
, tableGetColumnFlags
214+
, tableSetColumnEnabled
215+
, tableSetBgColor
216+
186217
-- ** Trees
187218
, treeNode
188219
, treePush
@@ -1274,6 +1305,203 @@ colorButton desc ref = liftIO do
12741305

12751306
return changed
12761307

1308+
data TableOptions = TableOptions
1309+
{ tableFlags :: ImGuiTableFlags
1310+
, outerSize :: ImVec2
1311+
, innerWidth :: Float
1312+
} deriving Show
1313+
1314+
defTableOptions :: TableOptions
1315+
defTableOptions = TableOptions (ImGuiTableFlags 0) (ImVec2 0 0) 0
1316+
1317+
-- | Wraps @ImGui::BeginTable()@.
1318+
beginTable :: MonadIO m => TableOptions -> String -> Int -> m Bool
1319+
beginTable (TableOptions flags outer inner) label columns = liftIO do
1320+
withCString label $ \l ->
1321+
with outer $ \o ->
1322+
Raw.beginTable l (fromIntegral columns) flags o (CFloat inner)
1323+
1324+
-- | Create a table.
1325+
--
1326+
-- The action will get 'False' if the entry is not visible.
1327+
--
1328+
-- ==== __Example usage:__
1329+
--
1330+
-- > withTable defTableOptions "MyTable" 2 $ \case
1331+
-- > False -> return ()
1332+
-- > True -> do
1333+
-- > tableSetupColumn "Hello"
1334+
-- > tableSetupColumn "World"
1335+
-- > tableHeadersRow
1336+
-- > forM_ [("a","1"),("b","2")] $\(a,b)
1337+
-- > tableNextRow
1338+
-- > whenM tableNextColumn (text a)
1339+
-- > whenM tableNextColumn (text b)
1340+
--
1341+
-- Displays:
1342+
--
1343+
-- @
1344+
-- | Hello | World |
1345+
-- +-------+-------+
1346+
-- | a | 1 |
1347+
-- | b | 2 |
1348+
-- @
1349+
--
1350+
withTable :: MonadUnliftIO m => TableOptions -> String -> Int -> (Bool -> m a) -> m a
1351+
withTable options label columns =
1352+
bracket (beginTable options label columns) (`when` Raw.endTable)
1353+
1354+
-- | Wraps @ImGui::TableNextRow()@ with 'defTableRowOptions'.
1355+
-- append into the first cell of a new row.
1356+
tableNextRow :: MonadIO m => m ()
1357+
tableNextRow = tableNextRowWith defTableRowOptions
1358+
1359+
data TableRowOptions = TableRowOptions
1360+
{ tableRowFlags :: ImGuiTableRowFlags
1361+
, minRowHeight :: Float
1362+
} deriving Show
1363+
1364+
defTableRowOptions :: TableRowOptions
1365+
defTableRowOptions = TableRowOptions (ImGuiTableRowFlags 0) 0
1366+
1367+
-- | Wraps @ImGui::TableNextRow()@ with explicit options.
1368+
tableNextRowWith :: MonadIO m => TableRowOptions -> m ()
1369+
tableNextRowWith (TableRowOptions flags minHeight) = liftIO do
1370+
Raw.tableNextRow flags (CFloat minHeight)
1371+
1372+
-- | Wraps @ImGui::TableSetColumnIndex()@.
1373+
-- append into the specified column. Return true when column is visible.
1374+
tableSetColumnIndex :: MonadIO m => Int -> m Bool
1375+
tableSetColumnIndex column = liftIO do
1376+
Raw.tableSetColumnIndex (fromIntegral column)
1377+
1378+
1379+
data TableColumnOptions = TableColumnOptions
1380+
{ tableColumnFlags :: ImGuiTableColumnFlags
1381+
, initWidthOrWeight :: Float
1382+
, userId :: ImGuiID
1383+
} deriving Show
1384+
1385+
defTableColumnOptions :: TableColumnOptions
1386+
defTableColumnOptions = TableColumnOptions (ImGuiTableColumnFlags 0) 0 0
1387+
1388+
-- | Wraps @ImGui::TableSetupColumn()@ using 'defTableColumnOptions'.
1389+
tableSetupColumn :: MonadIO m => String -> m ()
1390+
tableSetupColumn = tableSetupColumnWith defTableColumnOptions
1391+
1392+
-- | Wraps @ImGui::TableSetupColumn() with explicit options@.
1393+
tableSetupColumnWith :: MonadIO m => TableColumnOptions -> String -> m ()
1394+
tableSetupColumnWith (TableColumnOptions flags weight userId) label = liftIO do
1395+
withCString label $ \l ->
1396+
Raw.tableSetupColumn l flags (CFloat weight) userId
1397+
1398+
-- | Wraps @ImGui::TableSetupScrollFreeze()@.
1399+
-- lock columns/rows so they stay visible when scrolled.
1400+
tableSetupScrollFreeze :: MonadIO m => Int -> Int -> m ()
1401+
tableSetupScrollFreeze cols rows = liftIO do
1402+
Raw.tableSetupScrollFreeze (fromIntegral cols) (fromIntegral rows)
1403+
1404+
data TableSortingSpecs = TableSortingSpecs
1405+
{ tableSortingId :: ImGuiID -- ^ User id of the column (if specified by a TableSetupColumn() call)
1406+
, tableSortingColumn :: Int -- ^ Index of the column, starting at 0
1407+
, dableSortingOrder :: Int -- ^ Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here).
1408+
-- On 'ImGuiTableFlags_SortMulti' this is the order in which should be sorted.
1409+
, tableSortingDirection :: ImGuiSortDirection -- ^ 'ImGuiSortDirection_Ascending' or 'ImGuiSortDirection_Descending'. Should not be 'ImGuiSortDirection_None'
1410+
} deriving (Show, Eq)
1411+
1412+
-- | High-Level sorting. Returns of the underlying data should be sorted
1413+
-- and to what specification. Number of Specifications is mostly 0 or 1, but
1414+
-- can be more if 'ImGuiTableFlags_SortMulti' is enabled on the table.
1415+
--
1416+
-- The Bool only fires true for one frame on each sorting event and resets
1417+
-- automatically.
1418+
--
1419+
-- Must be called AFTER all columns are set up with 'tableSetupColumn'
1420+
--
1421+
-- Hint: Don't forget to set 'ImGuiTableFlags_Sortable' to enable sorting
1422+
-- on tables.
1423+
--
1424+
-- ==== __Example usage:__
1425+
--
1426+
-- > withTable defTableOptions "MyTable" 2 $ \case
1427+
-- > False -> return ()
1428+
-- > True -> do
1429+
-- > tableSetupColumn "Hello"
1430+
-- > tableSetupColumn "World"
1431+
-- > withSortableTable $ \(mustSort, sortSpecs) do
1432+
-- > when mustSort $
1433+
-- > -- ... do your sorting here & cache it. Dont sort every frame.
1434+
-- > tableHeadersRow
1435+
-- > forM_ [("a","1"),("b","2")] $\(a,b) -- use sorted data here.
1436+
-- > tableNextRow
1437+
-- > whenM tableNextColumn (text a)
1438+
-- > whenM tableNextColumn (text b)
1439+
withSortableTable :: MonadIO m => ((Bool,[TableSortingSpecs]) -> m a) -> m a
1440+
withSortableTable action = do
1441+
specsPtr <- liftIO $ Raw.tableGetSortSpecs
1442+
case specsPtr of
1443+
Nothing -> action (False, [])
1444+
Just ptr -> do
1445+
specs <- liftIO $ peek ptr
1446+
cSpecs <- liftIO $ peekArray (fromIntegral $ imGuiTableSortSpecsCount specs) (imGuiTableColumnSortSpecs specs)
1447+
1448+
-- just map singed 16-bit-int to something nice for the end-user
1449+
let cSpecs' = (\(ImGuiTableColumnSortSpecs a b c d) -> TableSortingSpecs a (fromIntegral b) (fromIntegral c) d) <$> cSpecs
1450+
1451+
result <- action (imGuiTableSortSpecsDirty specs /= 0, cSpecs')
1452+
-- set dirty to 0 after everything is done.
1453+
liftIO $ poke (ptr `plusPtr` (sizeOf (imGuiTableColumnSortSpecs specs)) `plusPtr` (sizeOf (imGuiTableSortSpecsCount specs))) (0 :: CInt)
1454+
return result
1455+
1456+
-- | Wraps @ImGui::TableGetColumnCount()@.
1457+
-- return number of columns (value passed to BeginTable)
1458+
tableGetColumnCount :: MonadIO m => m Int
1459+
tableGetColumnCount =
1460+
fromIntegral <$> Raw.tableGetColumnCount
1461+
1462+
-- | Wraps @ImGui::TableGetColumnIndex()@.
1463+
-- return current column index.
1464+
tableGetColumnIndex :: MonadIO m => m Int
1465+
tableGetColumnIndex =
1466+
fromIntegral <$> Raw.tableGetColumnIndex
1467+
1468+
-- | Wraps @ImGui::TableGetRowIndex()@.
1469+
-- return current row index
1470+
tableGetRowIndex :: MonadIO m => m Int
1471+
tableGetRowIndex =
1472+
fromIntegral <$> Raw.tableGetRowIndex
1473+
1474+
-- | Wraps @ImGui::TableGetColumnName
1475+
-- returns "" if column didn't have a name declared by TableSetupColumn
1476+
-- 'Nothing' returns the current column name
1477+
tableGetColumnName :: MonadIO m => Maybe Int -> m String
1478+
tableGetColumnName c = liftIO do
1479+
Raw.tableGetColumnName (fromIntegral <$> c) >>= peekCString
1480+
1481+
-- | Wraps @ImGui::TableGetRowIndex()@.
1482+
-- return column flags so you can query their Enabled/Visible/Sorted/Hovered
1483+
-- status flags.
1484+
-- 'Nothing' returns the current column flags
1485+
tableGetColumnFlags :: MonadIO m => Maybe Int -> m ImGuiTableColumnFlags
1486+
tableGetColumnFlags =
1487+
Raw.tableGetColumnFlags . fmap fromIntegral
1488+
1489+
-- | Wraps @ImGui::TableSetColumnEnabled()@.
1490+
-- change user accessible enabled/disabled state of a column. Set to false to
1491+
-- hide the column. User can use the context menu to change this themselves
1492+
-- (right-click in headers, or right-click in columns body with
1493+
-- 'ImGuiTableFlags_ContextMenuInBody')
1494+
tableSetColumnEnabled :: MonadIO m => Int -> Bool -> m ()
1495+
tableSetColumnEnabled column_n v =
1496+
Raw.tableSetColumnEnabled (fromIntegral column_n) (bool 0 1 v)
1497+
1498+
-- | Wraps @ImGui::TableSetBgColor()@.
1499+
-- change the color of a cell, row, or column.
1500+
-- See 'ImGuiTableBgTarget' flags for details.
1501+
-- 'Nothing' sets the current row/column color
1502+
tableSetBgColor :: MonadIO m => ImGuiTableBgTarget -> ImU32 -> Maybe Int -> m ()
1503+
tableSetBgColor target color column_n =
1504+
Raw.tableSetBgColor target color (fromIntegral <$> column_n)
12771505

12781506
-- | Wraps @ImGui::TreeNode()@.
12791507
treeNode :: MonadIO m => String -> m Bool

src/DearImGui/Context.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,14 @@ imguiContext = mempty
3434
, ( TypeName "ImVec3", [t| ImVec3 |] )
3535
, ( TypeName "ImVec4", [t| ImVec4 |] )
3636
, ( TypeName "ImU32", [t| ImU32 |] )
37+
, ( TypeName "ImGuiID", [t| ImGuiID |] )
3738
, ( TypeName "ImWchar", [t| ImWchar |] )
3839
, ( TypeName "ImDrawList", [t| ImDrawList |] )
3940
, ( TypeName "ImGuiContext", [t| ImGuiContext |] )
4041
, ( TypeName "ImFont", [t| ImFont |] )
4142
, ( TypeName "ImFontConfig", [t| ImFontConfig |] )
4243
, ( TypeName "ImFontGlyphRangesBuilder", [t| ImFontGlyphRangesBuilder |] )
4344
, ( TypeName "ImGuiListClipper", [t| ImGuiListClipper |] )
45+
, ( TypeName "ImGuiTableSortSpecs", [t| ImGuiTableSortSpecs |] )
4446
]
4547
}

0 commit comments

Comments
 (0)