Re: Losing controlListeners when display is rebuilt

I found the "problem", so this is for the archives:

ProjectionControl is different from the other "unique"
Display centric controls (GraphicsModeControl,
RendererControl).  When you add a ScalarMap to
XAxis, YAxis, ZAxis, Latitude, Longitude or Radius,
the control for that ScalarMap is the ProjectionControl
of the display.  So when the ScalarMaps are removed,
you screw up any listeners on the ProjectionControl.
So, if you add a ControlListener to the ProjectionControl
of a Display, make sure you add a DisplayListener to that
display to listen for DisplayEvent.MAPS_CLEARED so you can
re-add the listener.

Don

Don Murray wrote:



Bill Hibbard wrote:


Not a bug, just the way it works. The DisplayImpl.clearMaps()
call clears up everything (it is desireable to have a method
that clears up everything - the bug would be to find something
that is not cleared up).




Then this works differently than the other unique controls in a
Display. I mispoke in my previous message.  ProjectionControl
does act differently from GraphicsModeControl and RendererControl.
If I add ControlListeners to these two controls, when I rebuild
the display I do not lose my listeners, as I would expect should
happen since these controls are only created once and nothing
in clearMaps removes ControlListeners (other than the DisplayMonitor)
from a control.  So, clearMaps does not really "clear up everything".
That being the case, I would think that
either ProjectionControl should not remove it's listeners, or
that GraphicsModeControl and RendererControl should for
consistency.  Since they are unique controls, I think
ProjectionControl should retain it's listeners.  The only thing
that should clear out all listeners for a control is calling
Control.nullControl() and the only thing that does this is
ScalarMap.  Since ProjectionControl is not related to any
ScalarMap (i.e. it's not gotten by ScalarMap.getControl()),
I don't see why its listeners are cleared or stop working
upon a rebuild.

It is good to have a method to clear everything up, as long
as it actually does that.  Since GraphicsModeControl and
RendererControl don't get cleared up, then I'd maintain that
there is a bug in there somewhere.

 >The work-around is to re-add the
 > ControlListerner after rebuilding the display.

So in addition to a ControlListener, I have to add a DisplayListener
to listen for MAPS_CLEARED and then guess which ones got added
back and which ones didn't?

I've attached a modified version of PCTest that shows the
inconsistent behavior between these unique controls.


Don


------------------------------------------------------------------------

import visad.*;
import visad.java3d.*;
import visad.java2d.*;
import visad.data.mcidas.BaseMapAdapter;
import javax.swing.*;
import java.util.Vector;
import java.awt.event.*;

public class PCTest extends JFrame {

    DisplayImpl display;
    DataReference mapRef;

    public PCTest() {

        try {
           addWindowListener(new WindowAdapter() {
               public void windowClosing(WindowEvent we) {
                   System.exit(0);
               }
           });
           display = new DisplayImplJ3D("display");
           makeControlListener(display.getGraphicsModeControl());
           makeControlListener(display.getProjectionControl());
           makeControlListener(
             display.getDisplayRenderer().getRendererControl());

           display.addMap(
              new ScalarMap(RealType.Latitude, Display.YAxis));
           display.addMap(
              new ScalarMap(RealType.Longitude, Display.XAxis));
           display.addMap(
              new ScalarMap(RealType.Altitude, Display.ZAxis));
           BaseMapAdapter bma = new BaseMapAdapter("OUTLUSAM");
           mapRef = new DataReferenceImpl("map");
           mapRef.setData(bma.getData());
           display.addReference(mapRef);
           getContentPane().add(display.getComponent());
           JPanel p = new JPanel();
           JCheckBox scale = new JCheckBox("Scale On", false);
           scale.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent be) {
                 try {
                   display.getGraphicsModeControl().setScaleEnable(
                     ((JCheckBox)be.getSource()).isSelected());
                 } catch (Exception e) {
                    e.printStackTrace();
                 }
               }
           });
           p.add(scale);
           JCheckBox color = new JCheckBox("White Background", false);
           color.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent be) {
                 try {
RendererControl r = display.getDisplayRenderer().getRendererControl();
                   if (((JCheckBox)be.getSource()).isSelected()) {
                      r.setBackgroundColor(1.f, 1.f, 1.f);
                      r.setForegroundColor(0.f, 0.f, 0.f);
                   } else {
                      r.setBackgroundColor(0.f, 0.f, 0.f);
                      r.setForegroundColor(1.f, 1.f, 1.f);
                   }
                 } catch (Exception e) {
                    e.printStackTrace();
                 }
               }
           });
           p.add(color);
           getContentPane().add("North", p);
           JButton rebuild = new JButton("Rebuild Display");
           rebuild.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent ae) {
                   rebuildDisplay();
               }
           });
           getContentPane().add("South", rebuild);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void makeControlListener(Control c) {
        try {
           c.addControlListener(new ControlListener() {
               public void controlChanged(ControlEvent e) {
System.out.println("PC: got event: " + e + " from instance " +
                    ((Control) e.getControl()).getClass().getName());
                    //((Control) e.getControl()).getInstanceNumber());
               }
           });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void rebuildDisplay() {
        try {
            Vector maps = display.getMapVector();
            display.removeAllReferences();
            display.clearMaps();
            for (int i = 0; i < maps.size(); i++) {
                display.addMap((ScalarMap) maps.get(i));
            }
            display.addReference(mapRef);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        PCTest pc = new PCTest();
        pc.pack();
        pc.setVisible(true);
    }
}