Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gjt/sp/jedit/gui/ActionBar.java


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