Monday, June 30, 2008

CCombo. My arch nemesis.

CCombo is the emulated combo box that appears in Eclipse in, for instance, combos in table cell editors. This widget constantly causes me problems throughout WOLips because it's one of the most glaringly non-native components in the SWT family. Here are some pictures to illustrate:

CCombo Closed:

CCombo Opened:

Native (Leopard) Closed:

Native (Leopard) Opened:

Notice that in the closed form, there's no designator that shows that it is a combo (the up/down arrow icon). Currently there's not enough API in tables to add icons like this. I haven't looked at what i would take to fix that. In the open form, it's just all-sorts-a'-wrong. It's not the Leopard window style, it doesn't have proper keyboard navigation like native. Entity Modeler fixes some of this. In fact, if you were to look at this control outside of Entity Modeler, the focus ring is offset incorrectly by several pixels as well (it hangs outside of its table cell by about 3 pixels). Unfortunately, emulating is just never going to be right here. We can get away with it for tabs, because there is no native tab widget (yet), but for combo's, there are just too many expectations. I think the correct fix for this is to make CCombo a native widget on OS X, but currently C* widgets don't have native replacements (they are in the .custom instead of the .carbon package).

Sunday, June 29, 2008

Maclipse

I've been working on custom SWT and Workbench plugins that look more Macish than the defaults. After some discussion on the wolips list, I decided that ripping off Aperture would be a good way to go, because it comes the closest to showing samples of the layout widgets we need in Eclipse.

Here are some screenshots (and links to an early preview download at the end):

