PageRenderTime 39ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/netbeans-7.3/jellytools.ide/src/org/netbeans/jellytools/modules/editor/CompletionJListOperator.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 440 lines | 317 code | 42 blank | 81 comment | 28 complexity | 0cf6a82acd36f8632c51e6184f633381 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.jellytools.modules.editor;
  45. import java.awt.Point;
  46. import java.awt.Rectangle;
  47. import java.lang.reflect.Field;
  48. import java.lang.reflect.Method;
  49. import java.util.ArrayList;
  50. import java.util.List;
  51. import java.util.logging.Logger;
  52. import javax.swing.JList;
  53. import javax.swing.SwingUtilities;
  54. import javax.swing.event.DocumentEvent;
  55. import javax.swing.event.DocumentListener;
  56. import javax.swing.text.JTextComponent;
  57. import org.netbeans.api.editor.EditorRegistry;
  58. import org.netbeans.api.editor.completion.Completion;
  59. import org.netbeans.editor.BaseDocument;
  60. import org.netbeans.editor.Utilities;
  61. import org.netbeans.jellytools.Bundle;
  62. import org.netbeans.jemmy.JemmyException;
  63. import org.netbeans.jemmy.QueueTool;
  64. import org.netbeans.jemmy.Timeouts;
  65. import org.netbeans.jemmy.Waitable;
  66. import org.netbeans.jemmy.Waiter;
  67. import org.netbeans.jemmy.operators.JListOperator;
  68. import org.netbeans.modules.editor.completion.CompletionImpl;
  69. import org.netbeans.modules.editor.completion.CompletionJList;
  70. import org.netbeans.jemmy.operators.Operator;
  71. /**
  72. * Provides access to org.netbeans.modules.editor.completion.CompletionJlist
  73. * component.
  74. * Usage:
  75. * <pre>
  76. * CompletionJlist comp = CompletionJlist.showCompletion();
  77. * List list = comp.getCompletionItems();
  78. * ...
  79. * comp.hideAll();
  80. * </pre>
  81. * @author Martin.Schovanek@sun.com
  82. */
  83. public class CompletionJListOperator extends JListOperator {
  84. public static final String INSTANT_SUBSTITUTION = "InstantSubstitution";
  85. private static final Logger LOG = Logger.getLogger(CompletionJListOperator.class.getName());
  86. /**
  87. * This constructor is intended to use just for your own risk.
  88. * It could happen, that document is changed during invocation and
  89. * this costructor fails.
  90. */
  91. public CompletionJListOperator() {
  92. this(findCompletionJList());
  93. }
  94. private CompletionJListOperator(JList list) {
  95. super(list);
  96. }
  97. public List getCompletionItems() throws Exception {
  98. return getCompletionItems((JList) getSource());
  99. }
  100. private static List getCompletionItems(JList compJList)
  101. throws Exception {
  102. //ListModel model = (ListModel) compJList.getModel();
  103. // dump items to List
  104. CompletionJListOperator oper = new CompletionJListOperator(compJList);
  105. int size = oper.getModelSize();
  106. List<Object> data = new ArrayList<Object>(size);
  107. for (int i=0; i < size; i++) {
  108. data.add(oper.getModelElementAt(i));
  109. }
  110. return data;
  111. }
  112. private static JList findCompletionJList() {
  113. final String PLEASE_WAIT = Bundle.getStringTrimmed(
  114. "org.netbeans.modules.editor.completion.Bundle",
  115. "completion-please-wait");
  116. final Object result = waitFor(new Waitable() {
  117. public Object actionProduced(Object obj) {
  118. if (DocumentWatcher.isActive() && DocumentWatcher.isModified()) {
  119. return INSTANT_SUBSTITUTION;
  120. }
  121. try {
  122. // Path to the completion model:
  123. // CompletionImpl.get().layout.completionPopup.getCompletionScrollPane()
  124. // .view.getModel()
  125. CompletionImpl comp = CompletionImpl.get();
  126. //CompletionLayout.class
  127. Field layoutField = CompletionImpl.class.getDeclaredField("layout");
  128. layoutField.setAccessible(true);
  129. Object layout = layoutField.get(comp);
  130. //CompletionLayout.CompletionPopup.class
  131. Field popupField = layout.getClass().getDeclaredField("completionPopup");
  132. popupField.setAccessible(true);
  133. Object popup = popupField.get(layout);
  134. //CompletionScrollPane.class
  135. Field csPaneField = popup.getClass().getDeclaredField("completionScrollPane");
  136. csPaneField.setAccessible(true);
  137. Object compSPane = csPaneField.get(popup);
  138. if(compSPane == null) {
  139. return null;
  140. }
  141. // check if all result providers finished
  142. Field crField = comp.getClass().getDeclaredField("completionResult");
  143. crField.setAccessible(true);
  144. Object completionResult = crField.get(comp);
  145. if (completionResult != null) {
  146. Method grsMethod = completionResult.getClass().getDeclaredMethod("getResultSets");
  147. grsMethod.setAccessible(true);
  148. Object resultSets = grsMethod.invoke(completionResult, new Object[0]);
  149. Method iarfMethod = comp.getClass().getDeclaredMethod("isAllResultsFinished", List.class);
  150. iarfMethod.setAccessible(true);
  151. Boolean allResultsFinished = (Boolean) iarfMethod.invoke(comp, resultSets);
  152. if (!allResultsFinished) {
  153. LOG.fine(System.currentTimeMillis()+": all CC Results not finished yet.");
  154. return null;
  155. }
  156. }
  157. Field viewField = compSPane.getClass().getDeclaredField("view");
  158. viewField.setAccessible(true);
  159. CompletionJList compJList = (CompletionJList) viewField.get(compSPane);
  160. List list = getCompletionItems(compJList);
  161. // check if it is no a 'Please Wait' item
  162. if (list.size() > 0 && !(list.contains(PLEASE_WAIT))) {
  163. LOG.fine(list.toString());
  164. return compJList;
  165. } else {
  166. return null;
  167. }
  168. } catch (Exception ex) {
  169. throw new JemmyException("Exception when waiting for completion items.", ex);
  170. }
  171. }
  172. public String getDescription() {
  173. return "Wait for completion items data";
  174. }
  175. });
  176. if (result.equals(INSTANT_SUBSTITUTION)) {
  177. return null;
  178. }
  179. return (CompletionJList)result;
  180. }
  181. private static Object waitFor(Waitable action) {
  182. Waiter waiter = new Waiter(action);
  183. Timeouts waiterTimeouts = waiter.getTimeouts();
  184. waiterTimeouts.setTimeout("Waiter.TimeDelta", 500);
  185. waiterTimeouts.setTimeout("Waiter.AfterWaitingTime", 500);
  186. waiter.setTimeouts(waiterTimeouts);
  187. try {
  188. return waiter.waitAction(null);
  189. } catch (InterruptedException ex) {
  190. throw new JemmyException(action.getDescription()+" has been " +
  191. "interrupted.", ex);
  192. }
  193. }
  194. /** Returns a CompletionJListOperator or null in case of
  195. * instant substitution */
  196. public static CompletionJListOperator showCompletion() {
  197. CompletionJListOperator operator = null;
  198. DocumentWatcher.start();
  199. Runnable run = new Runnable() {
  200. public void run() {
  201. Completion.get().showCompletion();
  202. }
  203. };
  204. runInAWT(run);
  205. // wait CC
  206. JList list = findCompletionJList();
  207. if (list != null) {
  208. operator = new CompletionJListOperator(list);
  209. }
  210. DocumentWatcher.stop();
  211. return operator;
  212. }
  213. public static void showDocumentation() {
  214. Runnable run = new Runnable() {
  215. public void run() {
  216. Completion.get().showDocumentation();
  217. }
  218. };
  219. runInAWT(run);
  220. }
  221. public static void showToolTipPopup() {
  222. Runnable run = new Runnable() {
  223. public void run() {
  224. Completion.get().showToolTip();
  225. }
  226. };
  227. runInAWT(run);
  228. }
  229. public static void hideAll() {
  230. Runnable run = new Runnable() {
  231. public void run() {
  232. Completion.get().hideAll();
  233. }
  234. };
  235. runInAWT(run);
  236. }
  237. public static void hideCompletion() {
  238. Runnable run = new Runnable() {
  239. public void run() {
  240. Completion.get().hideCompletion();
  241. }
  242. };
  243. runInAWT(run);
  244. }
  245. public static void hideDocumentation() {
  246. Runnable run = new Runnable() {
  247. public void run() {
  248. Completion.get().hideDocumentation();
  249. }
  250. };
  251. runInAWT(run);
  252. }
  253. public static void hideToolTipPopup() {
  254. Runnable run = new Runnable() {
  255. public void run() {
  256. Completion.get().hideToolTip();
  257. }
  258. };
  259. runInAWT(run);
  260. }
  261. private static void runInAWT(Runnable r) {
  262. if (SwingUtilities.isEventDispatchThread()) {
  263. r.run();
  264. } else {
  265. try{
  266. SwingUtilities.invokeAndWait(r);
  267. }catch(Exception exc){
  268. throw new JemmyException("INVOKATION FAILED", exc);
  269. }
  270. }
  271. }
  272. static class DocumentWatcher {
  273. private static BaseDocument doc;
  274. private static boolean modified = false;
  275. private static boolean active = false;
  276. static DocumentListener listener = new DocumentListener() {
  277. public void changedUpdate(DocumentEvent e) {
  278. //setModified(true);
  279. }
  280. public void insertUpdate(DocumentEvent e) {
  281. setModified(true);
  282. }
  283. public void removeUpdate(DocumentEvent e) {
  284. //setModified(true);
  285. }
  286. };
  287. public static void start() {
  288. JTextComponent jtc = EditorRegistry.lastFocusedComponent();
  289. doc = jtc != null ? Utilities.getDocument(jtc) : null;
  290. if (doc != null) {
  291. doc.addDocumentListener(listener);
  292. }
  293. modified = false;
  294. active = true;
  295. }
  296. public static void stop() {
  297. if (doc != null) {
  298. doc.removeDocumentListener(listener);
  299. doc = null;
  300. }
  301. active = false;
  302. }
  303. public static boolean isModified() {
  304. if (!active) {
  305. throw new IllegalStateException("start() must be called before this.");
  306. }
  307. return modified;
  308. }
  309. public static boolean isActive() {
  310. return active;
  311. }
  312. private static void setModified(boolean b) {
  313. modified = b;
  314. if(doc!=null){
  315. doc.removeDocumentListener(listener);
  316. doc = null;
  317. }
  318. }
  319. }
  320. private int getModelSize() {
  321. return runMapping(new MapIntegerAction("getModel().getSize()") {
  322. @Override
  323. public int map() throws Exception {
  324. return getModel().getSize();
  325. }
  326. });
  327. }
  328. private Object getModelElementAt(final int index) {
  329. return runMapping(new MapAction("getModel().getElementAt()") {
  330. @Override
  331. public Object map() throws Exception {
  332. return getModel().getElementAt(index);
  333. }
  334. });
  335. }
  336. @Override
  337. public int findItemIndex(final ListItemChooser chooser, final int index) {
  338. return runMapping(new MapIntegerAction("findItemIndex") {
  339. @Override
  340. public int map() throws Exception {
  341. return CompletionJListOperator.super.findItemIndex(chooser, index);
  342. }
  343. });
  344. }
  345. @Override
  346. public Object clickOnItem(final String item)
  347. {
  348. return runMapping( new MapAction("clickOnItem( String )") {
  349. @Override
  350. public Object map() throws Exception {
  351. return CompletionJListOperator.super.clickOnItem( item );
  352. }
  353. });
  354. }
  355. @Override
  356. public Object clickOnItem(final String item, final Operator.StringComparator comp)
  357. {
  358. return clickOnItem(item, comp, 1);
  359. }
  360. @Override
  361. /*
  362. * Most of this code copied from JList.java because there are
  363. * some problems with scrolling on big completion lists, ex. full
  364. * PHP completion list contains about 6000 elements. Scrolling
  365. * just removed from code.
  366. */
  367. public Object clickOnItem(final String item, final Operator.StringComparator comp, final int clickCount)
  368. {
  369. return runMapping( new MapAction("clickOnItem( String, Comparator )")
  370. {
  371. @Override
  372. public Object map() throws Exception
  373. {
  374. final int itemIndex = CompletionJListOperator.super.findItemIndex(item, comp, 0);
  375. if( itemIndex < 0 || itemIndex >= getModel().getSize())
  376. throw(new NoSuchItemException(itemIndex));
  377. return( getQueueTool().invokeSmoothly( new QueueTool.QueueAction("Path selecting")
  378. {
  379. public Object launch()
  380. {
  381. if(((JList)getSource()).getAutoscrolls())
  382. ((JList)getSource()).ensureIndexIsVisible(itemIndex);
  383. Rectangle rect = getCellBounds(itemIndex, itemIndex);
  384. if(rect == null)
  385. return(null);
  386. Point point = new Point(
  387. (int)(rect.getX() + rect.getWidth() / 2),
  388. (int)(rect.getY() + rect.getHeight() / 2)
  389. );
  390. Object result = getModel().getElementAt(itemIndex);
  391. clickMouse(point.x, point.y, clickCount);
  392. return(result);
  393. }
  394. }));
  395. }
  396. });
  397. }
  398. }