001: /*
002: * FilesChangedDialog.java - Files changed on disk
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 2003 Slava Pestov
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022:
023: package org.gjt.sp.jedit.gui;
024:
025: //{{{ Imports
026: import javax.swing.border.*;
027: import javax.swing.event.*;
028: import javax.swing.tree.*;
029: import javax.swing.*;
030: import java.awt.event.*;
031: import java.awt.*;
032: import org.gjt.sp.jedit.*;
033:
034: //}}}
035:
036: /**
037: * Files changed on disk dialog.
038: *
039: * @author Slava Pestov
040: * @version $Id: FilesChangedDialog.java 8190 2006-12-07 07:58:34Z kpouer $
041: */
042: public class FilesChangedDialog extends EnhancedDialog {
043: //{{{ FilesChangedDialog constructor
044: public FilesChangedDialog(View view, int[] states,
045: boolean alreadyReloaded) {
046: super (view, jEdit.getProperty("files-changed.title"), false);
047:
048: this .view = view;
049:
050: JPanel content = new JPanel(new BorderLayout(12, 12));
051: content.setBorder(new EmptyBorder(12, 12, 12, 12));
052: setContentPane(content);
053:
054: Box iconBox = new Box(BoxLayout.Y_AXIS);
055: iconBox.add(new JLabel(UIManager
056: .getIcon("OptionPane.warningIcon")));
057: iconBox.add(Box.createGlue());
058: content.add(BorderLayout.WEST, iconBox);
059:
060: JPanel centerPanel = new JPanel(new BorderLayout());
061:
062: JLabel label = new JLabel(jEdit
063: .getProperty("files-changed.caption"));
064: label.setBorder(new EmptyBorder(0, 0, 6, 0));
065: centerPanel.add(BorderLayout.NORTH, label);
066:
067: DefaultMutableTreeNode deleted = new DefaultMutableTreeNode(
068: jEdit.getProperty("files-changed.deleted"), true);
069: DefaultMutableTreeNode changed = new DefaultMutableTreeNode(
070: jEdit.getProperty("files-changed.changed"
071: + (alreadyReloaded ? "-auto" : "")), true);
072: DefaultMutableTreeNode changedDirty = new DefaultMutableTreeNode(
073: jEdit.getProperty("files-changed.changed-dirty"
074: + (alreadyReloaded ? "-auto" : "")), true);
075: Buffer[] buffers = jEdit.getBuffers();
076: for (int i = 0; i < states.length; i++) {
077: Buffer buffer = buffers[i];
078: DefaultMutableTreeNode addTo;
079: switch (states[i]) {
080: case Buffer.FILE_DELETED:
081: addTo = deleted;
082: break;
083: case Buffer.FILE_CHANGED:
084: addTo = buffer.isDirty() ? changedDirty : changed;
085: break;
086: default:
087: addTo = null;
088: break;
089: }
090:
091: if (addTo != null) {
092: addTo.add(new DefaultMutableTreeNode(buffer.getPath()));
093: }
094: }
095:
096: root = new DefaultMutableTreeNode("", true);
097: if (deleted.getChildCount() != 0) {
098: root.add(deleted);
099: }
100: if (changed.getChildCount() != 0) {
101: root.add(changed);
102: }
103: if (changedDirty.getChildCount() != 0) {
104: root.add(changedDirty);
105: }
106:
107: bufferTreeModel = new DefaultTreeModel(root);
108: bufferTree = new JTree(bufferTreeModel);
109: bufferTree.setRootVisible(false);
110: bufferTree.setVisibleRowCount(10);
111: bufferTree.setCellRenderer(new Renderer());
112: bufferTree.getSelectionModel().addTreeSelectionListener(
113: new TreeHandler());
114: bufferTree.getSelectionModel().setSelectionMode(
115: TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
116:
117: centerPanel.add(BorderLayout.CENTER,
118: new JScrollPane(bufferTree));
119:
120: content.add(BorderLayout.CENTER, centerPanel);
121:
122: Box buttons = new Box(BoxLayout.X_AXIS);
123: buttons.add(Box.createGlue());
124:
125: if (!alreadyReloaded) {
126: selectAll = new JButton(jEdit
127: .getProperty("files-changed.select-all"));
128: selectAll.setMnemonic(jEdit.getProperty(
129: "files-changed.select-all.mnemonic").charAt(0));
130: buttons.add(selectAll);
131: selectAll.addActionListener(new ActionHandler());
132:
133: buttons.add(Box.createHorizontalStrut(12));
134:
135: reload = new JButton(jEdit
136: .getProperty("files-changed.reload"));
137: reload.setMnemonic(jEdit.getProperty(
138: "files-changed.reload.mnemonic").charAt(0));
139: buttons.add(reload);
140: reload.addActionListener(new ActionHandler());
141:
142: buttons.add(Box.createHorizontalStrut(12));
143:
144: ignore = new JButton(jEdit
145: .getProperty("files-changed.ignore"));
146: ignore.setMnemonic(jEdit.getProperty(
147: "files-changed.ignore.mnemonic").charAt(0));
148: buttons.add(ignore);
149: ignore.addActionListener(new ActionHandler());
150:
151: buttons.add(Box.createHorizontalStrut(12));
152: }
153:
154: close = new JButton(jEdit.getProperty("common.close"));
155: getRootPane().setDefaultButton(close);
156: buttons.add(close);
157: close.addActionListener(new ActionHandler());
158:
159: buttons.add(Box.createGlue());
160:
161: content.add(BorderLayout.SOUTH, buttons);
162:
163: bufferTree.expandPath(new TreePath(
164: new Object[] { root, deleted }));
165: bufferTree.expandPath(new TreePath(
166: new Object[] { root, changed }));
167: bufferTree.expandPath(new TreePath(new Object[] { root,
168: changedDirty }));
169:
170: GUIUtilities.requestFocus(this , bufferTree);
171:
172: updateEnabled();
173:
174: pack();
175: setLocationRelativeTo(view);
176: setVisible(true);
177: } //}}}
178:
179: //{{{ ok() method
180: public void ok() {
181: dispose();
182: } //}}}
183:
184: //{{{ cancel() method
185: public void cancel() {
186: dispose();
187: } //}}}
188:
189: //{{{ Private members
190: private View view;
191: private JTree bufferTree;
192: private DefaultTreeModel bufferTreeModel;
193: private DefaultMutableTreeNode root;
194: private JButton selectAll;
195:
196: // hack so that 'select all' does not change current buffer
197: private boolean selectAllInProgress;
198:
199: private JButton reload;
200: private JButton ignore;
201: private JButton close;
202:
203: //{{{ updateEnabled() method
204: private void updateEnabled() {
205: TreePath[] paths = bufferTree.getSelectionPaths();
206: boolean enabled = false;
207: if (paths != null) {
208: for (int i = 0; i < paths.length; i++) {
209: Object[] path = paths[i].getPath();
210: if (path.length == 3)
211: enabled = true;
212: }
213: }
214:
215: if (reload != null)
216: reload.setEnabled(enabled);
217:
218: if (ignore != null)
219: ignore.setEnabled(enabled);
220: } //}}}
221:
222: //{{{ selectAll() method
223: private void selectAll() {
224: selectAllInProgress = true;
225:
226: TreeNode[] path = new TreeNode[3];
227: path[0] = root;
228: for (int i = 0; i < root.getChildCount(); i++) {
229: DefaultMutableTreeNode node = (DefaultMutableTreeNode) root
230: .getChildAt(i);
231: path[1] = node;
232: for (int j = 0; j < node.getChildCount(); j++) {
233: DefaultMutableTreeNode node2 = (DefaultMutableTreeNode) node
234: .getChildAt(j);
235: path[2] = node2;
236: bufferTree.getSelectionModel().addSelectionPath(
237: new TreePath(path));
238: }
239: }
240:
241: selectAllInProgress = false;
242:
243: updateEnabled();
244: } //}}}
245:
246: //{{{ reload() method
247: private void action(String action) {
248: TreePath[] paths = bufferTree.getSelectionPaths();
249: if (paths == null || paths.length == 0)
250: return;
251:
252: int row = bufferTree.getRowForPath(paths[0]);
253:
254: for (int i = 0; i < paths.length; i++) {
255: TreePath path = paths[i];
256:
257: // is it a header?
258: if (path.getPathCount() == 2)
259: continue;
260:
261: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
262: .getLastPathComponent();
263: if (!(node.getUserObject() instanceof String)) {
264: return;
265: }
266:
267: Buffer buffer = jEdit.getBuffer((String) node
268: .getUserObject());
269: if (buffer == null)
270: return;
271:
272: if ("RELOAD".equals(action))
273: buffer.reload(view);
274: else {
275: buffer.setAutoReload(false);
276: buffer.setAutoReloadDialog(false);
277: }
278:
279: DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node
280: .getParent();
281: parent.remove(node);
282: }
283:
284: bufferTreeModel.reload(root);
285:
286: // we expand those that are non-empty, and
287: // remove those that are empty
288: TreeNode[] nodes = { root, null };
289:
290: // remove empty category branches
291: for (int j = 0; j < root.getChildCount(); j++) {
292: DefaultMutableTreeNode node = (DefaultMutableTreeNode) root
293: .getChildAt(j);
294: if (root.getChildAt(j).getChildCount() == 0) {
295: root.remove(j);
296: j--;
297: } else {
298: nodes[1] = node;
299: bufferTree.expandPath(new TreePath(nodes));
300: }
301: }
302:
303: if (root.getChildCount() == 0)
304: dispose();
305: else {
306: if (row >= bufferTree.getRowCount())
307: row = bufferTree.getRowCount() - 1;
308: TreePath path = bufferTree.getPathForRow(row);
309: if (path.getPathCount() == 2) {
310: // selected a header; skip to the next row
311: bufferTree.setSelectionRow(row + 1);
312: } else
313: bufferTree.setSelectionPath(path);
314: }
315: } //}}}
316:
317: //}}}
318:
319: //{{{ ActionHandler class
320: class ActionHandler implements ActionListener {
321: public void actionPerformed(ActionEvent evt) {
322: Object source = evt.getSource();
323: if (source == selectAll)
324: selectAll();
325: else if (source == reload)
326: action("RELOAD");
327: else if (source == close)
328: dispose();
329: else if (source == ignore)
330: action("IGNORE");
331: }
332: } //}}}
333:
334: //{{{ TreeHandler class
335: class TreeHandler implements TreeSelectionListener {
336: public void valueChanged(TreeSelectionEvent evt) {
337: if (selectAllInProgress)
338: return;
339:
340: updateEnabled();
341:
342: TreePath[] paths = bufferTree.getSelectionPaths();
343: if (paths == null || paths.length == 0)
344: return;
345: TreePath path = paths[paths.length - 1];
346: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
347: .getLastPathComponent();
348: if (node.getUserObject() instanceof String) {
349: Buffer buffer = jEdit.getBuffer((String) node
350: .getUserObject());
351: if (buffer != null)
352: view.goToBuffer(buffer);
353: }
354: }
355: } //}}}
356:
357: //{{{ Renderer class
358: static class Renderer extends DefaultTreeCellRenderer {
359: Renderer() {
360: entryFont = UIManager.getFont("Tree.font");
361: if (entryFont == null)
362: entryFont = jEdit
363: .getFontProperty("metal.secondary.font");
364: groupFont = entryFont.deriveFont(Font.BOLD);
365: }
366:
367: public Component getTreeCellRendererComponent(JTree tree,
368: Object value, boolean selected, boolean expanded,
369: boolean leaf, int row, boolean hasFocus) {
370: super .getTreeCellRendererComponent(tree, value, selected,
371: expanded, leaf, row, hasFocus);
372:
373: DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
374:
375: if (node.getParent() == tree.getModel().getRoot())
376: setFont(groupFont);
377: else
378: setFont(entryFont);
379:
380: setIcon(null);
381:
382: return this ;
383: }
384:
385: private Font entryFont;
386: private Font groupFont;
387: } //}}}
388: }
|