PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/gui/StatusBar.java

#
Java | 492 lines | 349 code | 55 blank | 88 comment | 55 complexity | 03b2bc4578fdf5f4e46c4f2bebb6e252 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. * StatusBar.java - The status bar displayed at the bottom of views
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2001, 2004 Slava Pestov
  7. * Portions copyright (C) 2001 Mike Dillon
  8. * Portions copyright (C) 2008 Matthieu Casanova
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. */
  24. package org.gjt.sp.jedit.gui;
  25. //{{{ Imports
  26. import javax.swing.border.*;
  27. import javax.swing.text.Segment;
  28. import javax.swing.*;
  29. import java.awt.event.*;
  30. import java.awt.*;
  31. import java.util.StringTokenizer;
  32. import org.gjt.sp.jedit.io.*;
  33. import org.gjt.sp.jedit.textarea.*;
  34. import org.gjt.sp.jedit.*;
  35. import org.gjt.sp.jedit.gui.statusbar.StatusWidgetFactory;
  36. import org.gjt.sp.jedit.gui.statusbar.Widget;
  37. import org.gjt.sp.jedit.gui.statusbar.ToolTipLabel;
  38. import org.gjt.sp.util.*;
  39. //}}}
  40. /**
  41. * The status bar used to display various information to the user.<p>
  42. *
  43. * Currently, it is used for the following:
  44. * <ul>
  45. * <li>Displaying caret position information
  46. * <li>Displaying {@link InputHandler#readNextChar(String,String)} prompts
  47. * <li>Displaying {@link #setMessage(String)} messages
  48. * <li>Displaying I/O progress
  49. * <li>Displaying various editor settings
  50. * <li>Displaying memory status
  51. * </ul>
  52. *
  53. * @version $Id: StatusBar.java 17443 2010-03-09 19:53:40Z kpouer $
  54. * @author Slava Pestov
  55. * @since jEdit 3.2pre2
  56. */
  57. public class StatusBar extends JPanel implements WorkThreadProgressListener
  58. {
  59. //{{{ StatusBar constructor
  60. public StatusBar(View view)
  61. {
  62. super(new BorderLayout());
  63. setName("StatusBar");
  64. setBorder(new CompoundBorder(new EmptyBorder(4,0,0,
  65. (OperatingSystem.isMacOS() ? 18 : 0)),
  66. UIManager.getBorder("TextField.border")));
  67. this.view = view;
  68. panel = new JPanel(new BorderLayout());
  69. box = new Box(BoxLayout.X_AXIS);
  70. panel.add(BorderLayout.EAST,box);
  71. add(BorderLayout.CENTER,panel);
  72. MouseHandler mouseHandler = new MouseHandler();
  73. caretStatus = new ToolTipLabel();
  74. caretStatus.setName("caretStatus");
  75. caretStatus.setToolTipText(jEdit.getProperty("view.status.caret-tooltip"));
  76. caretStatus.addMouseListener(mouseHandler);
  77. message = new JLabel(" ");
  78. setMessageComponent(message);
  79. modeWidget = _getWidget("mode");
  80. foldWidget = _getWidget("fold");
  81. encodingWidget = _getWidget("encoding");
  82. wrapWidget = _getWidget("wrap");
  83. multiSelectWidget = _getWidget("multiSelect");
  84. rectSelectWidget = _getWidget("rectSelect");
  85. overwriteWidget = _getWidget("overwrite");
  86. lineSepWidget = _getWidget("lineSep");
  87. } //}}}
  88. //{{{ propertiesChanged() method
  89. public void propertiesChanged()
  90. {
  91. Color fg = jEdit.getColorProperty("view.status.foreground");
  92. Color bg = jEdit.getColorProperty("view.status.background");
  93. showCaretStatus = jEdit.getBooleanProperty("view.status.show-caret-status");
  94. panel.setBackground(bg);
  95. panel.setForeground(fg);
  96. caretStatus.setBackground(bg);
  97. caretStatus.setForeground(fg);
  98. message.setBackground(bg);
  99. message.setForeground(fg);
  100. // retarded GTK look and feel!
  101. Font font = new JLabel().getFont();
  102. //UIManager.getFont("Label.font");
  103. FontMetrics fm = getFontMetrics(font);
  104. if (showCaretStatus)
  105. {
  106. panel.add(BorderLayout.WEST,caretStatus);
  107. caretStatus.setFont(font);
  108. Dimension dim = new Dimension(fm.stringWidth(caretTestStr),
  109. fm.getHeight());
  110. caretStatus.setPreferredSize(dim);
  111. updateCaretStatus();
  112. }
  113. else
  114. panel.remove(caretStatus);
  115. String statusBar = jEdit.getProperty("view.status");
  116. if (!StandardUtilities.objectsEqual(currentBar, statusBar))
  117. {
  118. box.removeAll();
  119. StringTokenizer tokenizer = new StringTokenizer(statusBar);
  120. while (tokenizer.hasMoreTokens())
  121. {
  122. String token = tokenizer.nextToken();
  123. if (Character.isLetter(token.charAt(0)))
  124. {
  125. Widget widget = getWidget(token);
  126. if (widget == null)
  127. {
  128. JLabel label = new JLabel(token);
  129. label.setBackground(bg);
  130. label.setForeground(fg);
  131. box.add(label);
  132. continue;
  133. }
  134. Component c = widget.getComponent();
  135. c.setBackground(bg);
  136. c.setForeground(fg);
  137. box.add(c);
  138. widget.update();
  139. widget.propertiesChanged();
  140. }
  141. else
  142. {
  143. JLabel label = new JLabel(token);
  144. label.setBackground(bg);
  145. label.setForeground(fg);
  146. box.add(label);
  147. }
  148. }
  149. currentBar = statusBar;
  150. }
  151. updateBufferStatus();
  152. updateMiscStatus();
  153. } //}}}
  154. //{{{ addNotify() method
  155. @Override
  156. public void addNotify()
  157. {
  158. super.addNotify();
  159. VFSManager.getIOThreadPool().addProgressListener(this);
  160. } //}}}
  161. //{{{ removeNotify() method
  162. @Override
  163. public void removeNotify()
  164. {
  165. super.removeNotify();
  166. VFSManager.getIOThreadPool().removeProgressListener(this);
  167. } //}}}
  168. //{{{ WorkThreadListener implementation
  169. //{{{ statusUpdate() method
  170. public void statusUpdate(final WorkThreadPool threadPool, int threadIndex)
  171. {
  172. SwingUtilities.invokeLater(new Runnable()
  173. {
  174. public void run()
  175. {
  176. // don't obscure existing message
  177. if(message != null && !"".equals(message.getText().trim())
  178. && !currentMessageIsIO)
  179. return;
  180. int requestCount = threadPool.getRequestCount();
  181. if(requestCount == 0)
  182. {
  183. setMessageAndClear(jEdit.getProperty(
  184. "view.status.io.done"));
  185. currentMessageIsIO = true;
  186. }
  187. else if(requestCount == 1)
  188. {
  189. setMessage(jEdit.getProperty(
  190. "view.status.io-1"));
  191. currentMessageIsIO = true;
  192. }
  193. else
  194. {
  195. Object[] args = {requestCount};
  196. setMessage(jEdit.getProperty(
  197. "view.status.io",args));
  198. currentMessageIsIO = true;
  199. }
  200. }
  201. });
  202. } //}}}
  203. //{{{ progressUpdate() method
  204. public void progressUpdate(WorkThreadPool threadPool, int threadIndex)
  205. {
  206. } //}}}
  207. //}}}
  208. //{{{ getMessage() method
  209. /**
  210. * Returns the current message.
  211. *
  212. * @return the current message
  213. * @since jEdit 4.4pre1
  214. */
  215. public String getMessage()
  216. {
  217. return message.getText();
  218. } //}}}
  219. //{{{ setMessageAndClear() method
  220. /**
  221. * Show a message for a short period of time.
  222. * @param message The message
  223. * @since jEdit 3.2pre5
  224. */
  225. public void setMessageAndClear(String message)
  226. {
  227. setMessage(message);
  228. tempTimer = new Timer(0,new ActionListener()
  229. {
  230. public void actionPerformed(ActionEvent evt)
  231. {
  232. // so if view is closed in the meantime...
  233. if(isShowing())
  234. setMessage(null);
  235. }
  236. });
  237. tempTimer.setInitialDelay(10000);
  238. tempTimer.setRepeats(false);
  239. tempTimer.start();
  240. } //}}}
  241. //{{{ setMessage() method
  242. /**
  243. * Displays a status message.
  244. * @param message the message to display, it can be null
  245. */
  246. public void setMessage(String message)
  247. {
  248. if(tempTimer != null)
  249. {
  250. tempTimer.stop();
  251. tempTimer = null;
  252. }
  253. setMessageComponent(this.message);
  254. if(message == null)
  255. {
  256. if(view.getMacroRecorder() != null)
  257. this.message.setText(jEdit.getProperty("view.status.recording"));
  258. else
  259. this.message.setText(" ");
  260. }
  261. else
  262. this.message.setText(message);
  263. } //}}}
  264. //{{{ setMessageComponent() method
  265. public void setMessageComponent(Component comp)
  266. {
  267. currentMessageIsIO = false;
  268. if (comp == null || messageComp == comp)
  269. {
  270. return;
  271. }
  272. messageComp = comp;
  273. panel.add(BorderLayout.CENTER, messageComp);
  274. } //}}}
  275. //{{{ updateCaretStatus() method
  276. public void updateCaretStatus()
  277. {
  278. if (showCaretStatus)
  279. {
  280. Buffer buffer = view.getBuffer();
  281. if(!buffer.isLoaded() ||
  282. /* can happen when switching buffers sometimes */
  283. buffer != view.getTextArea().getBuffer())
  284. {
  285. caretStatus.setText(" ");
  286. return;
  287. }
  288. JEditTextArea textArea = view.getTextArea();
  289. int caretPosition = textArea.getCaretPosition();
  290. int currLine = textArea.getCaretLine();
  291. // there must be a better way of fixing this...
  292. // the problem is that this method can sometimes
  293. // be called as a result of a text area scroll
  294. // event, in which case the caret position has
  295. // not been updated yet.
  296. if(currLine >= buffer.getLineCount())
  297. return; // hopefully another caret update will come?
  298. int start = textArea.getLineStartOffset(currLine);
  299. int dot = caretPosition - start;
  300. if(dot < 0)
  301. return;
  302. int bufferLength = buffer.getLength();
  303. buffer.getText(start,dot,seg);
  304. int virtualPosition = StandardUtilities.getVirtualWidth(seg,
  305. buffer.getTabSize());
  306. // for GC
  307. seg.array = null;
  308. seg.count = 0;
  309. if (jEdit.getBooleanProperty("view.status.show-caret-linenumber", true))
  310. {
  311. buf.append(currLine + 1);
  312. buf.append(',');
  313. }
  314. if (jEdit.getBooleanProperty("view.status.show-caret-dot", true))
  315. {
  316. buf.append(dot + 1);
  317. }
  318. if (jEdit.getBooleanProperty("view.status.show-caret-virtual", true) &&
  319. virtualPosition != dot)
  320. {
  321. buf.append('-');
  322. buf.append(virtualPosition + 1);
  323. }
  324. if (buf.length() > 0)
  325. {
  326. buf.append(' ');
  327. }
  328. if (jEdit.getBooleanProperty("view.status.show-caret-offset", true) &&
  329. jEdit.getBooleanProperty("view.status.show-caret-bufferlength", true))
  330. {
  331. buf.append('(');
  332. buf.append(caretPosition);
  333. buf.append('/');
  334. buf.append(bufferLength);
  335. buf.append(')');
  336. }
  337. else if (jEdit.getBooleanProperty("view.status.show-caret-offset", true))
  338. {
  339. buf.append('(');
  340. buf.append(caretPosition);
  341. buf.append(')');
  342. }
  343. else if (jEdit.getBooleanProperty("view.status.show-caret-bufferlength", true))
  344. {
  345. buf.append('(');
  346. buf.append(bufferLength);
  347. buf.append(')');
  348. }
  349. caretStatus.setText(buf.toString());
  350. buf.setLength(0);
  351. }
  352. } //}}}
  353. //{{{ updateBufferStatus() method
  354. public void updateBufferStatus()
  355. {
  356. wrapWidget.update();
  357. lineSepWidget.update();
  358. modeWidget.update();
  359. foldWidget.update();
  360. encodingWidget.update();
  361. } //}}}
  362. //{{{ updateMiscStatus() method
  363. public void updateMiscStatus()
  364. {
  365. multiSelectWidget.update();
  366. rectSelectWidget.update();
  367. overwriteWidget.update();
  368. } //}}}
  369. //{{{ Private members
  370. private String currentBar;
  371. private final View view;
  372. private final JPanel panel;
  373. private final Box box;
  374. private final ToolTipLabel caretStatus;
  375. private Component messageComp;
  376. private final JLabel message;
  377. private final Widget modeWidget;
  378. private final Widget foldWidget;
  379. private final Widget encodingWidget;
  380. private final Widget wrapWidget;
  381. private final Widget multiSelectWidget;
  382. private final Widget rectSelectWidget;
  383. private final Widget overwriteWidget;
  384. private final Widget lineSepWidget;
  385. /* package-private for speed */ StringBuilder buf = new StringBuilder();
  386. private Timer tempTimer;
  387. private boolean currentMessageIsIO;
  388. private final Segment seg = new Segment();
  389. private boolean showCaretStatus;
  390. //}}}
  391. static final String caretTestStr = "9999,999-999 (99999999/99999999)";
  392. //{{{ getWidget() method
  393. private Widget getWidget(String name)
  394. {
  395. if ("mode".equals(name))
  396. return modeWidget;
  397. if ("fold".equals(name))
  398. return foldWidget;
  399. if ("encoding".equals(name))
  400. return encodingWidget;
  401. if ("wrap".equals(name))
  402. return wrapWidget;
  403. if ("multiSelect".equals(name))
  404. return multiSelectWidget;
  405. if ("rectSelect".equals(name))
  406. return rectSelectWidget;
  407. if ("overwrite".equals(name))
  408. return overwriteWidget;
  409. if ("lineSep".equals(name))
  410. return lineSepWidget;
  411. return _getWidget(name);
  412. } //}}}
  413. //{{{ _getWidget() method
  414. private Widget _getWidget(String name)
  415. {
  416. StatusWidgetFactory widgetFactory =
  417. (StatusWidgetFactory) ServiceManager.getService("org.gjt.sp.jedit.gui.statusbar.StatusWidget", name);
  418. if (widgetFactory == null)
  419. {
  420. return null;
  421. }
  422. return widgetFactory.getWidget(view);
  423. } //}}}
  424. //{{{ MouseHandler class
  425. private class MouseHandler extends MouseAdapter
  426. {
  427. @Override
  428. public void mouseClicked(MouseEvent evt)
  429. {
  430. Object source = evt.getSource();
  431. if(source == caretStatus && evt.getClickCount() == 2)
  432. {
  433. view.getTextArea().showGoToLineDialog();
  434. }
  435. }
  436. } //}}}
  437. }