darkpbj
darkpbj

Reputation: 2992

Prevent a listener from triggering itself

My issue today involves a simple contention in a JFace TreeViewer Composite. I'm trying to attach a ControlListener to the columns of my tree to enforce a minimum width. To do this, I'm watching every time that the column is resized and if the new width is too small, I impose the minimum onto it.

This is a GUI issue, but really it's something that could happen in any Java environment with a modification listener. I figured maybe some of you Java geeks out there might have fun with it.

    public static void getSizeControlListener(final TreeColumn column, final int minSize) {
        column.addControlListener(new ControlListener() {
            @Override
            public void controlMoved(ControlEvent e) {}

            @Override
            public void controlResized(ControlEvent e) {
                if(column.getWidth()<minSize) {
                    column.setWidth(minSize);
                }
            }
    });

One solution that works is to add a flag that gets set on entrance that any nested calls can reference and immediately exit if necessary. It works, but it's dirty and ugly.

    public static void getSizeControlListener(final TreeColumn column, final int minSize) {
        column.addControlListener(new ControlListener() {

            private boolean isRunning;

            @Override
            public void controlMoved(ControlEvent e) {}

            @Override
            public void controlResized(ControlEvent e) {
                if(isRunning)
                    return;
                isRunning = true;
                if(column.getWidth()<minSize) {
                    column.setWidth(minSize);
                }
                isRunning = false
            }
    });

Upvotes: 1

Views: 157

Answers (2)

Peter Walser
Peter Walser

Reputation: 15706

Your solution with the flag is totally ok, we use this pattern regularly to prevent notification cascades.
One example when such cascades occur is when synchronizing model-view states in MVC. Using such a flag allows us to realize cascade-free unidirectional updates with bidirectionaly synchronization.

The only difference to your implementation is that we use try..finally to make sure the flag is always reset (also when an exception occurs):

if (updating) {
    return;
}
try {
   updating=true;

   // do stuff

} finally {
   updating=false;
}

Upvotes: 1

sambi reddy
sambi reddy

Reputation: 3085

I think you should put below code in org.eclipse.swt.widgets.Display.asyncExec(Runnable)

column.setWidth(minSize);

Upvotes: 0

Related Questions