001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.util; 003 004import java.util.Collection; 005import java.util.Collections; 006import java.util.HashSet; 007import java.util.Iterator; 008import java.util.Set; 009 010import org.openstreetmap.josm.Main; 011import org.openstreetmap.josm.data.osm.DataSet; 012import org.openstreetmap.josm.data.osm.OsmPrimitive; 013import org.openstreetmap.josm.data.osm.Relation; 014 015/** 016 * This class stores the set of highlited primitives and 017 * allows easy and fast change of highlighting 018 */ 019public class HighlightHelper { 020 private final Set<OsmPrimitive> highlightedPrimitives = new HashSet<>(); 021 022 /** 023 * Highlight and remember given primitives 024 * @param prims - primitives to highlight/unhighlight 025 * @return {@code true} if a repaint is needed 026 */ 027 public boolean highlight(Collection<? extends OsmPrimitive> prims) { 028 return highlight(prims, false); 029 } 030 031 /** 032 * Highlight and remember given primitives 033 * @param prims - primitives to highlight/unhighlight 034 * @param only - remove previous highlighting 035 * @return {@code true} if a repaint is needed 036 */ 037 public boolean highlight(Collection<? extends OsmPrimitive> prims, boolean only) { 038 boolean needsRepaint = false; 039 if (only) { 040 Iterator<OsmPrimitive> it = highlightedPrimitives.iterator(); 041 while (it.hasNext()) { 042 OsmPrimitive p = it.next(); 043 if (!prims.contains(p)) { 044 p.setHighlighted(false); 045 it.remove(); 046 needsRepaint = true; 047 } 048 } 049 } 050 for (OsmPrimitive p: prims) { 051 needsRepaint |= setHighlight(p, true); 052 } 053 054 return needsRepaint; 055 } 056 057 /** 058 * Highlight and remember given primitives, forgetting previously highlighted by this instance 059 * @param prims - primitives to highlight/unhighlight 060 * @return {@code true} if a repaint is needed 061 */ 062 public boolean highlightOnly(Collection<? extends OsmPrimitive> prims) { 063 return highlight(prims, true); 064 } 065 066 /** 067 * Highlight and remember given primitive, forgetting previously highlighted by this instance 068 * @param p - primitives to highlight/unhighlight 069 * @return {@code true} if a repaint is needed 070 */ 071 public boolean highlightOnly(OsmPrimitive p) { 072 return highlight(Collections.singleton(p), true); 073 } 074 075 /** 076 * Highlight and remember given primitive 077 * @param p - primitive to highlight/unhighlight 078 * @param flag - true to highlight 079 * @return {@code true} if a repaint is needed 080 */ 081 public boolean setHighlight(OsmPrimitive p, boolean flag) { 082 return setHighlight(p, flag, new HashSet<Relation>()); 083 } 084 085 private boolean setHighlight(OsmPrimitive p, boolean flag, Set<Relation> seenRelations) { 086 if (p instanceof Relation) { 087 Relation r = (Relation) p; 088 seenRelations.add(r); 089 boolean needRepaint = false; 090 for (OsmPrimitive m : r.getMemberPrimitives()) { 091 if (!(m instanceof Relation) || !seenRelations.contains(m)) { 092 needRepaint |= setHighlight(m, flag, seenRelations); 093 } 094 } 095 return needRepaint; 096 } else if (flag) { 097 if (highlightedPrimitives.add(p)) { 098 p.setHighlighted(true); 099 return true; 100 } 101 } else { 102 if (highlightedPrimitives.remove(p)) { 103 p.setHighlighted(false); 104 return true; 105 } 106 } 107 return false; 108 } 109 110 /** 111 * Clear highlighting of all remembered primitives 112 */ 113 public void clear() { 114 for (OsmPrimitive p: highlightedPrimitives) { 115 p.setHighlighted(false); 116 } 117 highlightedPrimitives.clear(); 118 } 119 120 /** 121 * Slow method to import all currently highlighted primitives into this instance 122 */ 123 public void findAllHighlighted() { 124 DataSet ds = Main.main.getCurrentDataSet(); 125 if (ds != null) { 126 highlightedPrimitives.addAll(ds.allNonDeletedPrimitives()); 127 } 128 } 129 130 /** 131 * Slow method to remove highlights from all primitives 132 */ 133 public static void clearAllHighlighted() { 134 DataSet ds = Main.main.getCurrentDataSet(); 135 if (ds != null) { 136 for (OsmPrimitive p: ds.allNonDeletedPrimitives()) { 137 p.setHighlighted(false); 138 } 139 } 140 } 141}