“Can you pick up some Block chocolate for cooking?”
“You mean a block of chocolate?”
“No, Block chocolate, it’s sort of metallic looking.”
So it is:
“Can you pick up some Block chocolate for cooking?”
“You mean a block of chocolate?”
“No, Block chocolate, it’s sort of metallic looking.”
So it is:
The rhythm was off or it was off-rhythm, or both. It felt, slightly, off. It wasn’t so much a Batman movie as it was a Joker movie. Ledger as The Joker is close to perfect, forget the entire “last movie” bit, he was just very very good here. Bale I’m not so sure of, I don’t think he’s entirely right for this. Feel a tinge of disappointment, not quite as good as I had hoped. Certain bits outright disgusting. But the Joker? Wicked.
Better than bad.
Learning more python and wanting to do some UI code in Linux I turned to PyGTK for a small home-brew Gnome Twitter app. As is invariably the case when I want to do some quick hacky little program with a GUI, after the third widget I hit a wall in the documentation wanting to do something which seems simple but is apparently not part of the standard functionality of the toolkit. Frustration. Does this imply something about GUI toolkits? Maybe.
The problem: you want to display a snippet of text in a list, for the list you have to use the aptly named TreeView component, for rendering text you have to use a CellRendererText. A list model representing rows with an image (PixBuf) on the left and text on the left would look something like this:
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn("MyText", cell)
col.set_attributes(cell, markup=1)
liststore = gtk.ListStore(gtk.gdk.Pixbuf, str)
textlist = gtk.TreeView(liststore)
textlist.append_column(col)
When used this will show text in a single line, continuing beyond the border of your widget should it happen to be longer than the widget’s current width. But since I’m building my little twitter thingamajig I want the text to wrap, dynamically, as the window resizes. Please.
Since some more recent version of GTK you can set wrap parameters for CellRendererText:
cell.props.wrap_mode = pango.WRAP_WORD cell.props.wrap_width = 200
Close, but no cigar. Notice that “wrap_width” parameter? It’s a fixed size to determine where the text should wrap. Fixed size?! What about resizing? It’s a window toolkit, I will drag that border around.
Narrowing the Google search to include the “pango.WRAP_WORD” and “wrap_width” keywords lead to the open source PyChess application, free as in sweet, annotated, highlighted, fully indexed source code. That particular function appends a column to a treeview and shows how to attach a callback to it to listen for “size-allocate” events on which you can recalculate the “wrap_width”. This is the relevant bit:
def callback (treeview, allocation, column, cell):
otherColumns = (c for c in treeview.get_columns() if c != column)
newWidth = allocation.width - sum(c.get_width() for c in otherColumns)
newWidth -= treeview.style_get_property("horizontal-separator") * 2
if cell.props.wrap_width == newWidth or newWidth <= 0:
return
cell.props.wrap_width = newWidth
store = treeview.get_model()
iter = store.get_iter_first()
while iter and store.iter_is_valid(iter):
store.row_changed(store.get_path(iter), iter)
iter = store.iter_next(iter)
treeview.set_size_request(0,-1)
treeview.connect_after("size-allocate", callback, column, cell)
Profit. Thank you PyChess developers.
Having recently uncovered the following gem in nearly productive code I wanted to make sure it was documented on the web in the hopes that if I google for this at some later point in time, this post will show up.
One of our applications at work was being randomly hit by the Linux OOM killer. Some tests, some googling and some consulting of passers-by revealed an unsuspected cause: Runtime.getRuntime().exec(), the canonical way to execute external processes in Java, makes your own process require double the memory for a very small period of time. Long enough for the OS to notice and to take action if so required, for example if you hit the maximum amount of memory user space processes are allocated. Since we run on an embedded platform this limit is rather lower than on your typical server.
Doubling the amount of memory required is a result of Sun having implemented Runtime.exec() by calling the POSIX fork() method followed by exec(). fork() copies the parent process’ address space. Sun documents this behavior indirectly in a document titled Minimizing Memory Usage for Creating Application Subprocesses, but sadly does not offer a real solution for Linux users. The seemingly obvious option of using the alternative fork implementation called vfork() is rejected by Sun (and others) due to concerns over deadlock issues.
In the short term we are therefore left with the following nasty workaround: use a separate process running alongside our application that listens on a socket and does nothing but spawn external processes. In the long term we will try to factor out these usages of Runtime.exec() and replace them with pure Java implementations.
Bah.
Tags: java, linux, tips | Comments (4)