1 19 20 package org.netbeans.lib.editor.bookmarks.api; 21 22 import java.beans.PropertyChangeListener ; 23 import java.beans.PropertyChangeSupport ; 24 import java.util.ArrayList ; 25 import java.util.List ; 26 import javax.swing.text.Document ; 27 import javax.swing.text.Element ; 28 import org.netbeans.lib.editor.bookmarks.BookmarksApiPackageAccessor; 29 import org.netbeans.lib.editor.bookmarks.BookmarksSpiPackageAccessor; 30 import org.netbeans.lib.editor.bookmarks.spi.BookmarkImplementation; 31 import org.netbeans.lib.editor.bookmarks.spi.BookmarkManager; 32 import org.netbeans.lib.editor.bookmarks.spi.BookmarkManagerFactory; 33 import org.netbeans.lib.editor.bookmarks.spi.BookmarkManagerSupport; 34 import org.openide.util.Lookup; 35 36 42 43 public final class BookmarkList { 44 45 private static BookmarkManagerFactory bookmarkManagerFactory; 46 47 static { 48 BookmarksApiPackageAccessor.register(new ApiAccessor()); 49 BookmarkManagerSupport.initPackageAccess(); 50 } 51 52 public static BookmarkList get(Document doc) { 53 synchronized (org.netbeans.modules.editor.bookmarks.PersistentBookmarks.class) { 54 BookmarkList bookmarkList = (BookmarkList)doc.getProperty(BookmarkList.class); 55 if (bookmarkList == null) { 56 BookmarkManager mgr = getBookmarkManagerFactory().createBookmarkManager(doc); 57 bookmarkList = new BookmarkList(doc, mgr); 58 doc.putProperty(BookmarkList.class, bookmarkList); 59 } 60 return bookmarkList; 61 } 62 } 63 64 private static BookmarkManagerFactory getBookmarkManagerFactory() { 65 if (bookmarkManagerFactory == null) { 66 bookmarkManagerFactory = (BookmarkManagerFactory) 67 Lookup.getDefault().lookup(BookmarkManagerFactory.class); 68 assert (bookmarkManagerFactory != null) : "No BookmarkManagerFactory available"; } 70 return bookmarkManagerFactory; 71 } 72 73 private static final String PROP_BOOKMARKS = "bookmarks"; 74 75 78 private Document doc; 79 80 83 private BookmarkManager manager; 84 85 88 private BookmarkManagerSupport managerSupport; 89 90 93 private List bookmarks; 94 95 private final PropertyChangeSupport PCS = new PropertyChangeSupport (this); 96 97 private BookmarkList(Document doc, BookmarkManager manager) { 98 if (doc == null) { 99 throw new NullPointerException ("Document cannot be null"); } 101 this.doc = doc; 102 this.bookmarks = new ArrayList (); 103 this.manager = manager; 104 this.managerSupport = BookmarksSpiPackageAccessor.get().createBookmarkManagerSupport(this); 105 this.manager.init(managerSupport); 106 } 107 108 113 public Document getDocument() { 114 return doc; 115 } 116 117 122 public int getBookmarkCount() { 123 return bookmarks.size(); 124 } 125 126 134 public Bookmark getBookmark(int index) { 135 return (Bookmark)bookmarks.get(index); 136 } 137 138 148 public Bookmark getNextBookmark(int offset, boolean wrapSearch) { 149 offset++; 150 checkOffsetNonNegative(offset); 151 int index = getBookmarkIndex(offset); 152 return (index < getBookmarkCount()) 153 ? getBookmark(index) 154 : wrapSearch ? getNextBookmark(-1, false) : null; 155 } 156 157 167 public Bookmark getPreviousBookmark(int offset, boolean wrapSearch) { 168 checkOffsetNonNegative(offset); 169 int bookmarkCount = getBookmarkCount(); 170 Bookmark bookmark; if (bookmarkCount > 0) { 172 offset--; int index = getBookmarkIndex(offset); 174 if (index == bookmarkCount || (bookmark = getBookmark(index)).getOffset() != offset) { 175 index--; if (index >= 0) { 177 bookmark = getBookmark(index); 178 } else { if (wrapSearch) { 180 bookmark = getPreviousBookmark(Integer.MAX_VALUE, false); 181 } else { bookmark = null; 183 } 184 } 185 } } else { bookmark = null; 188 } 189 return bookmark; 190 } 191 192 204 public int getBookmarkIndex(int offset) { 205 int low = 0; 207 int high = getBookmarkCount() - 1; 208 209 while (low <= high) { 210 int mid = (low + high) / 2; 211 int midOffset = getBookmark(mid).getOffset(); 212 213 if (midOffset < offset) { 214 low = mid + 1; 215 } else if (midOffset > offset) { 216 high = mid - 1; 217 } else { mid--; 220 while (mid >= 0) { 221 if (getBookmark(mid).getOffset() != offset) { 222 break; 223 } 224 mid--; 225 } 226 mid++; 227 return mid; 228 } 229 } 230 231 return low; 232 } 233 234 249 public Bookmark toggleLineBookmark(int offset) { 250 checkOffsetInDocument(offset); 251 Element lineRoot = doc.getDefaultRootElement(); 252 int lineIndex = lineRoot.getElementIndex(offset); 253 Bookmark bookmark = null; 254 if (lineIndex < lineRoot.getElementCount()) { 255 Element lineElem = lineRoot.getElement(lineIndex); 256 int lineStartOffset = lineElem.getStartOffset(); 257 int index = getBookmarkIndex(lineStartOffset); 258 if (index < getBookmarkCount() && getBookmark(index).getOffset() < lineElem.getEndOffset() ) { bookmark = removeBookmarkAtIndex(index); 262 } else { bookmark = addBookmark(manager.createBookmarkImplementation(lineStartOffset)); 264 } 265 manager.saveBookmarks(); 267 } 268 return bookmark; 269 } 270 271 277 public Bookmark removeBookmarkAtIndex(int index) { 278 Bookmark bookmark = (Bookmark)bookmarks.remove(index); 279 bookmark.release(); 280 PCS.firePropertyChange(PROP_BOOKMARKS, null, null); 281 return bookmark; 282 } 283 284 285 public void removeAllBookmarks(){ 286 if (!bookmarks.isEmpty()) { 287 for (int i = 0; i<bookmarks.size(); i++){ 288 Bookmark bookmark = (Bookmark)bookmarks.get(i); 289 bookmark.release(); 290 } 291 bookmarks.clear(); 292 PCS.firePropertyChange(PROP_BOOKMARKS, null, null); 293 } 294 } 295 296 299 BookmarkManager getManager() { 300 return manager; 301 } 302 303 308 Bookmark addBookmark(BookmarkImplementation impl) { 309 Bookmark bookmark = new Bookmark(this, impl); 312 int index = getBookmarkIndex(impl.getOffset() + 1); 313 bookmarks.add(index, bookmark); 314 PCS.firePropertyChange(PROP_BOOKMARKS, null, null); 315 return bookmark; 316 } 317 318 private void checkOffsetNonNegative(int offset) { 319 if (offset < 0) { 320 throw new IndexOutOfBoundsException ("offset=" + offset + " < 0"); } 322 } 323 324 private void checkOffsetInDocument(int offset) { 325 checkOffsetNonNegative(offset); 326 int docLen = doc.getLength(); 327 if (offset > docLen) { 328 throw new IndexOutOfBoundsException ("offset=" + offset + " > doc.getLength()=" + docLen); } 331 } 332 333 public String toString() { 334 return "Bookmarks: " + bookmarks; } 336 337 void addPropertyChangeListener(PropertyChangeListener l) { 338 PCS.addPropertyChangeListener(l); 339 } 340 341 void removePropertyChangeListener(PropertyChangeListener l) { 342 PCS.removePropertyChangeListener(l); 343 } 344 345 349 private static final class ApiAccessor extends BookmarksApiPackageAccessor { 350 351 public BookmarkManager getBookmarkManager(BookmarkList bookmarkList) { 352 return bookmarkList.getManager(); 353 } 354 355 public BookmarkImplementation getBookmarkImplementation(Bookmark bookmark) { 356 return bookmark.getImplementation(); 357 } 358 359 public Bookmark addBookmark(BookmarkList list, BookmarkImplementation impl) { 360 return list.addBookmark(impl); 361 } 362 363 public void addBookmarkListPcl(BookmarkList list, PropertyChangeListener l) { 364 list.addPropertyChangeListener(l); 365 } 366 367 public void removeBookmarkListPcl(BookmarkList list, PropertyChangeListener l) { 368 list.removePropertyChangeListener(l); 369 } 370 } } 372 373 | Popular Tags |