The best kittens, technology, and video games blog in the world.

Showing posts with label gui. Show all posts
Showing posts with label gui. Show all posts

Tuesday, November 27, 2012

JRuby Swing GUIs with cheri gem

PocketMew by Sin Amigos from flickr (CC-BY)


I am not in any way a fan of desktop GUI toolkits - HTML5 and jQuery totally spoiled me, so I resisted for a very long time making GUIs for my Total War tools - and happily enough, other people would sometimes make them for me.

But this time I decided to make a desktop GUI, in JRuby, and that means one of the awful non-HTML toolkits.

So my first idea was of course making a big window with a menu calling some functions, and big embedded HTML form with all stuff in HTML. I was even getting somewhere since Java Swing has HTML widget, but then it turned out it's HTML 3.2 only, no Javascript whatsoever, and serious pain to get data into and out of it.

I also tried SWT, and hoped danlucraft's cookbook would help me get somewhere with it, but I couldn't figure out most of the things I wanted to try, so I kept looking.

Finally I found this lovely cheri gem, which didn't seem to such too hard. I've heard mostly horrible things about Swing API, but it was only as bad as the rumor says, at least for my simple use case.


I'll put all that code for public view eventually, but it's pretty massive, so here are just some tips for working with Swing and cheri.

Basic window creation

Start a class and include Cheri::Swing module. What you probably want to match HTML-ish behaviour is actually not a single layout manager but GridBagLayout (for actual layout) within ScrollPane (so you get scrollbars when content).

That's the code:


class ConcentratedVanillaBuilder
  include Cheri::Swing

  def initialize
    @controls = {}
    @frame = swing.frame('Concentrated Vanilla builder'){ |frm|
      size 800, 800
      default_close_operation :EXIT_ON_CLOSE
      build_menu!
      scroll_pane {
        panel {
          grid_bag_layout
          grid_table {
            background :WHITE
            build_form!
          }
        }
      }
    }
    load_settings! load_settings_file("settings/default.txt")
    @frame.visible = true
  end
end

This initialization is pretty generic (other than trivial matters of default window size and title), other than four italicized lines.

Separate form buildings from settings


That's advice for GUIs that simply configure some settings and then run some script. You want to keep your settings in a nice Hash, and don't mix GUI code with settings defaults.

So what you want are helper methods like these:
  def checkbox(name, description)
    grid_row{
      @controls["checkbox-#{name}"] = swing.check_box description, :a => :w, :gridwidth => 3
    }
  end

And then use methods on @controls[something] to both get and set various fields. That's far easier than ton of on_change callbacks or whatever is their Swing equivalent.

Use text_area not label for labels


Label widgets are pretty dumb, and non-editable text areas can handle things like multiline text and formatting a lot better.

Just add some helper methods and pretend you're coding HTML:

  def div_helpmsg(msg)
    grid_row{
      text_area(:a => :w, :gridwidth => 3){
        editable false
        text msg.gsub(/^\s+/, "")
      }
    }
  end

  def h1(msg)
    font = java.awt.Font.new('Dialog', java.awt.Font::BOLD, 24)
    grid_row{
      text_area(:a => :w, :gridwidth => 3){
        set_font font
        editable false
        text msg
      }
    }
  end
If things get too complicated, you can always go for full HTML widgets.

Result

Half-finished result looks something like this. Not amazing, but it will do the trick.

It will get released sometime soon, and then you'll be able to play random scenarios everybody's waiting for.

By the way if any Java / JRuby experts has better ideas, go ahead. Googling was unusually unhelpful to me here, and IRC and StackOverflow were as useless as they always are.

Saturday, January 26, 2008

Keyboard layout should not be a global setting

mac kitty by atomicshark from flickr (CC-NC-SA)

Most computers these days are laptops. Their computing power got quite decent, and they're even becoming reasonably powerful for moderate gaming. One of the major problems left is typing on them. Laptop keyboards, especially in smaller laptops, are tiny, have very small keys, no numeric keypad and painfully unergonomic shape which forces you to keep your hands in unnatural position. As keyboard and screen are attached to each other there's no way to make it comfortable for both your eyes and your hands. To make matters worse recently many laptops started to include a big touchpad which doubles as a mouse button, so when you try to type, and you have to keep your hands very close to each other because the keyboard is so small, you're very likely to accidentally "press mouse button" by touching the touchpad. Basically they're completely unsuitable for touch typing, and they will forever stay this way, because it's impossible to build a decent keyboard that fits in laptop form factor. That doesn't mean that all of them are equally bad, the worst one I've seen so far was Macbook's, and some in bigger laptops are only annoying instead of being actively painful.

This all means that unless the only thing you type are Google search queries, you need a real keyboard for your computer in addition to the internal keyboard. Most people don't seem to care about this, but I really like Dvorak layout. And here lies the problem because in every operating system I've ever seen keyboard layout is a global setting, not per-device setting. I want to touch type in Dvorak on external keyboard, but as touch typing on laptop keyboard is not possible I'd prefer it to stay QWERTY, so I can at least see what key I'm pressing. However as keyboard layout is global rather than per-device setting, I have to manually switch it every time I attach or detach external keyboard.

Pressing keyboard layout switcher a couple times a day is maybe not the worst usability problem out there, but could KDE/GNOME developers please improve it ? That would be really really great.

Sunday, January 06, 2008

GNOME sucks

one pissed off pussycat by John Carleton from flickr (CC-NC-SA)

My dead Macbook returned with a new disk. I normally use KDE, but this time I thought it would be a good idea to try the Ubuntu's default GNOME desktop. And it sucks.

The thing which sucks most is virtual desktops support. If I have programs opened on different virtual desktops I cannot switch between them using alt+tab. I cannot switch between them using taskbar. And I cannot take my mouse and simply move from one virtual desktop to another over screen edge. That makes the whole virtual desktop thing pretty much useless.

The second things which sucks is lack of single place with all configuration options. I don't think it even has configuration options I want, believing instead in "one size fits all". Wake up GNOME people - configurable Windows is way more popular than one-true-way Mac for a reason, and so is configurable KDE way more popular than one-true-way GNOME.

The third thing which sucks is GNOME trying too hard to be a Mac but failing. There's even a menubar at top of the screen, but it does not host current application's menus. Instead it takes one of the most valuable parts of screen (top edge) and completely wastes it. It's even worse on a computer with tiny screen like Macbook, where top bar and bottom bar together take large part of total screenspace, leaving much less for applications.

A few more things. Applications menu does not remember my recently used programs. The only reason I would ever use Applications menu instead of Alt+F2 is if it listed the few most frequently (or most recently) used programs for simple clicking. Without that it's completely useless. Places menu is completely useless, and System menu as I said should be replaced by a single place with all config it in. Like your beloved Mac. Or Windows. Or KDE. Or anything except for GNOME.