This screenshot shows the new CTabFolder/CTabItem. The design is nearly pixel-for-pixel ripped off of Aperture. Getting the view toolbars to layout properly in here took some hackery to ToolBar (because it doesn't, by default, support transparent backgrounds).

Here's the same screenshot, but with a middle tab selected.

The close icon appears when you rollover the tab image. This is nice because it keeps the layout fixed compared to Eclipse's default style, which shuffles around the left margin of tabs as you select and deselect them (to hide the close icon on unselected tabs). I think this is the way FireFox works, as well.

The Sashes on Eclipse don't draw any drag handles. Here we're showing that we now draw a drag handle (based on Aperture's style rather than the OS X standard "dot" drag handle). If the Sash is less than 3 pixels, no handle is drawn. If it's 3 or more, one is drawn, and if it's 5 or more, 2 are drawn.

The CoolBar grabber has been changed from a rectangle to an Aperturish dotted line.

And here's the full monty screenshot (toolbar hidden) ...

There's still plenty more to do. Most of the emulated widgets are very unmacish (CCombo being an egregious example that is very high on my hit list). I'd like to get Eclipse using the unified toolbar window style as well, but just setting the flag doesn't cause it to render the unified look. I'm guessing because top toolbar isn't registered as the window's actual toolbar (and instead is just a regular view inside the window).

If you want to try this out, you can grab the binary build of the SWT and Workbench plugins from the WOLips build server and simply replace the corresponding jars in your plugins folder. Note that these ONLY work on Eclipse 3.4 and they are ALPHA QUALITY so make backups of your original plugin jars before replacing them!

Friday, June 27, 2008

WALL•E

Go see it. That is all.

Monday, May 5, 2008

EOGlobalIDs for Abstract Entities

I just got burned by this and it was a bitch to figure out. I had an ERXBatchingDisplayGroup that was fetching an abstract entity type that used Single Table Inheritance. It turns out that the way ERXBDG was fetching, it fetched the page of PK's, turned those into faults, then fired the faults. The problem with this is that if you turn a PK into a fault for an abstract entity type (note that it just has the PK, so it doesn't know the actual subentity yet), EOF decides to fetch the object so it can resolve the entity name for the global id. You'll see this as a bunch of one-by-one fetches in your log. Needless to say this is total crap.

It turns out that you can instead turn each PK into a GID directly with entity.globalIDForRow(pkDict). Inside of EOGlobalID, it already tracks the concept of not knowing the final subclass type. When you attempt to turn this global ID into an EO (using ERXGlobalIDUtilities, or whatever), EOF will properly fetch the objects and everyone will be happy. The nice thing here is that ERXGIDUtils can batch those fetches into a single query so you don't get 40, 50, 100 (or whatever your page size is) hits to the DB. This SEEMS like a bug in EOF to me, though I won't say that this won't totally burn me at some point. (by "me," I mean "all of us" since this has now been changed in ERXBatchingDisplayGroup).

Wednesday, April 23, 2008

ActiveLDAP

ActiveLDAP has some annoying install warts, but it's a pretty cool library.

Installing

First download and build RubyLDAP. Annoyingly this is NOT a gem, so you can't gem install it.

Next, build it ...
ruby extconf.rb
make
sudo make install

Now install ActiveLDAP ...

sudo gem install ruby-activeldap
Quick Start

Many of the examples are talking to a default openldap install. If you want to talk to a Mac OS X Open Dircetory server, you will need to change the prefix for users and groups, shown below in a quick sample app:

#!/usr/bin/env ruby

require 'rubygems'
require 'active_ldap'

class Group < ActiveLdap::Base
  ldap_mapping :dn_attribute => 'cn',
               :prefix => 'cn=groups',
               :classes => ['top', 'posixGroup'],
               :scope => :one
  has_many :members,
           :class => "User",
           :wrap => "memberUid",
           :primary_key => 'uid'
end

class User < ActiveLdap::Base
  ldap_mapping :dn_attribute => 'uid',
               :prefix => 'cn=users',
               :classes => ['top','inetOrgPerson']
  belongs_to :groups,
             :class => 'Group',
             :many => 'memberUid'
end

ActiveLdap::Base.establish_connection(
  :host => 'someldapserver.mdimension.com',
  :port => 389,
  :base => 'dc=mdimension,dc=com',
  :bind_dn => "uid=mschrag,cn=mdimension,dc=com",
  :password => 'mschragpw',
  :allow_anonymous => false,
  :try_sasl => false
)

#Group.find(:all, '*').each do |group|
  #puts "#{group.cn}"
  #group.members.each do |member|
    #puts "  #{member.cn}"
  #end
#end

user = User.find('mschrag');
user.givenName = 'NewFirstName'
user.save
And that's the quick start. It should give you enough to experiment with.

Saturday, March 29, 2008

git-cvsimport failure

I've been mirroring Project Wonder's CVS with github, and unfortunately git-cvsimport has been a real problem. If I try to run it directly on the repository, I get:

git-cvsimport: fatal: cvsps reported error 11

... which is really helpful. Well it turns out that you can run cvsps outside of git-cvsimport and get this all to work. Here's roughly what you need to do:

export CVSROOT=[your cvsroot]
cvsps -x --norc -u -A [your cvsmodule] > /tmp/cvsps.out
cd /path/to/your/git/repos
git-cvsimport -o git_cvs_head_branch_name -P /tmp/cvsps.out [your cvsmodule]
So in my case, I do:
export CVSROOT=/local/wonder/cvs
cvsps -x --norc -u -A Wonder > /tmp/cvsps.out
cd /local/wonder/git
git-cvsimport -o Wonder_HEAD_Branch -P /tmp/cvsps.out Wonder

The key here is that we run cvsps manually, saving its output, then run git-cvsimport with a -P passing it the name of the cvsps output. This allows us to manually ignore cvsps errors rather than have them kill git-cvsimport.

Note that by default gitcvs-import will use "master" as your head branch, which can cause problems with later merges. It's best to keep all CVS branches in their own git branch and don't touch them except with git-cvsimport.

VS 2008

Visual Studio 2008 has some really slick features ... Check out the Javascript interpreter stuff in particular. I plan to steal liberally from this for WOLips.