FLTK-based cross-platform CSV editor Tablecruncher now open source

120 views
Skip to first unread message

fischer...@gmail.com

unread,
May 19, 2025, 1:03:23 PMMay 19
to fltk.general
I’d like to share that I’ve open-sourced my previously commercial app Tablecruncher, a lightweight CSV editor built using the FLTK GUI toolkit.

You can find the code here: https://github.com/Tablecruncher/tablecruncher

The project started out as a way to refresh my rusty C++ knowledge and take a break from web development. As the app matured, I released it commercially for macOS only. I received quite a bit of positive feedback from users who needed a fast CSV viewer and editor. Recently, I decided to open source it under the GPLv3, as I never intended to run a full-fledged software business. In the process, I also built Windows and Linux versions, so Tablecruncher is now a cross-platform app.

I tried several other toolkits like Qt (complicated licensing) and wxWidgets (quite nice, but I was already deeply involved with FLTK), even rewriting Tablecruncher multiple times (please don’t ask). But I found FLTK always the easiest to handle as a part-time developer.

One main concern when using FLTK was mimicking the native look and feel — especially important for macOS users. If you dig into the code, you’ll see I even wrote a custom routine to draw the buttons in dialogs to make them look a bit more macOS-like, including rounded borders and a somewhat fitting blue tone.

I hope the repo might be of interest as a real-world example of how FLTK can be used for a cross-platform desktop app, including build instructions for the three major platforms. Of course, if you spot anything odd or have suggestions for improvement, I’d love to hear them.

Thanks to everyone involved in maintaining and improving FLTK. I hope that by open-sourcing my app, I can give a little something back to the community.

Best regards,
Stefan

Albrecht Schlosser

unread,
May 20, 2025, 7:40:50 AMMay 20
to fltkg...@googlegroups.com
On 5/19/25 19:03 fischer...@gmail.com wrote:
> I’d like to share that I’ve open-sourced my previously commercial app
> Tablecruncher, a lightweight CSV editor built using the FLTK GUI toolkit.
>
> You can find the code here: https://github.com/Tablecruncher/tablecruncher

Thanks for sharing this interesting project. So far I had some time to
take a quick look but not yet for building and testing. I'll try to do
that later...

> I tried several other toolkits like Qt (complicated licensing) and
> wxWidgets (quite nice, but I was already deeply involved with FLTK),
> ... I found FLTK always the easiest to handle as a part-time developer.

That's great, thanks for sharing this feedback as well. This might help
others to decide to use (or at least to try) FLTK too.

> One main concern when using FLTK was mimicking the native look and
> feel — especially important for macOS users. If you dig into the code,
> you’ll see I even wrote a custom routine to draw the buttons in
> dialogs to make them look a bit more macOS-like, including rounded
> borders and a somewhat fitting blue tone.

I'll definitely look at this code, thanks for the heads-up. We're always
looking for improvements that more app developers may want to use...

> I hope the repo might be of interest as a real-world example of how
> FLTK can be used for a cross-platform desktop app, including build
> instructions for the three major platforms. Of course, if you spot
> anything odd or have suggestions for improvement, I’d love to hear them.

I'll take a look and let you know if I find anything, either here or as
GitHub issue.

> Thanks to everyone involved in maintaining and improving FLTK.

Welcome!

> I hope that by open-sourcing my app, I can give a little something
> back to the community.

We appreciate open source FLTK apps. Thank you.

Best regards,
Albrecht
(FLTK developer)

Matthias Melcher

unread,
May 20, 2025, 8:14:19 AMMay 20
to fltk.general
fischer...@gmail.com schrieb am Montag, 19. Mai 2025 um 19:03:23 UTC+2:
I’d like to share that I’ve open-sourced my previously commercial app Tablecruncher, a lightweight CSV editor built using the FLTK GUI toolkit.

Thank you very much for your feedback. It's always great to see that our library is in active use.
 
