Ignore:
Timestamp:
17.01.2010 16:37:24 (2 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.