What is the design pattern for GUI menu/toolbar activation

Discussion in 'Java' started by timasmith@hotmail.com, Jun 20, 2006.

  1. Guest

    So suppose you have a complex frame with multiple panels and depending
    on the state of specific controls on the panels - you should enable or
    disable menus and toolbars accordingly.

    Menus have a workaround in that you could perform logic on 'click' -
    but what about toolbars.

    If I select text so copy and cut should be enabled. If a click on a
    node so my delete button should enable.

    I want to avoid polling the entire frames state every second of course.


    Perhaps I could have some kind of property listener for the relevant
    controls that on change changes (de)activates the toolbar - but the
    cut/copy example shows the impracticality of that.

    There must be a design pattern for this...

    Tim
     
    , Jun 20, 2006
    #1
    1. Advertising

  2. Phlip Guest

    timasmith wrote:

    > I want to avoid polling the entire frames state every second of course.


    Observer Pattern, from the book /Design Patterns/. It decouples the target
    from the observer, so neither knows the other's type.

    When you discover that you typically have a triangle of observers, then you
    have Model-View-Controller.

    --
    Phlip
    http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
     
    Phlip, Jun 20, 2006
    #2
    1. Advertising

  3. Chris Uppal Guest

    Phlip wrote:

    > > I want to avoid polling the entire frames state every second of course.

    >
    > Observer Pattern, from the book /Design Patterns/. It decouples the target
    > from the observer, so neither knows the other's type.


    In particular, since you are posting in Java groups, look into the buttons'
    Actions.

    -- chris
     
    Chris Uppal, Jun 20, 2006
    #3
  4. Guest

    Chris Uppal wrote:
    > Phlip wrote:
    >
    > > > I want to avoid polling the entire frames state every second of course.

    > >
    > > Observer Pattern, from the book /Design Patterns/. It decouples the target
    > > from the observer, so neither knows the other's type.

    >
    > In particular, since you are posting in Java groups, look into the buttons'
    > Actions.
    >

    Even within what Java/Swing supplies, there still seems to be a good
    deal of room for various implementations. For instance, if you have
    cut & copy buttons in a toolbar, the chances are they can apply to more
    than one control in your application: you may have text-editing
    controls (JTextComponent derived), and you may also have some other
    sort of object manipulation editor. Usually then the buttons need to
    enabled if and only if some control is focused that can currently
    support the relevant action. Problem is, there isn't really a
    consistent interface to determine when that state may change and how to
    query it. For a JTextComponent, usually you'd want to add a
    CaretListener that sets the Actions' enable status depending on whether
    there is text selected. But there may be other events that cause
    whether text is selected to change, for instance, programmatically
    changing the text on the underlying document, that are not trapped by
    this. For some other sort of control, there may be a rather different
    way of trapping whether the current selection has changed. And then
    you need to way of trapping every time focus is moved from one control
    to another, just in order to determine which control should be
    determining whether the commands are enabled.
    Further more, while there is built-in support for controlling the
    enable status of buttons, the same is not true for the "selected"
    state, i.e. for toggle-style buttons that may reflect attributes of the
    current selection (e.g. the "Bold" button in a word processor).

    I have to say, after spending some time trying to get all this to work
    for me, MFC's command update mechanism, which basically constantly
    refreshes the status of all toolbar buttons every time there is a lull
    in the windows message queue, is a good deal simpler to work with. You
    never have to worry about which listeners to install, and 90% of the
    time it correctly takes care of automatically querying the currently
    focused window/control. I'm actually curious if someone has attempted
    to emulate this in Java - if not, I'm extremely tempted to do so
    myself. I doubt there would be a way to trap "idle" message queue
    events, but even if it works by polling at a fixed interval, it would
    do the job.
     
    , Jun 21, 2006
    #4
  5. Chris Uppal Guest

    wrote:

    > Problem is, there isn't really a
    > consistent interface to determine when that state may change and how to
    > query it. For a JTextComponent, usually you'd want to add a
    > CaretListener that sets the Actions' enable status depending on whether
    > there is text selected. But there may be other events that cause
    > whether text is selected to change, for instance, programmatically
    > changing the text on the underlying document, that are not trapped by
    > this.


    I think the underlying problem here is trying to tie the activation state of
    the Action to overly low-level implementation state. If the Action, say, is a
    Listener itself (which is how I would probably want to set it up) then it
    wouldn't listen to the state of the text component, but to the state of the
    /application/ -- since it's the application which knows whether the
    corresponding operation is applicable at <some instant in time>. Granted that
    that is more work to set up, and may also be foreign to the way some
    programmers think about application structure.


    > I have to say, after spending some time trying to get all this to work
    > for me, MFC's command update mechanism, which basically constantly
    > refreshes the status of all toolbar buttons every time there is a lull
    > in the windows message queue, is a good deal simpler to work with.


    The system (not Java or MFC) I work with most uses that implementation
    technique too. It uses the idea of an "action" (which talks to the
    application, not the low-level components) as above, but doesn't use the
    Observer pattern. It just updates the enabledness (and related aspects) of
    command widgets whenever idle time starts. It's a hack, but it does work well
    in practice -- being simple, reliable, and requiring little maintenance.

    -- chris
     
    Chris Uppal, Jun 21, 2006
    #5
  6. Guest

    Chris Uppal wrote:
    >
    > The system (not Java or MFC) I work with most uses that implementation
    > technique too. It uses the idea of an "action" (which talks to the
    > application, not the low-level components) as above, but doesn't use the
    > Observer pattern. It just updates the enabledness (and related aspects) of
    > command widgets whenever idle time starts. It's a hack, but it does work well
    > in practice -- being simple, reliable, and requiring little maintenance.
    >

    I actually don't see it as a hack at all...it seems exactly the right
    sort of thing to use idle processing for.
    Unfortunately I can't see anyway of doing it portably using standard
    Java - although the AWT toolkit (or more specifically, the singleton
    AWTAutoShutdown object) is notified every time the Windows message
    queue goes idle, there's no way of overriding what happens at this
    point (you can't override creation of the AWTAutoShutdown object to do
    the necessary subclassing). And as for what happens on other platforms,
    who knows.
    Which probably leaves as the only realistic option using a timer, which
    is definitely slightly hackish, but trying to manually keep track of
    every single event that can modify toolbar button state is really not
    feasible (for instance, if someone copies something to the system
    clipboard in another application, your own app's Paste button might get
    disabled if the data format is not supported).
     
    , Jun 22, 2006
    #6
  7. Chris Uppal Guest

    wrote:

    > So suppose you have a complex frame with multiple panels and depending
    > on the state of specific controls on the panels - you should enable or
    > disable menus and toolbars accordingly.


    I happened across this article today while looking for something completely
    unrelated:

    http://www.jot.fm/issues/issue_2004_05/column6

    I have only skimmed it very quickly, but it may have some useful ideas.

    -- chris
     
    Chris Uppal, Jun 22, 2006
    #7
  8. Guest

    Chris Uppal wrote:
    > wrote:
    >
    > > So suppose you have a complex frame with multiple panels and depending
    > > on the state of specific controls on the panels - you should enable or
    > > disable menus and toolbars accordingly.

    >
    > I happened across this article today while looking for something completely
    > unrelated:
    >
    > http://www.jot.fm/issues/issue_2004_05/column6
    >
    > I have only skimmed it very quickly, but it may have some useful ideas.
    >


    Nothing to do with updating the state of toolbar buttons/menu items
    depending on the state of the currently active control etc.

    One comment interests me
    "...what if many components are interested in a text-field action? I
    suggest that if this occurs, we are too tied to the components. That
    text-field should be treated as a controller in a model-view-controller
    design pattern. A control should alter a model. Views that are
    interested in the model should be observing the model, not the
    controller."

    But that doesn't strike me as realistic. For instance, my
    application's primary view allows manipulation of objects such as
    boxes, lines and text-boxes. The "cut", "copy", "paste" and even
    "undo" and "redo" actions while you are working in that view applies to
    whole objects. But you can also click on a text-box object to edit the
    underlying text. Once that becomes the current control, then "cut",
    "copy", "paste", "undo" and "redo" are all handled by the text-editing
    control. I don't see how it could be handled by any sort of "model" in
    the traditional M-V-C pattern. So instead I have to supply code to
    route the actions that each toolbar button fires down to the currently
    active control. And note that detecting the currently active control
    is not completely trivial - the only way I've found of doing it
    reliably is to add a FocusListener to each button, and store a
    reference to the component that previously had the focus. Using the
    ActionEvent source or the KeyboardFocusManager's focus owner don't
    help, as they both point to the actual toolbar button itself.
     
    , Jun 22, 2006
    #8
  9. Chris Uppal Guest

    wrote:

    [me:]
    > > It just updates the enabledness (and related
    > > aspects) of command widgets whenever idle time starts. It's a hack,
    > > but it does work well in practice -- being simple, reliable, and
    > > requiring little maintenance.
    > >

    > I actually don't see it as a hack at all...it seems exactly the right
    > sort of thing to use idle processing for.


    Well, hack or not, I agree that there doesn't seem to be a way to hook idle
    time in Java.


    > Which probably leaves as the only realistic option using a timer, which
    > is definitely slightly hackish,


    <nods sadly/>

    -- chris
     
    Chris Uppal, Jun 23, 2006
    #9
  10. Chris Uppal Guest

    wrote:

    [me:]
    > > http://www.jot.fm/issues/issue_2004_05/column6
    > >
    > > I have only skimmed it very quickly, but it may have some useful ideas.
    > >

    >
    > Nothing to do with updating the state of toolbar buttons/menu items
    > depending on the state of the currently active control etc.


    Ah, well... Apologies for the misdirect, I thought it looked relevant, but
    you are right, it is not.


    > One comment interests me
    > "...what if many components are interested in a text-field action? I
    > suggest that if this occurs, we are too tied to the components. That
    > text-field should be treated as a controller in a model-view-controller
    > design pattern. A control should alter a model. Views that are
    > interested in the model should be observing the model, not the
    > controller."
    >
    > But that doesn't strike me as realistic. For instance, my
    > application's primary view allows manipulation of objects such as
    > boxes, lines and text-boxes. The "cut", "copy", "paste" and even
    > "undo" and "redo" actions while you are working in that view applies to
    > whole objects. But you can also click on a text-box object to edit the
    > underlying text. Once that becomes the current control, then "cut",
    > "copy", "paste", "undo" and "redo" are all handled by the text-editing
    > control. I don't see how it could be handled by any sort of "model" in
    > the traditional M-V-C pattern.


    I agree, but I don't think that sort of event was what the quoted passage was
    referring to. I take it to mean that if we are interested in, say, whether the
    text field contains a valid number, then we should be Observing the state of
    the text field's Model -- if that is a String (or some sort of value holder
    containing a String) which parses as a valid number then other UI elements will
    update themselves accordingly.

    But the specific actions you mention are not Model-related in the MVC sense --
    they are, I think, the responsibility of the Controller. What you have is a
    pattern where you have a sort of generic controller-like object, installed near
    the application's top level, which responds to user input by finding another
    contoller and invoking that controllers' specific cut, paste, or whatever code.
    And....

    > So instead I have to supply code to
    > route the actions that each toolbar button fires down to the currently
    > active control. And note that detecting the currently active control
    > is not completely trivial


    ..... as you note, that isn't too simple.

    (BTW, the non-Java UI system I mentioned before has exactly the same problem
    with buttons and toolbar buttons with invoke actions "for" some other
    component.)

    -- chris

    -- chris
     
    Chris Uppal, Jun 23, 2006
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Marine
    Replies:
    3
    Views:
    23,773
    Marine
    Feb 15, 2006
  2. Pallav singh
    Replies:
    0
    Views:
    415
    Pallav singh
    Jan 22, 2012
  3. Pallav singh
    Replies:
    0
    Views:
    434
    Pallav singh
    Jan 22, 2012
  4. Pallav singh
    Replies:
    1
    Views:
    475
    Peter Remmers
    Jan 22, 2012
  5. pcouas
    Replies:
    0
    Views:
    284
    pcouas
    Feb 19, 2007
Loading...

Share This Page