1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2019-05-28 14:45:56 -0500 (Tue, 28 May 2019) $ 4 * $Revision: 21972 $ 5 * 6 * Copyright (C) 2003-2005 Miguel, Jmol Development 7 * 8 * Contact: jmol-developers@lists.sf.net, jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 package org.jmol.viewer; 25 26 import org.jmol.script.T; 27 import org.jmol.util.BSUtil; 28 29 import javajs.util.AU; 30 31 32 import org.jmol.api.JmolSelectionListener; 33 import org.jmol.i18n.GT; 34 import javajs.util.BS; 35 import org.jmol.modelset.ModelSet; 36 37 public class SelectionManager { 38 39 private Viewer vwr; 40 41 private JmolSelectionListener[] listeners = new JmolSelectionListener[0]; 42 SelectionManager(Viewer vwr)43 SelectionManager(Viewer vwr) { 44 this.vwr = vwr; 45 } 46 47 final BS bsHidden = new BS(); 48 private final BS bsSelection = new BS(); 49 final BS bsFixed = new BS(); 50 51 public BS bsSubset; 52 public BS bsDeleted; 53 public Boolean noneSelected; 54 55 56 // void deleteModelAtoms(BS bsDeleted) { 57 // BSUtil.deleteBits(bsHidden, bsDeleted); 58 // BSUtil.deleteBits(bsSelection, bsDeleted); 59 // BSUtil.deleteBits(bsSubset, bsDeleted); 60 // BSUtil.deleteBits(bsFixed, bsDeleted); 61 // BSUtil.deleteBits(this.bsDeleted, bsDeleted); 62 // } 63 processDeletedModelAtoms(BS bsAtoms)64 void processDeletedModelAtoms(BS bsAtoms) { 65 BSUtil.deleteBits(bsDeleted, bsAtoms); 66 BSUtil.deleteBits(bsSubset, bsAtoms); 67 BSUtil.deleteBits(bsFixed, bsAtoms); 68 BSUtil.deleteBits(bsHidden, bsAtoms); 69 BS bs = BSUtil.copy(bsSelection); 70 BSUtil.deleteBits(bs, bsAtoms); 71 setSelectionSet(bs, 0); 72 selectionChanged(false); 73 } 74 75 76 // this is a tri-state. the value -1 means unknown 77 private final static int TRUE = 1; 78 private final static int FALSE = 0; 79 private final static int UNKNOWN = -1; 80 private int empty = TRUE; 81 82 boolean hideNotSelected; 83 clear()84 void clear() { 85 clearSelection(true); 86 setSelectionSubset(null); 87 hide(null, null, 0, true); 88 bsDeleted = null; 89 setMotionFixedAtoms(null); 90 } 91 display(ModelSet modelSet, BS bs, int addRemove, boolean isQuiet)92 void display(ModelSet modelSet, BS bs, int addRemove, boolean isQuiet) { 93 switch (addRemove) { 94 default: 95 BS bsNotSubset = (bsSubset == null ? null : BSUtil.andNot(BSUtil.copy(bsHidden), bsSubset)); 96 BS bsAll = modelSet.getModelAtomBitSetIncludingDeleted(-1, false); 97 bsHidden.or(bsAll); 98 if (bsNotSubset != null) { 99 bsHidden.and(bsSubset); 100 bsHidden.or(bsNotSubset); 101 } 102 //$FALL-THROUGH$ 103 case T.add: 104 if (bs != null) 105 bsHidden.andNot(bs); 106 break; 107 case T.remove: 108 if (bs != null) 109 bsHidden.or(bs); 110 break; 111 } 112 BSUtil.andNot(bsHidden, bsDeleted); 113 modelSet.setBsHidden(bsHidden); 114 if (!isQuiet) 115 vwr.reportSelection(GT.i(GT.$("{0} atoms hidden"), bsHidden.cardinality())); 116 } 117 hide(ModelSet modelSet, BS bs, int addRemove, boolean isQuiet)118 void hide(ModelSet modelSet, BS bs, int addRemove, boolean isQuiet) { 119 BS bsNotSubset = (addRemove == 0 || bsSubset == null ? null : BSUtil.andNot(BSUtil.copy(bsHidden), bsSubset)); 120 setBitSet(bsHidden, bs, addRemove); 121 if (bsNotSubset != null) 122 bsHidden.or(bsNotSubset); 123 if (modelSet != null) 124 modelSet.setBsHidden(bsHidden); 125 if (!isQuiet) 126 vwr.reportSelection(GT.i(GT.$("{0} atoms hidden"), bsHidden.cardinality())); 127 } 128 setSelectionSet(BS set, int addRemove)129 void setSelectionSet(BS set, int addRemove) { 130 setBitSet(bsSelection, set, addRemove); 131 empty = UNKNOWN; 132 } 133 setBitSet(BS bsWhat, BS bs, int addRemove)134 private static void setBitSet(BS bsWhat, BS bs, int addRemove) { 135 switch (addRemove) { 136 default: 137 bsWhat.clearAll(); 138 //$FALL-THROUGH$ 139 case T.add: 140 if (bs != null) 141 bsWhat.or(bs); 142 break; 143 case T.remove: 144 if (bs != null) 145 bsWhat.andNot(bs); 146 break; 147 } 148 } 149 getHiddenSet()150 public BS getHiddenSet() { 151 return bsHidden; 152 } 153 getHideNotSelected()154 boolean getHideNotSelected() { 155 return hideNotSelected; 156 } 157 setHideNotSelected(boolean TF)158 void setHideNotSelected(boolean TF) { 159 hideNotSelected = TF; 160 if (TF) 161 selectionChanged(false); 162 } 163 isSelected(int atomIndex)164 public boolean isSelected(int atomIndex) { 165 return (atomIndex >= 0 && bsSelection.get(atomIndex)); 166 } 167 select(BS bs, int addRemove, boolean isQuiet)168 void select(BS bs, int addRemove, boolean isQuiet) { 169 if (bs == null) { 170 selectAll(true); 171 if (!vwr.getBoolean(T.hydrogen)) 172 excludeSelectionSet(vwr.ms.getAtoms(T.hydrogen, null)); 173 if (!vwr.getBoolean(T.hetero)) 174 excludeSelectionSet(vwr.ms.getAtoms(T.hetero, null)); 175 } else { 176 setSelectionSet(bs, addRemove); 177 if (!vwr.getBoolean(T.hydrogen)) 178 excludeSelectionSet(vwr.ms.getAtoms(T.hydrogen, null)); 179 if (!vwr.getBoolean(T.hetero)) 180 excludeSelectionSet(vwr.ms.getAtoms(T.hetero, null)); 181 182 } 183 selectionChanged(false); 184 boolean reportChime = vwr.getBoolean(T.messagestylechime); 185 if (!reportChime && isQuiet) 186 return; 187 int n = getSelectionCount(); 188 if (reportChime) 189 vwr.getChimeMessenger().reportSelection(n); 190 else if (!isQuiet) 191 vwr.reportSelection(GT.i(GT.$("{0} atoms selected"), n)); 192 } 193 selectAll(boolean isQuiet)194 void selectAll(boolean isQuiet) { 195 int count = vwr.ms.ac; 196 empty = (count == 0) ? TRUE : FALSE; 197 for (int i = count; --i >= 0;) 198 bsSelection.set(i); 199 BSUtil.andNot(bsSelection, bsDeleted); 200 selectionChanged(isQuiet); 201 } 202 clearSelection(boolean isQuiet)203 void clearSelection(boolean isQuiet) { 204 setHideNotSelected(false); 205 bsSelection.clearAll(); 206 empty = TRUE; 207 selectionChanged(isQuiet); 208 } 209 isAtomSelected(int atomIndex)210 public boolean isAtomSelected(int atomIndex) { 211 return ( 212 (bsSubset == null || bsSubset.get(atomIndex)) 213 && bsDeleted == null || !bsDeleted.get(atomIndex)) 214 && bsSelection.get(atomIndex); 215 } 216 setSelectedAtom(int atomIndex, boolean TF)217 public void setSelectedAtom(int atomIndex, boolean TF) { 218 if (atomIndex < 0) { 219 selectionChanged(true); 220 return; 221 } 222 if (bsSubset != null && !bsSubset.get(atomIndex) 223 || bsDeleted != null && bsDeleted.get(atomIndex)) 224 return; 225 bsSelection.setBitTo(atomIndex, TF); 226 if (TF) 227 empty = FALSE; 228 else 229 empty = UNKNOWN; 230 } 231 setSelectionSubset(BS bs)232 public void setSelectionSubset(BS bs) { 233 bsSubset = bs; 234 } 235 isInSelectionSubset(int atomIndex)236 boolean isInSelectionSubset(int atomIndex) { 237 return (atomIndex < 0 || bsSubset == null || bsSubset.get(atomIndex)); 238 } 239 invertSelection()240 void invertSelection() { 241 BSUtil.invertInPlace(bsSelection, vwr.ms.ac); 242 empty = (bsSelection.length() > 0 ? FALSE : TRUE); 243 selectionChanged(false); 244 } 245 excludeSelectionSet(BS setExclude)246 private void excludeSelectionSet(BS setExclude) { 247 if (setExclude == null || empty == TRUE) 248 return; 249 bsSelection.andNot(setExclude); 250 empty = UNKNOWN; 251 } 252 253 private final BS bsTemp = new BS(); 254 getSelectionCount()255 public int getSelectionCount() { 256 if (empty == TRUE) 257 return 0; 258 empty = TRUE; 259 BS bs; 260 if (bsSubset == null) { 261 bs = bsSelection; 262 } else { 263 bsTemp.clearAll(); 264 bsTemp.or(bsSubset); 265 bsTemp.and(bsSelection); 266 bs = bsTemp; 267 } 268 int count = bs.cardinality(); 269 if (count > 0) 270 empty = FALSE; 271 return count; 272 } 273 addListener(JmolSelectionListener listener)274 void addListener(JmolSelectionListener listener) { 275 for (int i = listeners.length; --i >= 0;) 276 if (listeners[i] == listener) { 277 listeners[i] = null; 278 break; 279 } 280 int len = listeners.length; 281 for (int i = len; --i >= 0;) 282 if (listeners[i] == null) { 283 listeners[i] = listener; 284 return; 285 } 286 if (listeners.length == 0) 287 listeners = new JmolSelectionListener[1]; 288 else 289 listeners = (JmolSelectionListener[]) AU.doubleLength(listeners); 290 listeners[len] = listener; 291 } 292 selectionChanged(boolean isQuiet)293 private void selectionChanged(boolean isQuiet) { 294 if (hideNotSelected) 295 hide(vwr.ms, BSUtil.copyInvert(bsSelection, vwr.ms.ac), 0, isQuiet); 296 if (isQuiet || listeners.length == 0) 297 return; 298 for (int i = listeners.length; --i >= 0;) 299 if (listeners[i] != null) 300 listeners[i].selectionChanged(bsSelection); 301 } 302 deleteAtoms(BS bs)303 int deleteAtoms(BS bs) { 304 BS bsNew = BSUtil.copy(bs); 305 if (bsDeleted == null) { 306 bsDeleted = bsNew; 307 } else { 308 bsNew.andNot(bsDeleted); 309 bsDeleted.or(bs); 310 } 311 bsHidden.andNot(bsDeleted); 312 bsSelection.andNot(bsDeleted); 313 return bsNew.cardinality(); 314 } 315 getSelectedAtoms()316 BS getSelectedAtoms() { 317 if (bsSubset == null) 318 return bsSelection; 319 BS bs = BSUtil.copy(bsSelection); 320 bs.and(bsSubset); 321 return bs; 322 } 323 getSelectedAtomsNoSubset()324 BS getSelectedAtomsNoSubset() { 325 return BSUtil.copy(bsSelection); 326 } 327 excludeAtoms(BS bs, boolean ignoreSubset)328 public BS excludeAtoms(BS bs, boolean ignoreSubset) { 329 if (bsDeleted != null) 330 bs.andNot(bsDeleted); 331 if (!ignoreSubset && bsSubset != null) 332 (bs = BSUtil.copy(bs)).and(bsSubset); 333 return bs; 334 } 335 setMotionFixedAtoms(BS bs)336 void setMotionFixedAtoms(BS bs) { 337 bsFixed.clearAll(); 338 if (bs != null) 339 bsFixed.or(bs); 340 } 341 getMotionFixedAtoms()342 public BS getMotionFixedAtoms() { 343 return bsFixed; 344 } 345 346 } 347