One main concern when using FLTK was mimicking the native look and feel — especially important for macOS users. If you dig into the code, you’ll see I even wrote a custom routine to draw the buttons in dialogs to make them look a bit more macOS-like, including rounded borders and a somewhat fitting blue tone.

 The default look is very Windows98, which is quite appropriate for the time when Bill started the library. For me personally, I always set my apps to the "GTK+" scheme by default. As a Mac user, I can live with that. We have a bunch of ideas for schemes and color themes. Let's see what we can pack into 1.5.

Albrecht Schlosser

unread,
May 20, 2025, 1:32:35 PMMay 20
to fltkg...@googlegroups.com
Am 5/20/25 13:40 schrieb 'Albrecht Schlosser':
if you spot anything odd or have suggestions for improvement, I’d love to hear them.

I'll take a look and let you know if I find anything, either here or as GitHub issue.

OK, you asked for it, and here it is ;-)

This is from my personal build on my notebook (12th Gen Intel Core i7-1260P) using Debian 12 (Bookworm).

First of all, I built your app with both FLTK 1.4.3++ (current git branch-1.4) and 1.5 (branch master), and both worked after tweaking your CMakeLists.txt a bit:
```
$ git diff
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d61f6a8..ac04415 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -144,17 +144,9 @@ elseif(WIN32)
     target_link_options(${PROJECT_NAME} PRIVATE ${LINKER_FLAGS})
     target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
 elseif(LINUX)
-    target_link_libraries(${PROJECT_NAME} PRIVATE
-        ${FLTKLIBDIR}/lib/libfltk.a
-        ${FLTKLIBDIR}/lib/libfltk_images.a
-        ${FLTKLIBDIR}/lib/libfltk_z.a
-        Xft
-        fontconfig
-        Xrender
-        X11
-        pthread
-        dl
-    )
+    set(FLTK_DIR ${FLTKDIR})
+    find_package(FLTK 1.4 CONFIG REQUIRED)
+    target_link_libraries(${PROJECT_NAME} PRIVATE fltk::images)
 endif()
 
 
```

I used `ninja`:
$ cmake -G Ninja .. -D FLTKDIR=/home/albrecht/fltk/{1.4|1.5}/debug/share/fltk; time ninja

I had to define 'FLTKDIR' and assign it to 'FLTK_DIR' as you did for the WIN32 build. Wouldn't it be easier to use FLTK_DIR in the first place?

Your `target_link_libraries()` for Linux uses several libs, but this is all not necessary if you build with FLTK 1.4 or later, using "Modern CMake" (which you obviously do). This is described in our README.CMake.txt and *should* be usable "cross-platform", i.e. your distinction of WIN32 vs LINUX shouldn't be necessary. The same *should* also apply to macOS ("APPLE"). Even linkage to the macOS frameworks should be "inherited" properly if you use the correct "CONFIG" mode with CMake.

For instance: the following code can be simplified and can optionally include building a simple macOS bundle, although I noticed that you are doing it by other means. Note that "WIN32" and "MACOSX_BUNDLE" are ignored on other platforms.
```
if(WIN32)
    add_executable(${PROJECT_NAME} WIN32 ${SOURCES})
else()
    add_executable(${PROJECT_NAME} ${SOURCES})
endif()
```
could become just one line:

add_executable(${PROJECT_NAME} WIN32 [MACOSX_BUNDLE] ${SOURCES})
The line
  include_directories(${SRCDIR} ${EXTERNAL} ${FLTKINCDIR} ${FLTKLIBDIR})

should be after (below) add_executable() and should likely read:

  target_include_directories(${PROJECT_NAME} PRIVATE ${SRCDIR} ${EXTERNAL})

(tested on Linux, see below). Again, all the FLTK specific include directories are "inherited" by proper use of CMake CONFIG mode (which you are doing). All the extra stuff you're doing with FLTKINCDIR and FLTKLIBDIR seems to be superfluous but I didn't touch that.

