Ignore:
Timestamp:
2010-01-17T16:37:24+01:00 (14 years ago)
Author:
jttt
Message:

Partially fix situation after last layer removal - most objects still stay in memory but at least there are less references and forgotten listeners

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MapStatus.java

    r2869 r2871  
    6969     */
    7070    final MapView mv;
     71    final Collector collector;
    7172
    7273    /**
     
    143144         */
    144145        public void run() {
    145             for (;;) {
    146 
    147                 MouseState ms = new MouseState();
    148                 synchronized (this) {
    149                     try {wait();} catch (InterruptedException e) {}
    150                     ms.modifiers = mouseState.modifiers;
    151                     ms.mousePos = mouseState.mousePos;
    152                 }
    153                 if (parent != Main.map)
    154                     return; // exit, if new parent.
    155 
    156                 // Do nothing, if required data is missing
    157                 if(ms.mousePos == null || mv.center == null) {
    158                     continue;
    159                 }
    160 
    161                 // Freeze display when holding down CTRL
    162                 if ((ms.modifiers & MouseEvent.CTRL_DOWN_MASK) != 0) {
    163                     // update the information popup's labels though, because
    164                     // the selection might have changed from the outside
    165                     popupUpdateLabels();
    166                     continue;
    167                 }
    168 
    169                 // This try/catch is a hack to stop the flooding bug reports about this.
    170                 // The exception needed to handle with in the first place, means that this
    171                 // access to the data need to be restarted, if the main thread modifies
    172                 // the data.
    173                 try {
    174                     // Set the text label in the bottom status bar
    175                     statusBarElementUpdate(ms);
    176 
    177                     // The popup != null check is required because a left-click
    178                     // produces several events as well, which would make this
    179                     // variable true. Of course we only want the popup to show
    180                     // if the middle mouse button has been pressed in the first
    181                     // place
    182                     boolean isAtOldPosition = (oldMousePos != null
    183                             && oldMousePos.equals(ms.mousePos)
    184                             && popup != null);
    185                     boolean middleMouseDown = (ms.modifiers & MouseEvent.BUTTON2_DOWN_MASK) != 0;
    186 
    187                     // Popup Information
    188                     // display them if the middle mouse button is pressed and
    189                     // keep them until the mouse is moved
    190                     if (middleMouseDown || isAtOldPosition)
    191                     {
    192                         Collection<OsmPrimitive> osms = mv.getAllNearest(ms.mousePos);
    193 
    194                         if (osms == null) {
    195                             continue;
     146            registerListeners();
     147            try {
     148                for (;;) {
     149
     150                    MouseState ms = new MouseState();
     151                    synchronized (this) {
     152                        // TODO Would be better if the timeout wasn't necessary
     153                        try {wait(1000);} catch (InterruptedException e) {}
     154                        ms.modifiers = mouseState.modifiers;
     155                        ms.mousePos = mouseState.mousePos;
     156                    }
     157                    if (parent != Main.map)
     158                        return; // exit, if new parent.
     159
     160                    // Do nothing, if required data is missing
     161                    if(ms.mousePos == null || mv.center == null) {
     162                        continue;
     163                    }
     164
     165                    // Freeze display when holding down CTRL
     166                    if ((ms.modifiers & MouseEvent.CTRL_DOWN_MASK) != 0) {
     167                        // update the information popup's labels though, because
     168                        // the selection might have changed from the outside
     169                        popupUpdateLabels();
     170                        continue;
     171                    }
     172
     173                    // This try/catch is a hack to stop the flooding bug reports about this.
     174                    // The exception needed to handle with in the first place, means that this
     175                    // access to the data need to be restarted, if the main thread modifies
     176                    // the data.
     177                    try {
     178                        // Set the text label in the bottom status bar
     179                        statusBarElementUpdate(ms);
     180
     181                        // The popup != null check is required because a left-click
     182                        // produces several events as well, which would make this
     183                        // variable true. Of course we only want the popup to show
     184                        // if the middle mouse button has been pressed in the first
     185                        // place
     186                        boolean isAtOldPosition = (oldMousePos != null
     187                                && oldMousePos.equals(ms.mousePos)
     188                                && popup != null);
     189                        boolean middleMouseDown = (ms.modifiers & MouseEvent.BUTTON2_DOWN_MASK) != 0;
     190
     191                        // Popup Information
     192                        // display them if the middle mouse button is pressed and
     193                        // keep them until the mouse is moved
     194                        if (middleMouseDown || isAtOldPosition)
     195                        {
     196                            Collection<OsmPrimitive> osms = mv.getAllNearest(ms.mousePos);
     197
     198                            if (osms == null) {
     199                                continue;
     200                            }
     201
     202                            final JPanel c = new JPanel(new GridBagLayout());
     203                            final JLabel lbl = new JLabel(
     204                                    "<html>"+tr("Middle click again to cycle through.<br>"+
     205                                    "Hold CTRL to select directly from this list with the mouse.<hr>")+"</html>",
     206                                    null,
     207                                    JLabel.HORIZONTAL
     208                            );
     209                            lbl.setHorizontalAlignment(JLabel.LEFT);
     210                            c.add(lbl, GBC.eol().insets(2, 0, 2, 0));
     211
     212                            // Only cycle if the mouse has not been moved and the
     213                            // middle mouse button has been pressed at least twice
     214                            // (the reason for this is the popup != null check for
     215                            // isAtOldPosition, see above. This is a nice side
     216                            // effect though, because it does not change selection
     217                            // of the first middle click)
     218                            if(isAtOldPosition && middleMouseDown) {
     219                                // Hand down mouse modifiers so the SHIFT mod can be
     220                                // handled correctly (see funcion)
     221                                popupCycleSelection(osms, ms.modifiers);
     222                            }
     223
     224                            // These labels may need to be updated from the outside
     225                            // so collect them
     226                            List<JLabel> lbls = new ArrayList<JLabel>();
     227                            for (final OsmPrimitive osm : osms) {
     228                                JLabel l = popupBuildPrimitiveLabels(osm);
     229                                lbls.add(l);
     230                                c.add(l, GBC.eol().fill(GBC.HORIZONTAL).insets(2, 0, 2, 2));
     231                            }
     232
     233                            popupShowPopup(popupCreatePopup(c, ms), lbls);
     234                        } else {
     235                            popupHidePopup();
    196236                        }
    197237
    198                         final JPanel c = new JPanel(new GridBagLayout());
    199                         final JLabel lbl = new JLabel(
    200                                 "<html>"+tr("Middle click again to cycle through.<br>"+
    201                                 "Hold CTRL to select directly from this list with the mouse.<hr>")+"</html>",
    202                                 null,
    203                                 JLabel.HORIZONTAL
    204                         );
    205                         lbl.setHorizontalAlignment(JLabel.LEFT);
    206                         c.add(lbl, GBC.eol().insets(2, 0, 2, 0));
    207 
    208                         // Only cycle if the mouse has not been moved and the
    209                         // middle mouse button has been pressed at least twice
    210                         // (the reason for this is the popup != null check for
    211                         // isAtOldPosition, see above. This is a nice side
    212                         // effect though, because it does not change selection
    213                         // of the first middle click)
    214                         if(isAtOldPosition && middleMouseDown) {
    215                             // Hand down mouse modifiers so the SHIFT mod can be
    216                             // handled correctly (see funcion)
    217                             popupCycleSelection(osms, ms.modifiers);
    218                         }
    219 
    220                         // These labels may need to be updated from the outside
    221                         // so collect them
    222                         List<JLabel> lbls = new ArrayList<JLabel>();
    223                         for (final OsmPrimitive osm : osms) {
    224                             JLabel l = popupBuildPrimitiveLabels(osm);
    225                             lbls.add(l);
    226                             c.add(l, GBC.eol().fill(GBC.HORIZONTAL).insets(2, 0, 2, 2));
    227                         }
    228 
    229                         popupShowPopup(popupCreatePopup(c, ms), lbls);
    230                     } else {
    231                         popupHidePopup();
     238                        oldMousePos = ms.mousePos;
     239                    } catch (ConcurrentModificationException x) {
     240                        //x.printStackTrace();
     241                    } catch (NullPointerException x) {
     242                        //x.printStackTrace();
    232243                    }
    233 
    234                     oldMousePos = ms.mousePos;
    235                 } catch (ConcurrentModificationException x) {
    236                     //x.printStackTrace();
    237                 } catch (NullPointerException x) {
    238                     //x.printStackTrace();
    239                 }
     244                }
     245            } finally {
     246                unregisterListeners();
    240247            }
    241248        }
     
    496503    MouseState mouseState = new MouseState();
    497504
     505    private AWTEventListener awtListener = new AWTEventListener() {
     506        public void eventDispatched(AWTEvent event) {
     507            if (event instanceof ComponentEvent &&
     508                    ((ComponentEvent)event).getComponent() == mv) {
     509                synchronized (collector) {
     510                    mouseState.modifiers = ((InputEvent)event).getModifiersEx();
     511                    if (event instanceof MouseEvent) {
     512                        mouseState.mousePos = ((MouseEvent)event).getPoint();
     513                    }
     514                    collector.notify();
     515                }
     516            }
     517        }
     518    };
     519
     520    private MouseMotionListener mouseMotionListener = new MouseMotionListener() {
     521        public void mouseMoved(MouseEvent e) {
     522            synchronized (collector) {
     523                mouseState.modifiers = e.getModifiersEx();
     524                mouseState.mousePos = e.getPoint();
     525                collector.notify();
     526            }
     527        }
     528
     529        public void mouseDragged(MouseEvent e) {
     530            mouseMoved(e);
     531        }
     532    };
     533
     534    private KeyAdapter keyAdapter = new KeyAdapter() {
     535        @Override public void keyPressed(KeyEvent e) {
     536            synchronized (collector) {
     537                mouseState.modifiers = e.getModifiersEx();
     538                collector.notify();
     539            }
     540        }
     541
     542        @Override public void keyReleased(KeyEvent e) {
     543            keyPressed(e);
     544        }
     545    };
     546
     547    private void registerListeners() {
     548        // Listen to keyboard/mouse events for pressing/releasing alt key and
     549        // inform the collector.
     550        try {
     551            Toolkit.getDefaultToolkit().addAWTEventListener(awtListener,
     552                    AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
     553        } catch (SecurityException ex) {
     554            mv.addMouseMotionListener(mouseMotionListener);
     555            mv.addKeyListener(keyAdapter);
     556        }
     557    }
     558
     559    private void unregisterListeners() {
     560        try {
     561            Toolkit.getDefaultToolkit().removeAWTEventListener(awtListener);
     562        } catch (SecurityException e) {
     563            // Don't care, awtListener probably wasn't registered anyway
     564        }
     565        mv.removeMouseMotionListener(mouseMotionListener);
     566        mv.removeKeyListener(keyAdapter);
     567    }
     568
     569
    498570    /**
    499571     * Construct a new MapStatus and attach it to the map view.
     
    502574    public MapStatus(final MapFrame mapFrame) {
    503575        this.mv = mapFrame.mapView;
     576        this.collector = new Collector(mapFrame);
    504577
    505578        JumpToAction JumpToAct = new JumpToAction();
     
    539612
    540613        // The background thread
    541         final Collector collector = new Collector(mapFrame);
    542614        thread = new Thread(collector, "Map Status Collector");
    543615        thread.setDaemon(true);
    544616        thread.start();
    545 
    546         // Listen to keyboard/mouse events for pressing/releasing alt key and
    547         // inform the collector.
    548         try {
    549             Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener(){
    550                 public void eventDispatched(AWTEvent event) {
    551                     if (event instanceof ComponentEvent &&
    552                             ((ComponentEvent)event).getComponent() == mapFrame.mapView) {
    553                         synchronized (collector) {
    554                             mouseState.modifiers = ((InputEvent)event).getModifiersEx();
    555                             if (event instanceof MouseEvent) {
    556                                 mouseState.mousePos = ((MouseEvent)event).getPoint();
    557                             }
    558                             collector.notify();
    559                         }
    560                     }
    561                 }
    562             }, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
    563         } catch (SecurityException ex) {
    564             mapFrame.mapView.addMouseMotionListener(new MouseMotionListener() {
    565                 public void mouseMoved(MouseEvent e) {
    566                     synchronized (collector) {
    567                         mouseState.modifiers = e.getModifiersEx();
    568                         mouseState.mousePos = e.getPoint();
    569                         collector.notify();
    570                     }
    571                 }
    572 
    573                 public void mouseDragged(MouseEvent e) {
    574                     mouseMoved(e);
    575                 }
    576             });
    577 
    578             mapFrame.mapView.addKeyListener(new KeyAdapter() {
    579                 @Override public void keyPressed(KeyEvent e) {
    580                     synchronized (collector) {
    581                         mouseState.modifiers = e.getModifiersEx();
    582                         collector.notify();
    583                     }
    584                 }
    585 
    586                 @Override public void keyReleased(KeyEvent e) {
    587                     keyPressed(e);
    588                 }
    589             });
    590         }
    591617    }
    592618
Note: See TracChangeset for help on using the changeset viewer.