Mark S. Miller writes:
>When I run Elmer under Symantec Cafe, everything seems fine. When I run it
>directly using jre.exe, or equivalently, from the installed icon,
>everything works fine except that copy doesn't put anything on the
>clipboard. It doesn't seem to matter whether copy is invoked by Ctrl-C or
>by menu. I already made sure both were using the same swing .jar file.
>Since the bug only happens when I can't examine it...
>
>Has anyone else been seeing similar problems? Under what conditions?
I've been developing an app with Swing and also noticed a problem with X and the clipboard. I'm using the blackdown.org Linux/x86 port of JDK-1.1.7. Within the app, copy and paste work fine, but it neither seems to catch copies from the "outside world" nor does copying within the app affect the "outside world".
(Note: stop reading now if all you want out of this list is E discussion, especially if you're not in the mood for minor heresy.)
This isn't directly about E, but I thought I'd share a little bit about the design of my app. One of the pieces is a toolkit consisting of interfaces and events, and a couple of base classes, somewhat along the line of AWT/Swing (but not for anything having to do directly with graphics), but with a couple innovations. As most of you probably know, event-style programming and asynch messaging-style programming are fairly similar when you get right down to it. What I've come up with is my "happy medium". I don't think I have the time (or patience) to go into all the details, but I'll give a quick (and somewhat simplified) example of what I've done:
interface Entity /* how many synonyms of Object are there? */ {
void addListener (EventListener l);
void removeListener (EventListener l);
}
abstract class BaseEvent
extends java.util.Event
{
public abstract void sendTo (java.util.EventListener l); }
interface Foo
extends Entity
{
...
}
class FooEvent
extends BaseEvent
{
private FooEvent (Foo source, ...) { ... }
public void sendTo (java.util.EventListener l) { ... }
static FooEvent interestingThing (Foo source, ...) { ... }
static FooEvent somethingElse (Foo source, ...) { ... }
...
interface FooListener
extends java.util.EventListener
{
void interestingThing (FooEvent event);
void somethingElse (FooEvent event);
}
The salient aspects are: 1) All objects that send events have a single add/removeListener interface. 2) For the most part, you can tell the class of event that anything sends by adding "Event" to the name of the interface(s) it implements. 3) You know what interface to implement if you care about listening to such events by replacing "Event" with "Listener". 4) An event is made *only* by using static (and well checked) methods on the event class. 5) The listener method name for an event has the same name as the name of the static method to create that event (on the event class).
In this model, listeners aren't supposed to throw exceptions, but if they do, it's legit to just drop them on the floor (although in debug mode it'll spit them to System.err). Also, listeners aren't supposed to take long to execute their code, but there's not much enforcement there either. Horrible as it may seem, you still have to be careful with multi-thread access to objects. And, you still have to do a bit of (error-prone) copy/paste work to get all the event and listener methods named and dispatched appropriately. It's a bit like manually constructing method dispatch tables and deflectors.
All of this is leading to a very simple comment: The above design wasn't too hard to develop, isn't too onerous to write code for, and Java didn't get in the way of its implementation very much. And, despite its imperfections, it does seem to work reasonably well (admittedly, for a non-distributed app, but one which *does* do asynchronous comm). There have certainly been times that I've just wanted to write a "<-" and be done with it, but, somewhat surprisingly, those moments have been fairly infrequent.
Before writing this app, I was a bit unsure about how it would be to *really* program in Java, as opposed to the keep-my-nose-pinched paradigm which I'd practiced in the past (both at EC and on the demo/prototype for my "real" job). My current opinion is that it's still a pain in the ass, and it's harder than it ought to be, but it *is* sufficiently useful, even without a lot of new library support. (The utility/base classes to support my event model are only a few hundred lines of code.)
Okay, I'll stop being heretical now and tell you what the program actually does.
(Note: stop reading now if you don't care about the particulars of the app.)
The app in question is called UberChat, and its origin is in me getting frustrated with all the really bad text chat interfaces that are out there, and the fact that all chat clients I've ever seen only handle one protocol. I know that IRC sucks as a protocol and is insecure, blah blah blah, but the fact is, I have a friend that runs a private IRC server, and I want to access it. I also have a group of friends that hang out on an ICB server, and I want to play there too. And I have a few friends on The SpaceBar, etc. Anyway, I'm not trying to force these guys to shut down their servers to run something better, merely trying to make the interface on my end tolerable.
I've been working on this in the bit of spare time I've found myself having, since the demo/prototype for my "real" work is stable, but we still aren't funded. Rather than twiddle my thumbs and tweak the demo (which won't get us any closer to funding), I decided it was time to do UberChat, something I'd thought of doing for quite a while. Also, I had the realization recently that I don't really have a significant system that I've done post-college that I'm not NDA-obliged not to show off.
My goal for the 1.0 release is to handle three fairly different server protocols and have both graphical and text console UIs. Right now, I've got two protocols *mostly* done (ICB and "spacebar"), have a working but incomplete GUI, and have a used-to-work-but-is-now-out-of-date and butt-ugly console UI. As those of you who know my past work can probably surmise, I've paid very careful attention to keeping the different pieces of the system fairly carefully separated. The system is (mostly) cleanly divided into:
0. Independent utility classes/packages
I've been making a couple pre-releases of this per week or so for about the last month, but I've been fairly quiet about it, since it still needs lots of work before I'm ready for the masses to bang on it. However, I trust the members of this list to be sophisticated enough to understand what it means to be a pre-pre-pre-alpha piece of software. That being said, you can find a screen-shot at:
http://www.milk.com/dropoff/uberdump.gif
and you can find the latest distribution (as of this writing) at:
http://www.milk.com/dropoff/uberchat-0.9.tar.gz
The distribution includes (well-commented) source, jar file, run script, javadoc files, and a couple info files. Feel free to snarf it and have a look.
-dan, breaking his silence for a moment