PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/gui/ActionBar.java

#
Java | 554 lines | 434 code | 55 blank | 65 comment | 98 complexity | 768ec1f14a943e3f06d39b7d20cbc2a0 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. //{{{ Private members
  79. private static NameSpace namespace = new NameSpace(
  80. BeanShell.getNameSpace(),"action bar namespace");
  81. //{{{ Instance variables
  82. private View view;
  83. private boolean temp;
  84. private int repeatCount;
  85. private HistoryTextField action;
  86. private CompletionPopup popup;
  87. private RolloverButton close;
  88. //}}}
  89. //{{{ invoke() method
  90. private void invoke()
  91. {
  92. String cmd;
  93. if(popup != null)
  94. cmd = popup.list.getSelectedValue().toString();
  95. else
  96. {
  97. cmd = action.getText().trim();
  98. int index = cmd.indexOf('=');
  99. if(index != -1)
  100. {
  101. action.addCurrentToHistory();
  102. String propName = cmd.substring(0,index).trim();
  103. String propValue = cmd.substring(index + 1).trim();
  104. String code;
  105. /* construct a BeanShell snippet instead of
  106. * invoking directly so that user can record
  107. * property changes in macros. */
  108. if(propName.startsWith("buffer."))
  109. {
  110. if(propName.equals("buffer.mode"))
  111. {
  112. code = "buffer.setMode(\""
  113. + MiscUtilities.charsToEscapes(
  114. propValue) + "\");";
  115. }
  116. else
  117. {
  118. code = "buffer.setStringProperty(\""
  119. + MiscUtilities.charsToEscapes(
  120. propName.substring("buffer.".length())
  121. ) + "\",\""
  122. + MiscUtilities.charsToEscapes(
  123. propValue) + "\");";
  124. }
  125. code = code + "\nbuffer.propertiesChanged();";
  126. }
  127. else if(propName.startsWith("!buffer."))
  128. {
  129. code = "jEdit.setProperty(\""
  130. + MiscUtilities.charsToEscapes(
  131. propName.substring(1)) + "\",\""
  132. + MiscUtilities.charsToEscapes(
  133. propValue) + "\");\n"
  134. + "jEdit.propertiesChanged();";
  135. }
  136. else
  137. {
  138. code = "jEdit.setProperty(\""
  139. + MiscUtilities.charsToEscapes(
  140. propName) + "\",\""
  141. + MiscUtilities.charsToEscapes(
  142. propValue) + "\");\n"
  143. + "jEdit.propertiesChanged();";
  144. }
  145. Macros.Recorder recorder = view.getMacroRecorder();
  146. if(recorder != null)
  147. recorder.record(code);
  148. BeanShell.eval(view,namespace,code);
  149. cmd = null;
  150. }
  151. else if(cmd.length() != 0)
  152. {
  153. String[] completions = getCompletions(cmd);
  154. if(completions.length != 0)
  155. {
  156. cmd = completions[0];
  157. }
  158. }
  159. else
  160. cmd = null;
  161. }
  162. if(popup != null)
  163. {
  164. popup.dispose();
  165. popup = null;
  166. }
  167. final String finalCmd = cmd;
  168. final EditAction act = (finalCmd == null ? null : jEdit.getAction(finalCmd));
  169. if(temp)
  170. view.removeToolBar(ActionBar.this);
  171. SwingUtilities.invokeLater(new Runnable()
  172. {
  173. public void run()
  174. {
  175. view.getTextArea().requestFocus();
  176. if(act == null)
  177. {
  178. if(finalCmd != null)
  179. {
  180. view.getStatus().setMessageAndClear(
  181. jEdit.getProperty(
  182. "view.action.no-completions"));
  183. }
  184. }
  185. else
  186. {
  187. view.getInputHandler().setRepeatCount(repeatCount);
  188. view.getInputHandler().invokeAction(act);
  189. }
  190. }
  191. });
  192. } //}}}
  193. //{{{ getCompletions() method
  194. private String[] getCompletions(String str)
  195. {
  196. str = str.toLowerCase();
  197. String[] actions = jEdit.getActionNames();
  198. ArrayList returnValue = new ArrayList(actions.length);
  199. for(int i = 0; i < actions.length; i++)
  200. {
  201. if(actions[i].toLowerCase().indexOf(str) != -1)
  202. returnValue.add(actions[i]);
  203. }
  204. return (String[])returnValue.toArray(new String[returnValue.size()]);
  205. } //}}}
  206. //{{{ complete() method
  207. private void complete(boolean insertLongestPrefix)
  208. {
  209. String text = action.getText().trim();
  210. String[] completions = getCompletions(text);
  211. if(completions.length == 1)
  212. {
  213. if(insertLongestPrefix)
  214. action.setText(completions[0]);
  215. }
  216. else if(completions.length != 0)
  217. {
  218. if(insertLongestPrefix)
  219. {
  220. String prefix = MiscUtilities.getLongestPrefix(
  221. completions,true);
  222. if(prefix.indexOf(text) != -1)
  223. action.setText(prefix);
  224. }
  225. if(popup != null)
  226. popup.setModel(completions);
  227. else
  228. popup = new CompletionPopup(completions);
  229. return;
  230. }
  231. if(popup != null)
  232. {
  233. popup.dispose();
  234. popup = null;
  235. }
  236. } //}}}
  237. //}}}
  238. //{{{ Inner classes
  239. //{{{ ActionHandler class
  240. class ActionHandler implements ActionListener
  241. {
  242. public void actionPerformed(ActionEvent evt)
  243. {
  244. if(evt.getSource() == close)
  245. view.removeToolBar(ActionBar.this);
  246. else
  247. invoke();
  248. }
  249. } //}}}
  250. //{{{ DocumentHandler class
  251. class DocumentHandler implements DocumentListener
  252. {
  253. //{{{ insertUpdate() method
  254. public void insertUpdate(DocumentEvent evt)
  255. {
  256. if(popup != null)
  257. complete(false);
  258. } //}}}
  259. //{{{ removeUpdate() method
  260. public void removeUpdate(DocumentEvent evt)
  261. {
  262. if(popup != null)
  263. complete(false);
  264. } //}}}
  265. //{{{ changedUpdate() method
  266. public void changedUpdate(DocumentEvent evt) {}
  267. //}}}
  268. } //}}}
  269. //{{{ ActionTextField class
  270. class ActionTextField extends HistoryTextField
  271. {
  272. boolean repeat;
  273. boolean nonDigit;
  274. ActionTextField()
  275. {
  276. super("action");
  277. setSelectAllOnFocus(true);
  278. }
  279. public boolean isManagingFocus()
  280. {
  281. return false;
  282. }
  283. public boolean getFocusTraversalKeysEnabled()
  284. {
  285. return false;
  286. }
  287. public void processKeyEvent(KeyEvent evt)
  288. {
  289. evt = KeyEventWorkaround.processKeyEvent(evt);
  290. if(evt == null)
  291. return;
  292. switch(evt.getID())
  293. {
  294. case KeyEvent.KEY_TYPED:
  295. char ch = evt.getKeyChar();
  296. if(!nonDigit && Character.isDigit(ch))
  297. {
  298. super.processKeyEvent(evt);
  299. repeat = true;
  300. repeatCount = Integer.parseInt(action.getText());
  301. }
  302. else
  303. {
  304. nonDigit = true;
  305. if(repeat)
  306. {
  307. passToView(evt);
  308. }
  309. else
  310. super.processKeyEvent(evt);
  311. }
  312. break;
  313. case KeyEvent.KEY_PRESSED:
  314. int keyCode = evt.getKeyCode();
  315. if(evt.isActionKey()
  316. || evt.isControlDown()
  317. || evt.isAltDown()
  318. || evt.isMetaDown()
  319. || keyCode == KeyEvent.VK_BACK_SPACE
  320. || keyCode == KeyEvent.VK_DELETE
  321. || keyCode == KeyEvent.VK_ENTER
  322. || keyCode == KeyEvent.VK_TAB
  323. || keyCode == KeyEvent.VK_ESCAPE)
  324. {
  325. nonDigit = true;
  326. if(repeat)
  327. {
  328. passToView(evt);
  329. break;
  330. }
  331. else if(keyCode == KeyEvent.VK_TAB)
  332. {
  333. complete(true);
  334. evt.consume();
  335. }
  336. else if(keyCode == KeyEvent.VK_ESCAPE)
  337. {
  338. evt.consume();
  339. if(popup != null)
  340. {
  341. popup.dispose();
  342. popup = null;
  343. action.requestFocus();
  344. }
  345. else
  346. {
  347. if(temp)
  348. view.removeToolBar(ActionBar.this);
  349. view.getEditPane().focusOnTextArea();
  350. }
  351. break;
  352. }
  353. else if((keyCode == KeyEvent.VK_UP
  354. || keyCode == KeyEvent.VK_DOWN)
  355. && popup != null)
  356. {
  357. popup.list.processKeyEvent(evt);
  358. break;
  359. }
  360. }
  361. super.processKeyEvent(evt);
  362. break;
  363. }
  364. }
  365. private void passToView(final KeyEvent evt)
  366. {
  367. if(temp)
  368. view.removeToolBar(ActionBar.this);
  369. view.getTextArea().requestFocus();
  370. SwingUtilities.invokeLater(new Runnable()
  371. {
  372. public void run()
  373. {
  374. view.getTextArea().requestFocus();
  375. view.getInputHandler().setRepeatCount(repeatCount);
  376. view.processKeyEvent(evt,
  377. View.ACTION_BAR);
  378. }
  379. });
  380. }
  381. public void addNotify()
  382. {
  383. super.addNotify();
  384. repeat = nonDigit = false;
  385. }
  386. } //}}}
  387. //{{{ CompletionPopup class
  388. class CompletionPopup extends JWindow
  389. {
  390. CompletionList list;
  391. //{{{ CompletionPopup constructor
  392. CompletionPopup(String[] actions)
  393. {
  394. super(view);
  395. setContentPane(new JPanel(new BorderLayout())
  396. {
  397. /**
  398. * Returns if this component can be traversed by pressing the
  399. * Tab key. This returns false.
  400. */
  401. public boolean isManagingFocus()
  402. {
  403. return false;
  404. }
  405. /**
  406. * Makes the tab key work in Java 1.4.
  407. */
  408. public boolean getFocusTraversalKeysEnabled()
  409. {
  410. return false;
  411. }
  412. });
  413. list = new CompletionList(actions);
  414. list.setVisibleRowCount(8);
  415. list.addMouseListener(new MouseHandler());
  416. list.setSelectedIndex(0);
  417. list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  418. // stupid scrollbar policy is an attempt to work around
  419. // bugs people have been seeing with IBM's JDK -- 7 Sep 2000
  420. JScrollPane scroller = new JScrollPane(list,
  421. JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
  422. JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
  423. getContentPane().add(scroller, BorderLayout.CENTER);
  424. GUIUtilities.requestFocus(this,list);
  425. pack();
  426. Point p = new Point(0,-getHeight());
  427. SwingUtilities.convertPointToScreen(p,action);
  428. setLocation(p);
  429. setVisible(true);
  430. KeyHandler keyHandler = new KeyHandler();
  431. addKeyListener(keyHandler);
  432. list.addKeyListener(keyHandler);
  433. } //}}}
  434. //{{{ setModel() method
  435. void setModel(String[] actions)
  436. {
  437. list.setListData(actions);
  438. list.setSelectedIndex(0);
  439. } //}}}
  440. //{{{ MouseHandler class
  441. class MouseHandler extends MouseAdapter
  442. {
  443. public void mouseClicked(MouseEvent evt)
  444. {
  445. invoke();
  446. }
  447. } //}}}
  448. //{{{ CompletionList class
  449. class CompletionList extends JList
  450. {
  451. CompletionList(Object[] data)
  452. {
  453. super(data);
  454. }
  455. // we need this public not protected
  456. public void processKeyEvent(KeyEvent evt)
  457. {
  458. super.processKeyEvent(evt);
  459. }
  460. } //}}}
  461. //{{{ KeyHandler class
  462. class KeyHandler extends KeyAdapter
  463. {
  464. public void keyTyped(KeyEvent evt)
  465. {
  466. action.processKeyEvent(evt);
  467. }
  468. public void keyPressed(KeyEvent evt)
  469. {
  470. int keyCode = evt.getKeyCode();
  471. if(keyCode == KeyEvent.VK_ESCAPE)
  472. action.processKeyEvent(evt);
  473. else if(keyCode == KeyEvent.VK_ENTER)
  474. invoke();
  475. else if(keyCode == KeyEvent.VK_UP)
  476. {
  477. int selected = list.getSelectedIndex();
  478. if(selected == 0)
  479. {
  480. list.setSelectedIndex(
  481. list.getModel().getSize()
  482. - 1);
  483. evt.consume();
  484. }
  485. }
  486. else if(keyCode == KeyEvent.VK_DOWN)
  487. {
  488. int selected = list.getSelectedIndex();
  489. if(selected == list.getModel().getSize() - 1)
  490. {
  491. list.setSelectedIndex(0);
  492. evt.consume();
  493. }
  494. }
  495. }
  496. } //}}}
  497. } //}}}
  498. //}}}
  499. }