PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/gui/ActionBar.java

#
Java | 576 lines | 445 code | 59 blank | 72 comment | 100 complexity | 836bdba11eeeaea202fad27e4218b557 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * ActionBar.java - For invoking actions directly
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2003 Slava Pestov
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package org.gjt.sp.jedit.gui;
  23. //{{{ Imports
  24. import bsh.NameSpace;
  25. import java.awt.event.*;
  26. import java.awt.*;
  27. import java.util.ArrayList;
  28. import java.util.Arrays;
  29. import javax.swing.event.*;
  30. import javax.swing.*;
  31. import org.gjt.sp.jedit.*;
  32. //}}}
  33. /**
  34. * Action invocation bar.
  35. */
  36. public class ActionBar extends JPanel
  37. {
  38. //{{{ ActionBar constructor
  39. public ActionBar(final View view, boolean temp)
  40. {
  41. setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
  42. this.view = view;
  43. this.temp = temp;
  44. add(Box.createHorizontalStrut(2));
  45. JLabel label = new JLabel(jEdit.getProperty("view.action.prompt"));
  46. add(label);
  47. add(Box.createHorizontalStrut(12));
  48. add(action = new ActionTextField());
  49. action.setEnterAddsToHistory(false);
  50. Dimension max = action.getPreferredSize();
  51. max.width = Integer.MAX_VALUE;
  52. action.setMaximumSize(max);
  53. action.addActionListener(new ActionHandler());
  54. action.getDocument().addDocumentListener(new DocumentHandler());
  55. if(temp)
  56. {
  57. close = new RolloverButton(GUIUtilities.loadIcon("closebox.gif"));
  58. close.addActionListener(new ActionHandler());
  59. close.setToolTipText(jEdit.getProperty(
  60. "view.action.close-tooltip"));
  61. add(close);
  62. }
  63. // if 'temp' is true, hide search bar after user is done with it
  64. this.temp = temp;
  65. } //}}}
  66. //{{{ getField() method
  67. public HistoryTextField getField()
  68. {
  69. return action;
  70. } //}}}
  71. //{{{ goToActionBar() method
  72. public void goToActionBar()
  73. {
  74. repeatCount = view.getInputHandler().getRepeatCount();
  75. action.setText(null);
  76. action.requestFocus();
  77. } //}}}
  78. //{{{ actionListChanged()
  79. /**
  80. * Called when plugins are added or removed to notify the action bar
  81. * that the action list has changed.
  82. * @since jEdit 4.2pre2
  83. */
  84. public void actionListChanged()
  85. {
  86. actions = null;
  87. } //}}}
  88. //{{{ Private members
  89. private static NameSpace namespace = new NameSpace(
  90. BeanShell.getNameSpace(),"action bar namespace");
  91. //{{{ Instance variables
  92. private View view;
  93. private boolean temp;
  94. private int repeatCount;
  95. private HistoryTextField action;
  96. private CompletionPopup popup;
  97. private RolloverButton close;
  98. private String[] actions;
  99. //}}}
  100. //{{{ initActions() method
  101. private void initActions()
  102. {
  103. if(actions != null)
  104. return;
  105. actions = jEdit.getActionNames();
  106. Arrays.sort(actions,new MiscUtilities.StringICaseCompare());
  107. } //}}}
  108. //{{{ invoke() method
  109. private void invoke()
  110. {
  111. String cmd;
  112. if(popup != null)
  113. cmd = popup.list.getSelectedValue().toString();
  114. else
  115. {
  116. cmd = action.getText().trim();
  117. int index = cmd.indexOf('=');
  118. if(index != -1)
  119. {
  120. action.addCurrentToHistory();
  121. String propName = cmd.substring(0,index).trim();
  122. String propValue = cmd.substring(index + 1).trim();
  123. String code;
  124. /* construct a BeanShell snippet instead of
  125. * invoking directly so that user can record
  126. * property changes in macros. */
  127. if(propName.startsWith("buffer."))
  128. {
  129. if(propName.equals("buffer.mode"))
  130. {
  131. code = "buffer.setMode(\""
  132. + MiscUtilities.charsToEscapes(
  133. propValue) + "\");";
  134. }
  135. else
  136. {
  137. code = "buffer.setStringProperty(\""
  138. + MiscUtilities.charsToEscapes(
  139. propName.substring("buffer.".length())
  140. ) + "\",\""
  141. + MiscUtilities.charsToEscapes(
  142. propValue) + "\");";
  143. }
  144. code = code + "\nbuffer.propertiesChanged();";
  145. }
  146. else if(propName.startsWith("!buffer."))
  147. {
  148. code = "jEdit.setProperty(\""
  149. + MiscUtilities.charsToEscapes(
  150. propName.substring(1)) + "\",\""
  151. + MiscUtilities.charsToEscapes(
  152. propValue) + "\");\n"
  153. + "jEdit.propertiesChanged();";
  154. }
  155. else
  156. {
  157. code = "jEdit.setProperty(\""
  158. + MiscUtilities.charsToEscapes(
  159. propName) + "\",\""
  160. + MiscUtilities.charsToEscapes(
  161. propValue) + "\");\n"
  162. + "jEdit.propertiesChanged();"
  163. + "EditBus.send(new DockableWindowUpdate(wm,"
  164. + "DockableWindowUpdate."
  165. + "PROPERTIES_CHANGED,null));";
  166. }
  167. Macros.Recorder recorder = view.getMacroRecorder();
  168. if(recorder != null)
  169. recorder.record(code);
  170. BeanShell.eval(view,namespace,code);
  171. cmd = null;
  172. }
  173. else if(cmd.length() != 0)
  174. {
  175. String[] completions = getCompletions(cmd);
  176. if(completions.length != 0)
  177. {
  178. cmd = completions[0];
  179. }
  180. }
  181. else
  182. cmd = null;
  183. }
  184. if(popup != null)
  185. {
  186. popup.dispose();
  187. popup = null;
  188. }
  189. final String finalCmd = cmd;
  190. final EditAction act = (finalCmd == null ? null : jEdit.getAction(finalCmd));
  191. if(temp)
  192. view.removeToolBar(ActionBar.this);
  193. SwingUtilities.invokeLater(new Runnable()
  194. {
  195. public void run()
  196. {
  197. view.getTextArea().requestFocus();
  198. if(act == null)
  199. {
  200. if(finalCmd != null)
  201. {
  202. view.getStatus().setMessageAndClear(
  203. jEdit.getProperty(
  204. "view.action.no-completions"));
  205. }
  206. }
  207. else
  208. {
  209. view.getInputHandler().setRepeatCount(repeatCount);
  210. view.getInputHandler().invokeAction(act);
  211. }
  212. }
  213. });
  214. } //}}}
  215. //{{{ getCompletions() method
  216. private String[] getCompletions(String str)
  217. {
  218. initActions();
  219. str = str.toLowerCase();
  220. ArrayList returnValue = new ArrayList(actions.length);
  221. for(int i = 0; i < actions.length; i++)
  222. {
  223. if(actions[i].toLowerCase().indexOf(str) != -1)
  224. returnValue.add(actions[i]);
  225. }
  226. return (String[])returnValue.toArray(new String[returnValue.size()]);
  227. } //}}}
  228. //{{{ complete() method
  229. private void complete(boolean insertLongestPrefix)
  230. {
  231. String text = action.getText().trim();
  232. String[] completions = getCompletions(text);
  233. if(completions.length == 1)
  234. {
  235. if(insertLongestPrefix)
  236. action.setText(completions[0]);
  237. }
  238. else if(completions.length != 0)
  239. {
  240. if(insertLongestPrefix)
  241. {
  242. String prefix = MiscUtilities.getLongestPrefix(
  243. completions,true);
  244. if(prefix.indexOf(text) != -1)
  245. action.setText(prefix);
  246. }
  247. if(popup != null)
  248. popup.setModel(completions);
  249. else
  250. popup = new CompletionPopup(completions);
  251. return;
  252. }
  253. if(popup != null)
  254. {
  255. popup.dispose();
  256. popup = null;
  257. }
  258. } //}}}
  259. //}}}
  260. //{{{ Inner classes
  261. //{{{ ActionHandler class
  262. class ActionHandler implements ActionListener
  263. {
  264. public void actionPerformed(ActionEvent evt)
  265. {
  266. if(evt.getSource() == close)
  267. view.removeToolBar(ActionBar.this);
  268. else
  269. invoke();
  270. }
  271. } //}}}
  272. //{{{ DocumentHandler class
  273. class DocumentHandler implements DocumentListener
  274. {
  275. //{{{ insertUpdate() method
  276. public void insertUpdate(DocumentEvent evt)
  277. {
  278. if(popup != null)
  279. complete(false);
  280. } //}}}
  281. //{{{ removeUpdate() method
  282. public void removeUpdate(DocumentEvent evt)
  283. {
  284. if(popup != null)
  285. complete(false);
  286. } //}}}
  287. //{{{ changedUpdate() method
  288. public void changedUpdate(DocumentEvent evt) {}
  289. //}}}
  290. } //}}}
  291. //{{{ ActionTextField class
  292. class ActionTextField extends HistoryTextField
  293. {
  294. boolean repeat;
  295. boolean nonDigit;
  296. ActionTextField()
  297. {
  298. super("action");
  299. setSelectAllOnFocus(true);
  300. }
  301. public boolean isManagingFocus()
  302. {
  303. return false;
  304. }
  305. public boolean getFocusTraversalKeysEnabled()
  306. {
  307. return false;
  308. }
  309. public void processKeyEvent(KeyEvent evt)
  310. {
  311. evt = KeyEventWorkaround.processKeyEvent(evt);
  312. if(evt == null)
  313. return;
  314. switch(evt.getID())
  315. {
  316. case KeyEvent.KEY_TYPED:
  317. char ch = evt.getKeyChar();
  318. if(!nonDigit && Character.isDigit(ch))
  319. {
  320. super.processKeyEvent(evt);
  321. repeat = true;
  322. repeatCount = Integer.parseInt(action.getText());
  323. }
  324. else
  325. {
  326. nonDigit = true;
  327. if(repeat)
  328. passToView(evt);
  329. else
  330. super.processKeyEvent(evt);
  331. }
  332. break;
  333. case KeyEvent.KEY_PRESSED:
  334. int keyCode = evt.getKeyCode();
  335. if(evt.isActionKey()
  336. || evt.isControlDown()
  337. || evt.isAltDown()
  338. || evt.isMetaDown()
  339. || keyCode == KeyEvent.VK_BACK_SPACE
  340. || keyCode == KeyEvent.VK_DELETE
  341. || keyCode == KeyEvent.VK_ENTER
  342. || keyCode == KeyEvent.VK_TAB
  343. || keyCode == KeyEvent.VK_ESCAPE)
  344. {
  345. nonDigit = true;
  346. if(repeat)
  347. {
  348. passToView(evt);
  349. break;
  350. }
  351. else if(keyCode == KeyEvent.VK_TAB)
  352. {
  353. complete(true);
  354. evt.consume();
  355. }
  356. else if(keyCode == KeyEvent.VK_ESCAPE)
  357. {
  358. evt.consume();
  359. if(popup != null)
  360. {
  361. popup.dispose();
  362. popup = null;
  363. action.requestFocus();
  364. }
  365. else
  366. {
  367. if(temp)
  368. view.removeToolBar(ActionBar.this);
  369. view.getEditPane().focusOnTextArea();
  370. }
  371. break;
  372. }
  373. else if((keyCode == KeyEvent.VK_UP
  374. || keyCode == KeyEvent.VK_DOWN)
  375. && popup != null)
  376. {
  377. popup.list.processKeyEvent(evt);
  378. break;
  379. }
  380. }
  381. super.processKeyEvent(evt);
  382. break;
  383. }
  384. }
  385. private void passToView(final KeyEvent evt)
  386. {
  387. if(temp)
  388. view.removeToolBar(ActionBar.this);
  389. SwingUtilities.invokeLater(new Runnable()
  390. {
  391. public void run()
  392. {
  393. view.getTextArea().requestFocus();
  394. view.getInputHandler().setRepeatCount(repeatCount);
  395. view.getInputHandler().processKeyEvent(evt);
  396. }
  397. });
  398. }
  399. public void addNotify()
  400. {
  401. super.addNotify();
  402. repeat = nonDigit = false;
  403. }
  404. } //}}}
  405. //{{{ CompletionPopup class
  406. class CompletionPopup extends JWindow
  407. {
  408. CompletionList list;
  409. //{{{ CompletionPopup constructor
  410. CompletionPopup(String[] actions)
  411. {
  412. super(view);
  413. setContentPane(new JPanel(new BorderLayout())
  414. {
  415. /**
  416. * Returns if this component can be traversed by pressing the
  417. * Tab key. This returns false.
  418. */
  419. public boolean isManagingFocus()
  420. {
  421. return false;
  422. }
  423. /**
  424. * Makes the tab key work in Java 1.4.
  425. */
  426. public boolean getFocusTraversalKeysEnabled()
  427. {
  428. return false;
  429. }
  430. });
  431. list = new CompletionList(actions);
  432. list.setVisibleRowCount(8);
  433. list.addMouseListener(new MouseHandler());
  434. list.setSelectedIndex(0);
  435. list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  436. // stupid scrollbar policy is an attempt to work around
  437. // bugs people have been seeing with IBM's JDK -- 7 Sep 2000
  438. JScrollPane scroller = new JScrollPane(list,
  439. JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
  440. JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
  441. getContentPane().add(scroller, BorderLayout.CENTER);
  442. GUIUtilities.requestFocus(this,list);
  443. pack();
  444. Point p = new Point(0,-getHeight());
  445. SwingUtilities.convertPointToScreen(p,action);
  446. setLocation(p);
  447. show();
  448. KeyHandler keyHandler = new KeyHandler();
  449. addKeyListener(keyHandler);
  450. list.addKeyListener(keyHandler);
  451. } //}}}
  452. //{{{ setModel() method
  453. void setModel(String[] actions)
  454. {
  455. list.setListData(actions);
  456. list.setSelectedIndex(0);
  457. } //}}}
  458. //{{{ MouseHandler class
  459. class MouseHandler extends MouseAdapter
  460. {
  461. public void mouseClicked(MouseEvent evt)
  462. {
  463. invoke();
  464. }
  465. } //}}}
  466. //{{{ CompletionList class
  467. class CompletionList extends JList
  468. {
  469. CompletionList(Object[] data)
  470. {
  471. super(data);
  472. }
  473. // we need this public not protected
  474. public void processKeyEvent(KeyEvent evt)
  475. {
  476. super.processKeyEvent(evt);
  477. }
  478. } //}}}
  479. //{{{ KeyHandler class
  480. class KeyHandler extends KeyAdapter
  481. {
  482. public void keyTyped(KeyEvent evt)
  483. {
  484. action.processKeyEvent(evt);
  485. }
  486. public void keyPressed(KeyEvent evt)
  487. {
  488. int keyCode = evt.getKeyCode();
  489. if(keyCode == KeyEvent.VK_ESCAPE)
  490. action.processKeyEvent(evt);
  491. else if(keyCode == KeyEvent.VK_ENTER)
  492. invoke();
  493. else if(keyCode == KeyEvent.VK_UP)
  494. {
  495. int selected = list.getSelectedIndex();
  496. if(selected == 0)
  497. {
  498. list.setSelectedIndex(
  499. list.getModel().getSize()
  500. - 1);
  501. evt.consume();
  502. }
  503. }
  504. else if(keyCode == KeyEvent.VK_DOWN)
  505. {
  506. int selected = list.getSelectedIndex();
  507. if(selected == list.getModel().getSize() - 1)
  508. {
  509. list.setSelectedIndex(0);
  510. evt.consume();
  511. }
  512. }
  513. }
  514. } //}}}
  515. } //}}}
  516. //}}}
  517. }