Last but not least: using the libs "fltk::fltk" and "fltk::z" explicitly is not necessary and could even be wrong if the FLTK library has been linked against the system ZLIB (as it is in my case). fltk::fltk doesn't does no harm but is implied anyway by fltk::images. (Side note: I'm not sure why your instructions say to use the bundled zlib, but that's your decision.)

IMHO it's much better to use what FLTK provides by CMake as link and include dependencies (on all platforms) rather than trying to be explicit. This is possible since FLTK 1.4 if it has been built with CMake. If your target FLTK version is 1.4 anyway, this should work. Unless ... you or another user wants to build with a system version of FLTK that lacks its CMake config file.

I also tried (again, only on Linux) my simplified version of CMakeLists.txt. Please see attached file 'simplified.diff' for some ideas.
$ git diff --stat
 CMakeLists.txt | 54 +++++++++++++-----------------------------------------
 1 file changed, 13 insertions(+), 41 deletions(-)

I hope this helps. I worked on this (longer than I had planned) because I always want to test FLTK builds with different apps, and yours was a good example (and I might use it myself from time to time ;-) ). Note that even my simplified version can probably be improved, but this is enough for today. Enjoy trying my version and improving it. Feedback would be welcome, and please feel free to use my simplification in your repo (no attribution necessary, just us it if you like).

Finally: I wonder why some of your source files take about 10 and more (up to 18) seconds to compile on my system. The entire build takes 32 seconds (about 5 min. CPU) on my 16 core intel i7. This seems to be very much, but this is only my gut feeling. I noticed that you are using the C++ stdlib intensely...

For comparison: the entire FLTK lib (X11) builds in 12.6 seconds (2m36s total CPU) on the same system.

simplified.diff

Mo_Al_

unread,
May 20, 2025, 1:39:21 PMMay 20
to fltk.general
Visually the app looks really nice. Thank you for sharing

fischer...@gmail.com

unread,
May 21, 2025, 3:51:53 AMMay 21
to fltk.general
@Albrecht Wow, thanks — that's incredibly helpful feedback! I'm completely new to CMake and just tried to convert my macOS-only Make solution. And my Makefile was already a mess. ;-)
I'll definitely try to use your suggestions in future builds. Building and testing for three (or rather four — macOS ARM and Intel) platforms is a heavier task than I expected.

@Others Thanks as well for your kind words — much appreciated!

Albrecht Schlosser

unread,
May 21, 2025, 7:02:31 AMMay 21
to fltkg...@googlegroups.com
On 5/21/25 09:51 fischer...@gmail.com wrote:
@Albrecht Wow, thanks — that's incredibly helpful feedback!

Welcome.


I'm completely new to CMake and just tried to convert my macOS-only Make solution. And my Makefile was already a mess. ;-)

I understand this. IMHO (larger) Makefiles *are* a mess. Almost always. If you look at our src/Makefile in 1.4 (1100 lines, not counting configure.ac and all the other Makefiles) you'll understand this as well. That's one of the reasons why we decided to remove configure/make support in FLTK 1.5. CMake needs a lot of knowledge to do it well, but it can do much more than the classic configure + Makefiles can do.

