001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.ui;
038:
039: import javax.swing.*;
040: import javax.swing.border.LineBorder;
041: import javax.swing.border.EmptyBorder;
042: import java.awt.*;
043: import java.util.LinkedList;
044: import edu.rice.cs.drjava.model.OpenDefinitionsDocument;
045: import edu.rice.cs.drjava.DrJava;
046: import edu.rice.cs.drjava.config.*;
047: import edu.rice.cs.drjava.CodeStatus;
048: import edu.rice.cs.util.swing.DisplayManager;
049: import edu.rice.cs.util.StringOps;
050:
051: /** This class extends a Swing view class. Hence it should only be accessed from the event-handling thread. */
052: public class RecentDocFrame extends JWindow {
053: // MainFrame
054: MainFrame _frame;
055:
056: // The manager that gives filenames and icons
057: DisplayManager<OpenDefinitionsDocument> _displayManager = _frame
058: .getOddDisplayManager30();
059:
060: // the label that shows the icon and filename
061: JLabel _label;
062: // the panel that holds the label and textpane
063: JPanel _panel;
064: // the pane that holds the sample of source
065: JTextPane _textpane;
066: // the scroller that holds the text
067: JScrollPane _scroller;
068: // the currently selected document
069: int _current = 0;
070:
071: int _padding = 4;
072:
073: LinkedList<OpenDefinitionsDocument> _docs = new LinkedList<OpenDefinitionsDocument>();
074:
075: private OptionListener<Color> _colorListener = new OptionListener<Color>() {
076: public void optionChanged(OptionEvent<Color> oce) {
077: updateFontColor();
078: }
079: };
080:
081: private OptionListener<Font> _fontListener = new OptionListener<Font>() {
082: public void optionChanged(OptionEvent<Font> oce) {
083: updateFontColor();
084: }
085: };
086:
087: private OptionListener<Boolean> _antialiasListener = new OptionListener<Boolean>() {
088: public void optionChanged(OptionEvent<Boolean> oce) {
089: updateFontColor();
090: }
091: };
092:
093: private OptionListener<Boolean> _showSourceListener = new OptionListener<Boolean>() {
094: public void optionChanged(OptionEvent<Boolean> oce) {
095: _showSource = oce.value;
096: }
097: };
098:
099: /* if the pane should antialias itself */
100: boolean _antiAliasText = false;
101:
102: /* if we should show source code when switching */
103: boolean _showSource;
104:
105: public RecentDocFrame(MainFrame f) {
106: super ();
107: _frame = f;
108: _current = 0;
109: _label = new JLabel("...") {
110: // Enable anti-aliased text by overriding paintComponent.
111: protected void paintComponent(Graphics g) {
112: if (_antiAliasText && g instanceof Graphics2D) {
113: Graphics2D g2d = (Graphics2D) g;
114: g2d.setRenderingHint(
115: RenderingHints.KEY_TEXT_ANTIALIASING,
116: RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
117: }
118: super .paintComponent(g);
119: }
120: };
121: _panel = new JPanel();
122: _scroller = new JScrollPane();
123: _textpane = new JTextPane() {
124: // Enable anti-aliased text by overriding paintComponent.
125: protected void paintComponent(Graphics g) {
126: if (_antiAliasText && g instanceof Graphics2D) {
127: Graphics2D g2d = (Graphics2D) g;
128: g2d.setRenderingHint(
129: RenderingHints.KEY_TEXT_ANTIALIASING,
130: RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
131: }
132: super .paintComponent(g);
133: }
134: };
135:
136: _textpane.setText("...");
137: _scroller.getViewport().add(_textpane);
138: _scroller
139: .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
140: _scroller
141: .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
142: _scroller.setMaximumSize(new Dimension(300, 200));
143:
144: _panel.setLayout(new BorderLayout());
145: _panel.add(_label, BorderLayout.NORTH);
146: _panel.add(_scroller, BorderLayout.SOUTH);
147:
148: getContentPane().add(_panel);
149: pack();
150: updateFontColor();
151: _showSource = DrJava.getConfig().getSetting(
152: OptionConstants.SHOW_SOURCE_WHEN_SWITCHING);
153: DrJava.getConfig().addOptionListener(
154: OptionConstants.DEFINITIONS_BACKGROUND_COLOR,
155: _colorListener);
156: DrJava.getConfig().addOptionListener(
157: OptionConstants.DEFINITIONS_NORMAL_COLOR,
158: _colorListener);
159: DrJava.getConfig().addOptionListener(OptionConstants.FONT_MAIN,
160: _fontListener);
161: DrJava.getConfig().addOptionListener(
162: OptionConstants.TEXT_ANTIALIAS, _antialiasListener);
163: DrJava.getConfig().addOptionListener(
164: OptionConstants.SHOW_SOURCE_WHEN_SWITCHING,
165: _showSourceListener);
166: }
167:
168: private void updateFontColor() {
169: Font mainFont = DrJava.getConfig().getSetting(
170: OptionConstants.FONT_MAIN);
171: Color backColor = DrJava.getConfig().getSetting(
172: OptionConstants.DEFINITIONS_BACKGROUND_COLOR);
173: Color fontColor = DrJava.getConfig().getSetting(
174: OptionConstants.DEFINITIONS_NORMAL_COLOR);
175: /* make it bigger */
176: Font titleFont = mainFont.deriveFont((float) (mainFont
177: .getSize() + 3));
178: _antiAliasText = DrJava.getConfig().getSetting(
179: OptionConstants.TEXT_ANTIALIAS).booleanValue();
180:
181: _label.setForeground(fontColor);
182: _panel.setBackground(backColor);
183: _label.setFont(titleFont);
184: _textpane.setForeground(fontColor);
185: _textpane.setFont(mainFont);
186: ;
187: _textpane.setBackground(backColor);
188: _scroller.setBackground(backColor);
189: _scroller.setBorder(new EmptyBorder(0, 0, 0, 0));
190: _panel.setBorder(new LineBorder(fontColor, 1));
191: }
192:
193: /** Moves the document d to the beginning of the list if it's already in the list, or it adds it to the
194: * beginning if its not already in the list.
195: */
196: public void pokeDocument(OpenDefinitionsDocument d) {
197: if (_docs.contains(d)) {
198: _current = _docs.indexOf(d);
199: reset();
200: } else
201: _docs.addFirst(d);
202: }
203:
204: /** Removes the document from the list. */
205: public void closeDocument(OpenDefinitionsDocument d) {
206: _docs.remove(d);
207: }
208:
209: private void show(int _current) {
210: OpenDefinitionsDocument doc = _docs.get(_current);
211:
212: String text = getTextFor(doc);
213:
214: _label.setText(_displayManager.getName(doc));
215: _label.setIcon(_displayManager.getIcon(doc));
216:
217: if (text.length() > 0) {
218: // as wide as the text area wants, but only 200px high
219: _textpane.setText(text);
220: _scroller.setPreferredSize(_textpane
221: .getPreferredScrollableViewportSize());
222: if (_scroller.getPreferredSize().getHeight() > 200)
223: _scroller.setPreferredSize(new Dimension(
224: (int) _scroller.getPreferredSize().getWidth(),
225: 200));
226:
227: _scroller.setVisible(_showSource);
228: } else
229: _scroller.setVisible(false);
230:
231: Dimension d = _label.getMinimumSize();
232: d.setSize(d.getWidth() + _padding * 2, d.getHeight() + _padding
233: * 2);
234: _label.setPreferredSize(d);
235: _label.setHorizontalAlignment(SwingConstants.CENTER);
236: _label.setVerticalAlignment(SwingConstants.CENTER);
237: pack();
238: centerH();
239: }
240:
241: /** Sets the current document to be the next document in the list. */
242: public void next() {
243: if (_docs.size() > 0) {
244: _current++;
245: if (_current >= _docs.size())
246: _current = 0;
247: show(_current);
248: }
249: }
250:
251: /** Sets the current document to be the previous document in the list. */
252: public void prev() {
253: if (_docs.size() > 0) {
254: _current--;
255: if (_current < 0)
256: _current = _docs.size() - 1;
257: show(_current);
258: }
259: }
260:
261: private String getTextFor(OpenDefinitionsDocument doc) {
262: DefinitionsPane pane = _frame.getDefPaneGivenODD(doc);
263: String endl = "\n"; // was StringOps.EOL; but Swing uses '\n' for newLine
264: int loc = pane.getCaretPosition();
265: int start = loc;
266: int end = loc;
267: String text;
268: text = doc.getText();
269:
270: /* get the starting point of 2 lines up... */
271: for (int i = 0; i < 4; i++) {
272: if (start > 0)
273: start = text.lastIndexOf(endl, start - endl.length());
274: }
275: if (start == -1)
276: start = 0;
277:
278: // skip the end line, if we're at one
279: // if (doc.getLength() >= endl.length() && text.substring(start, start+endl.length()) == endl)
280: // start += endl.length();
281: if (doc.getLength() >= endl.length()
282: && text.substring(start, start + endl.length()).equals(
283: endl))
284: start += endl.length();
285: /* get the ending point 2 lines down */
286: int index;
287: for (int i = 0; i < 4; i++) {
288: if (end < doc.getLength()) {
289: index = text.indexOf(endl, end + endl.length());
290: if (index != -1)
291: end = index;
292: }
293: }
294: if (end < start)
295: end = start;
296: text = text.substring(start, end);
297: return text;
298: }
299:
300: /** Resets the frame to point to the first document in the list. */
301: public void first() {
302: _current = 0;
303: next();
304: }
305:
306: public void refreshColor() {
307: }
308:
309: /** Sets this frame as visible only if _docs is non empty. Also resets the frame accordingly */
310: public void setVisible(boolean v) {
311: centerH();
312: if (_docs.size() > 0) {
313: if (v) {
314: centerV();
315: refreshColor();
316: first();
317: } else
318: reset();
319: super .setVisible(v);
320: }
321: }
322:
323: /** Centers the frame in the screen. */
324: private void centerH() {
325: MainFrame.setPopupLoc(this , _frame);
326: }
327:
328: /** Centers the frame in the screen. */
329: private void centerV() {
330: Dimension screenSize = Toolkit.getDefaultToolkit()
331: .getScreenSize();
332: Dimension frameSize = getSize();
333: setLocation((int) getLocation().getX(),
334: (screenSize.height - frameSize.height) / 2);
335: }
336:
337: /** Moves the selected document to the front of the list. */
338: public void reset() {
339: if (_current < _docs.size())
340: _docs.addFirst(_docs.remove(_current));
341: }
342:
343: /** Returns null if the list is empty, or the currently prefered OpenDefinitionsDocument. */
344: public OpenDefinitionsDocument getDocument() {
345: if (_docs.size() > 0)
346: return _docs.getFirst();
347: return null;
348: }
349:
350: // private ImageIcon _getIconResource(String name) {
351: // URL url = RecentDocFrame.class.getResource("icons/" + name);
352: // if (url != null) return new ImageIcon(url);
353: // return null;
354: // }
355:
356: }
|