Pattern for popup menu management?

Yes, this is a GUI-specific design question, but I'm more interested in the general pattern.

My basic question: who should own the construction and management of popup menus ("context menus") for a given component?

A. The enclosing JFrame, or something at that level.

B. The enclosing component (e.g. a JTree, or a JList, or a JTable, or...).

C. The object--or GUI-specific wrapped object, such as a special kind of TreeNode, or table cell, or...--that is displayed by the enclosing component.

D. Something else.

My original post is over in the Swing forum, and can be referenced here: http://forum.java.sun.com/thread.jsp?forum=57&thread=366179&tstart=0&trange=15

If anyone has any ideas, I'd appreciate your insights.

Cheers,

Laird

[808 byte] By [ljnelsona] at [2007-9-28 13:19:00]
# 1

Well, all of your listed options are viable, it really depends on how re-usable you want your solution to be...

Let's take a few different examples.

1) JFrame based - What you can do here is when a popup is activated from anywhere within the frame you identify the component under the mouse at that time and go to some resource to identify the different actions that can be taken for that component (or possibly base the actions on a component/frame combination). If you went this route I could make an argument for this being an implementation of the "Decorator" pattern, or the Visitor pattern (roughly speaking).

2) JComponent based. Create an interface called "IActionable" (or something like that) that allows you to 1) define a list of action names, and 2) a method that you can invoke a specific action by passing in the name:

interface IActionable {

// Returns a string array of the actions this component can perform

public String [] getActions();

// Invokes the named action

public void invokeAction(String actionName);

}

Then implement this interface on any JComponents you want to have display a context menu. You'll have to wire up the popup menu generation yourself. As far as patterns are concerned - Mediator, Visitor (kinda/sorta)

3) You COULD create something like example #2, but using the underlying models of the JComponents. I would caution against this approach since most popup menus tend to be UI centric in the logic they support (cut, paste, etc) and when you are dealing with the underlying models you are getting closer to the business logic world.

Now if you are looking to do something more business logic centric (save, cancel, post, etc), here is a cool little alternative:

On your underlying business object (take an Invoice as an example) you create a number of "Actions" (See the Command pattern for details). Give the ability to request the actions that a given BO supports. Then, whenever you have a JPanel / JFrame that references a specific BO, have it query the BO for the actions it supports when you create the popup. Click on an item, and that action is invoked in the BO.

Note: There is a lot of little implementation details absent from the last idea - it assumes things like you have a separation between presentation and BO logic, you are "binding" UI components to the underlying BO in some generic fashion (i.e. a Proxy), etc.

Does this help at all? I could make an equally strong argument for any of these implementations - it really depends on how the rest of your application is designed.

Jonathan House

jonathanhousea at 2007-7-12 9:15:21 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

> 3) You COULD create something like example #2, but

> using the underlying models of the JComponents.

You're now the second person to suggest this approach. I'll think about doing it this way. For what it's worth, I'm looking to support a mix of "textish" and business-oriented actions.

I'm still kind of irked that all my solutions, and yours, and other people's, go against the grain of encapsulation: my brain still stubbornly wants the JTable or the JTree to manage the popup entirely, because that Just Seems Like The Right Object-Oriented Thing To Do. You know, so that the interaction is like this:

JFrame: Hey, Tree, I'm assembling the GUI. Go install yourself.

JTree: Right. Will do. OK, so, we've got a TreeModel, and I know how to lay that out...OK, next is the popup menu; yep, got that...OK, JFrame, I'm done. I'll respond to the events that I'm supposed to respond to.

JFrame: Great. OK, OS, I'm done. Let's go.

Instead, the interaction, regardless of solution, ends up from everyone's suggestions (and my own ideas) being something like this:

JFrame: OK, building the GUI. Step one is to create a JTree. OK, insert tab A into slot B...OK. Next, I need to install a handler into the tree so that when the mouse is over the tree and the right button is clicked, I will show a popup menu as though it were coming from the tree itself. Right. So that handler will need to [much detailed **** involving the innards of the JTree and its interaction with MouseListeners and the like omitted]

JFrame: [some time later] Wow, that was exhausting. OK, on to the JList, where I have to do the same thing [more detailed **** involving the innards of the JList and so on omitted]

> Now if you are looking to do something more business

> logic centric (save, cancel, post, etc), here is a

> cool little alternative:

(I am.)

> On your underlying business object (take an Invoice as

> an example) you create a number of "Actions" (See the

> Command pattern for details). Give the ability to

> request the actions that a given BO supports. Then,

> whenever you have a JPanel / JFrame that references a

> specific BO, have it query the BO for the actions it

> supports when you create the popup. Click on an item,

> and that action is invoked in the BO.

Yeah; others have suggested this as well. But what if the underlying business object should be able to do different things based on how it's represented in the GUI? And in what order should the actions be added to the popup menu? Who makes that call? What about stupid layout details of the popup menu, like separators and icons and all that happy silliness?

I think what I'm taking away from your good suggestions (and those of others in the other thread) is that--very surprisingly to me--everyone does this extremely common thing (context-sensitive popup menus) very differently. I had thought that perhaps there was one way to do it, or at least a generally accepted way. I'll probably look at what people have suggested and roll my own hybrid.

Thanks very much for your feedback.

Cheers,

Laird

ljnelsona at 2007-7-12 9:15:21 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

>I'm still kind of irked that all my solutions, and yours, and other >people's, go against the grain of encapsulation: my brain still >stubbornly wants the JTable or the JTree to manage the popup entirely, >because that Just Seems Like The Right Object-Oriented Thing To Do. >You know, so that the interaction is like this:

That is why good design is an art, and not a science. I feel the same way myself at times - where you draw the boundaries of encapsulation is one of my favorite arguments in design sessions.

>Yeah; others have suggested this as well. But what if the underlying >business object should be able to do different things based on how >it's represented in the GUI?

Strictly speaking, it shouldn't behave differently based on the UI alone. Usually there is a different factor that will affect how the BO behaves (like permissions for a specific users), so it still makes sense for the UI to determine what "actions" can be taken depending on the "state" of the BO.

Of course, this is only true if you are really adamant about maintaining a clear separation of UI logic and business logic. Needless to say, this is tough to do, and not too many teams take the time to make it work.

It's interesting that there were similar ideas from that other thread (I didn't read it before responding here). I guess I'll saunter over and see what they had to say there...

Jonathan House

jonathanhousea at 2007-7-12 9:15:21 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

> > Yeah; others have suggested this as well. But what if

> > the underlying business object should be able to do

> > different things based on how it's represented in the

> > GUI?

>

> Strictly speaking, it shouldn't behave differently

> based on the UI alone.

Right; my mistake--I meant the particular UI view of said object. For example, you might want a File object that shows up in a list to have a Move Up or Move Down MenuItem in its popup, whereas you don't want it to have such a thing when it's shown as an Icon. (There are obviously solutions that get around this and preserve your suggestion's import.)

> Of course, this is only true if you are really adamant

> about maintaining a clear separation of UI logic and

> business logic. Needless to say, this is tough to do,

> and not too many teams take the time to make it work.

Fortunately, (a) this is a side project for me, (b) I am always adamant about business logic and UI separation, and (c) I have no deadline. :-) I'm just interested in finding a paradigm that I hope I can cart to my next project without having to go through this exploratory process.

Thanks again for your feedback.

Cheers,

Laird

ljnelsona at 2007-7-12 9:15:21 > top of Java-index,Other Topics,Patterns & OO Design...