I'd like to add another hint for CMake usage: in theory CMake *should* hide all platform specific things so your CMakeLists.txt is mostly cross-platform (see my simplification of your CMakeLists.txt). That's what CMake was designed for. Don't try to "port" your Makefile(s) step by step to "similar" CMake code. Only in special cases (e.g. macOS bundles) you need platform specific CMake code. Ideally. If you look at our FLTK CMake files you'll notice that there is a lot of platform specific code (grown in the past) but I'm trying to simplify this as well in the future. The "modern CMake" approach is important, in short words: don't use variables and global functions, use target specific "properties" instead. For you as an application developer you need to look for CMake CONFIG mode of your dependencies (libraries). If this is available (as in FLTK since 1.4) you can just use `target_link_libraries(target ... fltk::fltk) etc. (usually with the "prefix::" notation) to link the library *and* to inherit all dependencies and include directories.


I'll definitely try to use your suggestions in future builds. Building and testing for three (or rather four — macOS ARM and Intel) platforms is a heavier task than I expected.

In the case of FLTK as a dependency macOS "ARM and Intel" shouldn't make a difference, hence you should be able to use all three (or four) platforms in common code, relying on FLTK to provide the needed properties (like weak linking) for specific macOS platforms.

Good luck.


@Others Thanks as well for your kind words — much appreciated!
Albrecht-S schrieb am Dienstag, 20. Mai 2025 um 19:32:35 UTC+2:
Am 5/20/25 13:40 schrieb 'Albrecht Schlosser':
if you spot anything odd or have suggestions for improvement, I’d love to hear them.

I'll take a look and let you know if I find anything, either here or as GitHub issue.

OK, you asked for it, and here it is ;-)

This is from my personal build on my notebook (12th Gen Intel Core i7-1260P) using Debian 12 (Bookworm).

First of all, I built your app with both FLTK 1.4.3++ (current git branch-1.4) and 1.5 (branch master), and both worked after tweaking your CMakeLists.txt a bit:

[...] Details removed for brevity.


Greg Ercolano

unread,
May 22, 2025, 4:07:42 PMMay 22
to fltkg...@googlegroups.com

On 5/19/25 10:03, fischer...@gmail.com wrote:

[..] Of course, if you spot anything odd or have suggestions for improvement, I’d love to hear them.

    I'm always glad to see Fl_Table being used. I know it takes "getting used to", and I think once someone plays with it, they get why it's designed the way it is, and the benefits that brings for speed, and allows the application to handle data management in whatever way is most efficient for the app.

fischer...@gmail.com

unread,
May 23, 2025, 3:51:24 AMMay 23
to fltk.general
In fact, Fl_Table has been a main reason I chose FLTK in the first place. During my research which UI toolkit to use, my focus was on the table components. Fl_Table does what I needed it to do and was rather easy to handle. So, thank you for providing it.


My biggest problem with FLTK is the multi document handling. When having several documents windows open, it's not always easy to tell which is on top. Especially on macOS, that's a problem as you have only a single app-wide menubar. My solution sort of works, but I'm inclined to believe there would be a better and more robust pattern.

So, if anyone wants to look into it, I'd be extremely thankful. :-)

Thanks again for all your work and help!
Stefan

Heart Bleed

unread,
May 29, 2025, 1:17:04 AMMay 29
to fltk.general
Graphics looks super awesome. Will be good for me to learn from this open project :)

Heart Bleed

unread,
Jun 3, 2025, 7:31:52 AMJun 3
to fltk.general
It seems hard for me to grasp you code (most code not commented). Maybe someone here could help me with some tips as how to handle project with this many files. @fischer maybe you could help me with some documents/memoir that you made while you were developing it.

Regards

fischer...@gmail.com

unread,
Jun 4, 2025, 4:58:40 AMJun 4
to fltk.general
Oh, yes, the code really lacks documentation. My goal was to document the code before open sourcing it, but I learned that this would have meant to never open source it. ;-)
I hope to find some time to compile some basic developer documentation.

Greg Ercolano

unread,
Jun 4, 2025, 10:37:47 AMJun 4
to fltkg...@googlegroups.com

On 6/4/25 01:58, fischer...@gmail.com wrote:

Oh, yes, the code really lacks documentation. My goal was to document the code before open sourcing it, but I learned that this would have meant to never open source it. ;-)
I hope to find some time to compile some basic developer documentation.

    He seemed interested I think in maybe a simple top level description of the files.

    I usually put some form description of class hierarchy or per-file descriptions in a README file in the src directory, usually as an "ASCII art tree"; breadcrumbs to help return to a project after a year or so of not working on it.

    This sort of thing is easy to write, and I find has the biggest impact on getting me back into the headspace of a project, when returning to it after a long time. Moreso than really getting in there with detailed dev docs or doxygen-level source comments.

    Here's one for a small FLTK GUI application that's over 20 years old, redesigned it a few times. I put this info in the README more towards the bottom, below the descriptions and whatnot. (It's a small app that shows the real time cpu/mem/network use of multiple hosts in the form of bargraphs):

GUI CLASS HIERARCHY

    rushtop : Fl_Double_Window
       |
       |__ HtmlHelp              -- hidden dialog
       |__ HostBrowser           -- hidden dialog
       |
       |
       |__ MyHorizPack           -- manages column headers
       |   |__ Fl_Box[]          -- manages column header names
       |
       |__ Fl_Scroll             -- manages all the hosts in a scroller
           |__ HostGraph[]       -- manages groups of GraphBox and HostBox
           |__ MyHorizPack
           |   |__ HostBox[]     -- manages hostname column for one row
           |
           |__ MyHorizPack       -- manages columns for one row
               |__ GraphBox[]    -- manages data for one column of info (cpu, ram, swap..)
                   |__ BarData[] -- manages individual data for a single column..
                                    > for cpus, one of each for: usr, sys
                                    > for ram, one for: "ram used"
                                    > for swap, one for: "swap used"
                                    > for net, one of each for: input, output

MEMBER HIERARCHY

class RushTop : Fl_Double_Window
   |
   |-- String hostgroups     -- unexpanded list of hostgroups
   |-- String hosts          -- list of hosts to show
   |-- PipeCommand *pcmd     -- runs 'rush -status..'
   |-- popup                 -- (Fl_Menu_Button) popup menu
   |-- helpwin               -- (HtmlHelp) help dialog
   |-- hostbrow              -- (HostBrowser) host browser dialog
   |-- (user preferences)
   |-- (RC file management)
   |
   |-- heading (MyHorizPack) header for the cpu bars
   |       |
   |       |-- hostheading (Fl_Box)       -- the heading box for the hostname
   |       |-- cpusheading (Fl_Box)       -- the heading box for the cpus
   |       |-- ramheading  (Fl_Box)       -- the heading box for the ram
   |       |-- swapheading (Fl_Box)       -- the heading box for the swap
   |
   |-- scroll (Fl_Scroll)                 -- the scroll widget
       |
       |-- hostgraphs[] (HostGraph:FlHorizPack) -- array of 'graph' rows
         |
         |-- hostbox (HostBox:Fl_Box)           -- the lefthand hostname 'box'
         |-- cpugroup (Fl_Group)                -- parent for all the cpu bar graphs (can hide())
         |          |
         |          |-- cpus[0] (GraphBox)            -- array of cpus
         |                  |
         |                  |-- bars[0] (BarData)     -- usr use of cpu 0
         |                  |-- bars[1] (BarData)     -- sys use of cpu 0
         |                  :      :    
         |
         |-- mem  (GraphBox)            -- the mem bar
         |     |
         |     |-- bars[0] (BarData)    -- mem used
         |
         |-- swap (GraphBox)            -- the swap bar
         |     |
         |     |-- bars[0] (BarData)    -- swap used
         |     |-- bars[1] (BarData)    -- 'bad swap'
         |
         |-- net  (GraphBox)            -- the network i/o bar
               |
               |-- bars[0] (BarData)    -- input i/o
               |-- bars[1] (BarData)    -- output i/o

Heart Bleed

unread,
Jun 20, 2025, 2:57:42 AMJun 20
to fltk.general
@Er..... Yes sir. I was looking for something like that

@fisher..... I really think I would learn a lot about FLTK from your project. Can I please get your Telegram username 
So I could talk to you for small helps? 

Reply all
Reply to author
Forward
0 new messages