Saturday, September 10, 2011

Windowing Toolkits: Why You No Meet My Requirements?

Recently, I had an epiphany. I had been searching for a programming project that could, simultaneously, be something I'm familiar with, something that forces me to learn new things, and be something I intend on finding a use for in the future.

Now that I have made some significant progress in this endeavor (and also because I have no readers of my blog), I have decided that I can safely announce here what I have been working on.

My idea is a hodgepodge of  projects I have done in the past, integrated in such a way that they can all be used together easily and effectively. When playing Kalarsys (http://kalarsys.exofire.net) over the Internet, we typically use our computers to simulate dice rolling, store character sheets, and (Tale Spinners specifically) generate non-player characters (NPCs). For the dice rolling and NPC generation, I had created programs in the past. While lacking elegance, they were functional. We typically used word processors to handle our character sheets and a web browser to reference the various game materials.

This mess leaves at least four or five windows open simultaneously, ignoring any whiteboard and voice-over-IP (VoIP) software we are using. "Why not combine some of this shit into one program?" I pondered to myself, nearly wetting my pants in excitement over the prospect. I drew up some diagrams of what the program should look like. Then, I got to work selecting a toolkit to use for developing the graphical user interface (GUI) of the program.

I thought, foolishly, that my requirements were simple:
  • Must be cross-platform. I'm the only one that uses Linux on a nearly fulltime basis, but I want to be able to run a native copy. 
  • Must be "open". I avoided Microsoft's Visual Studio Express products because of license issues. While Mono provides a decent, open-source .NET implementation, I didn't want to use anything that was based on such a closed system.
  • Must provide a means of rendering HTML. The rulebook(s) are in HTML, and by being able to separate the chapters the program would be able to render chapters without me having to change the book in any real way.
  • Must be programmed using C/C++.
Oh, there are solutions that meet these requirements. Let me give you the rundown on why I've been bashing my face off of my keyboard lately.

I decided on GTK+ almost immediately. Coding the interfaces without any sort of GUI editor was super-easy. The paradigm of packing boxes was easy to grasp and simple to code. I had about 80% of what I needed to know about it down in my first day at it, I'm sure. I had a basic UI done, three buttons at the top for "NPC Gen", "Book Reference", and "Character DB". In the middle, a simple and always-visible instance of a dice roller. Finally, a big area at the bottom for whatever was selected with the top buttons.  I imported (and slightly modified) some code from my most recent KDice GUI program and got the dice roller working.

Then, I decided to try and get my development environment on Windows set up. Holy shit, if I knew it was going to be such a pain I wouldn't have bothered. I spent way too long finding a way to do this, but at long last, the official website was able to make me feel stupid when I figured it out. (At your own risk:  http://www.gtk.org/download/win32.php, download the 2.22 full bundle and read the readme).

I told Code::Blocks to check in c:\opt\gtk and I was set to go. I got the program built and running and I was feeling pretty good about myself. I was living the high life, developing with an intuitive toolkit with a long UNIX/Linux history on Windows.

Then, I thought it would be great to get the book viewer up and working. I may as well have tried clipping my nails with a garbage disposal. One of my tenants listed above was that HTML rendering is required. Oh, no big deal. There's GTKHTML, right? Or WebkitGTK+. Or GtkMozEmbeded.

Well, here's the rub: GTKHTML hasn't been supported (in either iteration) for several years. WebkitGTK+ doesn't work on Windows. If I'm wrong, which I pray endlessly for, prove me wrong. Please. If there is some magical way to use it, then please direct me to a guide or tutorial showing how. GtkMozEmbeded suffers from a combination of the two previous problems: It's old and unsupported, and also doesn't work in Windows. (And by "doesn't work" in this context, I mean that they aren't compatible with mingw32-g++ (my C++ compiler in Code::Blocks) running on Windows.)

I think I spent a good two days Google-searching for some way to get any of these three solutions to work. And I found lots of help....for those programming in Python. Foolishly, I pressed on. I found some GTKHTML packages, but the only mingw32-g++ ones were some OpenSuSE packages. Suddenly, I knew what I had to do: create a Linux virtual machine, install OpenSuSE on it, install these packages and cross-compile for Windows.

I love programming (when it doesn't make me want to pull out my pubic hair one at a time as a means of exchanging my emotional pain for physical pain). I love using Linux (when I don't get the sudden urge to play Oblivion. Or any PC game for that matter.) Somehow, though, coding this program in Linux and compiling for Windows seemed like a suboptimal solution, especially considering I was already set up for compiling on Windows. GTKHTML was a picky bastard, though, and my code struggled to compile with it around and refused to link outright. (Compiling turns code that has been written into machine code, linking takes the compiled code I've written and combines it with the GTK+ code I'm using to make the final program.)

Somehow, I managed to get GTK+ programs to work in Linux without Code::Blocks working for me and even made a few friends along the way. Most notably, pkg-config, which I remember somewhat from my tangles with SDL. He's a little helper that'll grab all the options you need to include for compiling and linking code that uses external code, like GTK+ or SDL. A simple `pkg-config --cflags --libs gtk+-2.0` in my makefiles helped my code compile and run, but GTKHTML was still being a bitch.

Endless Googling (and even Bing-ing, in desperation) returned not useful results. UNTIL someone with my exact problem (I swear to God it was buried under four pages of nonsense results) was helped by an old C coder. (http://forums.freescale.com/t5/CodeWarrior-for-ColdFire-and/CW6-1-Undefined-Reference-Linker-Error/td-p/1397) Though it didn't immediately help, it sure put me on the right track. Putting my "#include <gtkhtml/gtkhtml.h>" preprocessor command inside my other new friend, an "extern "C" { }" block, fixed those linker errors right up. And made me feel like dumbass for wasting so much time.

So far, my disgusting solution of cross-compiling has been working decently well. Except for the 15MB of DLLs I have to ship with my program. Then I'll have to figure out what exactly the licenses are forcing me to include in addition to that. Oh, and the D-Bus errors I can't seem to fix, though the program still works fine. Mostly.

Then I decided it was time to include a chapter listing. Click a chapter, the HTML code of that chapter gets sent to the GTKHTML widget to be rendered. Great in theory, except despite how easy everything else in GTK+ is, list boxes don't exist. Instead, there are... um... Tree Views. They're amazingly powerful and extensible. But when you just want to display a God damn list of items in a box, it's overkill. They're ridiculously complicated and unintuitive. Somehow from copying the code of others I've managed to get a rudimentary list box going in just over 20 lines of code. Despite it's great power and flexibility, I'm used to doing such a feat in under five lines. Thankfully, someone has written a decent wrapper for them... in Python. (Python is evidently more popular than I thought, and startlingly so.)

For some reason I haven't given up on the project yet. I'm way too close to having a finished, usable product to give up now. And I can't imagine that the hard stuff isn't behind me, though I doubt I could be surprised after the list box incident.

There were points in time where I decided that maybe I'd be better of using WxWidgets or something other framework. I was greatly averse to such an idea when I started. WxWidgets requires a 2GB package to be installed for me to develop with it in Code::Blocks. Also, I don't remember much from my last foray with it, but I remember struggling with coding the interface design (there's a GUI for it, but I won't want to depend on that). At this point, however, it isn't out of the question that I'd start over and made a WxWidgets version once I finish. There's an easy-to-use HTML rendering widget and list boxes at least. Plus, installing a 2GB package to compile natively doesn't seem so bad compared to a 4GB virtual Linux machine for cross-compiling.

Now that I've gotten all that off of my chest, I think it's time to give my fingers a break. They've been doing a  lot of coding and sandwich making lately, and blogging isn't doing much to stave off my imminent carpal tunnel syndrome. While it may seem crazy, I think what I may do is start over fresh and make some kind of guide on how to do this all in the future, partially for my own reference and partially to demonstrate how insane the process is. Hopefully some good comes out of the teeth my keyboard has claimed from me.

No comments:

Post a Comment