Tuesday, June 26, 2007

This is the end (for now)




The thing is done. The database is fairly stable, the edit perspective is basically done, and most importantly, I'll never use it.

Todos:

  • Feat special rules need to be implemented

  • MainPerspective calculated values (melee, damage, etc.)

  • Create charactersheet print out

Monday, June 25, 2007

CheckboxTableViewer.setChecked() fails silently

Took me a while to figure this out:

If you have a CheckboxTableViewer and want to set the initial state of the table contents as (un)checked, you cannot do the initialization in the LabelProvider. It seemed like the most logical place, and the viewer does enter the code for setChecked(element, true), but nothing is displayed. Turns you have to let the table draw first (I don't understand why):

public void update() {
// inputs the same
tableViewer.setInput("");
tableViewer.refresh();

List weapons = WeaponHome.inst.findAll();
for (DAO weapon : weapons) {
if (Ctx.getChar().weapons.contains(weapon)) {
((CheckboxTableViewer) tableViewer).setChecked(weapon, true);
}
}
}


For the record, this is the code that does not work:

public String getColumnText(Object element, int columnIndex) {
String value = "";
Weapon weapon = (Weapon) element;
if (isEditable()) {
if (Ctx.getChar().weapons.contains(weapon)) {
((CheckboxTableViewer) tableViewer).setChecked(element, true);
}
}

Tuesday, May 29, 2007

Expandable SWT/JFace Dialog

This confounded me for a while, so here's the short:
  1. Extend JFace Dialog
  2. Keep a handle to the content of your expandable section
  3. Do this (from ErrorDialog):

private void toggleDetailsArea() {
Point windowSize = getShell().getSize();
Point oldSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
if (listCreated) {
list.dispose();
listCreated = false;
detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
} else {
list = createDropDownList((Composite) getContents());
detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
}
Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
getShell()
.setSize(
new Point(windowSize.x, windowSize.y
+ (newSize.y - oldSize.y)));
}

Sunday, May 20, 2007

Working with Checkboxes in TreeItems

I spent some time working out how to get my Tree checkboxes functional. I'm reusing the SpellsView across the display and edit view (with AbstractSpellsView:

public void createPartControl(Composite parent) {
...
if (isEditable()) {
// select checkbox
TreeColumn treeColumn11 = new TreeColumn(tree, SWT.NONE);
treeColumn11.setWidth(60);
}
TreeColumn nameCol = new TreeColumn(tree, SWT.NONE);
nameCol.setWidth(60);
nameCol.setText("Name");



The subclasses override the getInput(), the abstract view includes a switch in the create and LabelProviders to update or ignore the checkbox.

Saturday, May 12, 2007

One Perspective to Rule Them All

I've had a few discussion about the "failings" of the Eclipse perspective model to effectively deal with the complexity of information management within an IDE. While most of his arguments are perfectly loony, he made the point that Eclipse imposes a "Debug Perspective" on you while coding, causing the developer to lose focus as you switch from whatever his main work perspective is. This bugged me enough in the past to create a new window to house the Debug perspective. The new solution:

Porting to RCP

After taking the charmgr as far as I could with PyGTK, I've decided to port it over to the Eclipse RCP. Whatever its failings, I love the frameworks and architecture, and expertise in Eclipse is marketable. The philosophy is about 180 degrees from Python (I've read many posts lauding Python's lack of rigid frameworks), but being from Java, the RCP is my comfort zone.

Porting the UI was trivial using the Visual Editor (though not nearly as simple as Glade):


I used Derby as a replacement for SQLite, and after populating the Spell tree using straight SQL, I thought I'd look into Hibernate for data access. The Hibernate framework hides the SQL from the code, provides a lot of connection management functionality, and has the added benefit of generating most of the boilerplate DAO code. Unfortunately I ran into an access problem when trying to initialize Hibernate from the RCP:

 private Object getInput() {
logger.debug("getInput()");

HibernateUtil.currentSession();


Basically get a ClassNotFoundException on Session. This solved by creating a plugin from the jar and registering it in the MANIFEST.MF.

After flopping around for a bit, I violated good practice and copied the hibernate.cfg.xml file to the root of the org.hibernate plugin. This solved the problem for the short term. I then moved all the dependent jars to their rightful place in the hibernate plugin and as well the creating an org.apache.logging plugin for those libs (so both hibernate and charmgr can access the logging). I cheated again by copying the log4j.xml to the logging plugin to resolve that little classpath issue.

So my current workspace looks like this:



and the main view is now functional:

Sunday, March 11, 2007

TiddlyWiki Customization Notes

TiddlyWiki rocks the house, of course. Fantastic tool for a professional diary, and it's been tweaked for all kinds of tasks. I'm experimenting with using it as an content manager for static media, so I want to remove/hide the sidebar (what contains the search, options, tabs, etc):

1. remove the <div> sidebar stuff:
<div id='sidebar'>\n<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>\n<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>\n</div>\n (249:780)

2. recover the space for the content area:
#displayArea {\n margin: 1em 0em 0em 14em;\n} (247:4250)


The search box is the only thing I'm interested in keeping from the sidebar, so I move it to the MainMenu (right sidebar) simply by adding <<search>> to the content of MainMenu.

Because the content of the wiki will be static (it will eventually be the gateway to CD of deliverable documentation), I want to remove the editor and creation/modification date information on tiddler subtitle found on the ViewTemplate:

\n<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date [[DD MMM YYYY]]'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date [[DD MMM YYYY]]'></span>)</div>


I also changed all refs to "tiddler" to "entry" to grow things up a little bit.

I don't like the way the heading are formatted by default, viz. the blue background, so that's the next to go:
background: [[ColorPalette::PrimaryPale]];\n(246,446)

Sunday, February 18, 2007

Getting text from a TextView

It took some searching to see how to get the string contained in a TextView with a string (hint: there's no textview.get_text()), but here's the snippet I came up with:

notes_txt = self.widgets.get_widget('notesTxt').get_buffer()
startiter, enditer = notes_txt.get_bounds()
character = dbaccess.fetch_character(self.char_id)
notes_file = open(character['name'] + "-notes.txt", "w")
notes_file.write(notes_txt.get_text(startiter, enditer))
notes_file.close()

Basically, you have to find the start and end Iters to set the bounds of the text you want.

Populating is trivial:

try:
notes_file = open(character['name'] + "-notes.txt", "r")
text = self.widgets.get_widget('notesTxt').get_buffer()
text.set_text(notes_file.read())
notes_file.close()
except:
print "No notes file found: ", character['name'] + \
"-notes.txt"

Saturday, February 10, 2007

Setting the active text on a ComboBox

I had some trouble finding this on the Interweb, so here's how you set the active text on a ComboBox:

def set_combo_value(self, combo, value):
model=combo.get_model()
for item in model:
if item[0]==value:
combo.set_active_iter(item.iter)
break

Setting the active item by index you can get right off the ComboBox API.

Wednesday, February 7, 2007

SQLLite Database Browser

Here's a nice tool for browsing the contents of the Character Manager db:

SQLLite Database Browser

Runs as a single .exe, no dependency downloading nonsense. Excellent work, guys!

Saturday, February 3, 2007

Populating a ComboBox

I'm using Glade to design my UI, which introduced some difficulty in figuring out how to populate my ComboBox (of which there are 2 versions in PyGTK). The PyGTK Tutorial was helpful, and the PyGTK IRC Channel took me the last mile.

The short of it is, a ComboBox works like a TreeView:

# create a store
weapon_store=gtk.ListStore(gobject.TYPE_STRING)
# populate the store
for w in weapon_names:
row=weapon_store.insert_after(None, None)
weapon_store.set_value(row, 0, w)
# get the Glade widget
left_hand_weapon_cbo=self.widgets.get_widget('leftHandWeapon')
left_hand_weapon_cbo.set_model(weapon_store)
# the business bit
cell=gtk.CellRendererText()
left_hand_weapon_cbo.pack_start(cell)
left_hand_weapon_cbo.add_attribute(cell, 'text', 0)
left_hand_weapon_cbo.set_wrap_width(3)


It would be nice if the Glade/PyGTK infrastructure would do more of the work of setting up the widgets with sensible defaults.

Tuesday, January 23, 2007

Screenshot

First pass with by-level spell table populated from the character file.

Monday, January 22, 2007

First Thoughts

Glade is quite nice apart from the GIMP-style multi window UI. It's incredibly frustrating to have a web page with instructions (or another app with a mockup) underneath Glade, then click that app and then have to raise each of the four Glade windows separately. Makes absolutely no sense. A friend of mine suggests that's what multiple desktops are for, but this is a clumsy workaround.

Found a good tutorial on Glade + Python. It's all text, and somewhat outdated, but was the most helpful of the stuff I read.

Kicking the Java Desktop

This guy makes some disparaging (but empty) comments about Java on the Desktop. It's early days, but my own experience with Python + Glade leaves much to be desired. Java tools are massive levers of productivity, Eclipse foremost among them. Why anyone would prefer working in a bare text editor + commandline is beyond me.

First Post

This is experimental blog tied to the development Character Manager application. This will be the journal for development (containing editorial content), leaving the wiki for "factual" data. The Character Manager application is a simple UI for managing characters used in the Dungeons and Dragons game. It is inspired by RedBlade, but it's chief purpose is to teach me Python + GTK UI development.