diff --git a/source/org/thdl/util/StatusBar.java b/source/org/thdl/util/StatusBar.java new file mode 100644 index 0000000..262240c --- /dev/null +++ b/source/org/thdl/util/StatusBar.java @@ -0,0 +1,104 @@ +/* +The contents of this file are subject to the THDL Open Community License +Version 1.0 (the "License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License on the THDL web site +(http://www.thdl.org/). + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +License for the specific terms governing rights and limitations under the +License. + +The Initial Developer of this software is the Tibetan and Himalayan Digital +Library (THDL). Portions created by the THDL are Copyright 2001 THDL. +All Rights Reserved. + +Contributor(s): ______________________________________. +*/ + +package org.thdl.util; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.Stack; + +/** A StatusBar can be added to a component, typically to the bottom + of it, in order to show the user the status of the program. There + are methods to change the status, and there are actually a LIFO + stack of status messages if you wish to use them. */ +public class StatusBar extends JPanel { + /** The current status is the String on top of the stack. */ + private Stack statuses; + + private JLabel label; + + /** Creates a status bar. */ + public StatusBar() { + super(); + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + statuses = new Stack(); + label = new JLabel("Visit 'http://www.thdl.org/'."); + label.setHorizontalAlignment(SwingConstants.LEFT); + add(label); + } + + /** Creates a status bar with the initial message msg. */ + public StatusBar(String msg) { + this(); + pushStatus(msg); + } + + /** Sets the status to msg, replacing the current status message. */ + public void replaceStatus(String msg) throws NullPointerException { + if (msg == null) + throw new NullPointerException(); + if (!statuses.empty()) + statuses.pop(); + statuses.push(msg); + updateLabel(); + } + + /** Sets the status to msg, leaving the previous status on the + stack. */ + public void pushStatus(String msg) throws NullPointerException { + if (msg == null) + throw new NullPointerException(); + statuses.push(msg); + updateLabel(); + } + + /** Removes the current status message. If the stack is then + empty, the message will be the empty string. Otherwise, the + message will be the message then topmost on the stack. + + @throws NullPointerException if msg is null + */ + public void popStatus() { + if (!statuses.empty()) { + statuses.pop(); + updateLabel(); + } + } + + /** Returns the String currently displayed in the status bar. */ + public String currentStatus() { + return getMsgOnTopOfStack(); + } + + /** Returns the status message on top of the stack, or "" if the + stack is empty. */ + private String getMsgOnTopOfStack() { + if (statuses.empty()) + return ""; + else + return (String)statuses.peek(); + } + + /** Sets the displayed text to what's on top of the stack, or "" + if the stack is empty. */ + private void updateLabel() { + label.setText(" " + // FIXME: nasty hack to make everything show up + getMsgOnTopOfStack()); + } +} diff --git a/source/org/thdl/util/ThdlDebug.java b/source/org/thdl/util/ThdlDebug.java index 759bff6..e35c304 100644 --- a/source/org/thdl/util/ThdlDebug.java +++ b/source/org/thdl/util/ThdlDebug.java @@ -20,6 +20,7 @@ package org.thdl.util; import java.io.PrintStream; import java.io.FileOutputStream; +import java.io.File; import org.thdl.util.TeeStream; @@ -119,11 +120,68 @@ public class ThdlDebug { /** Sets it up so that a call to System.out or System.err prints * to standard output/error but ALSO prints to the log file named - * logFile. */ - public static void attemptToSetUpLogFile(String logFile) { + * (prefix + suffix). Be sure the log file name is a relative + * path, because we may put this file into an arbitrary + * directory. */ + public static void attemptToSetUpLogFile(String prefix, String suffix) { + final String tempDirProp = "thdl.use.temp.file.directory.for.log"; + final String logDirProp = "thdl.log.directory"; + File logFile = null; + + if (Boolean.getBoolean(tempDirProp)) { + /* The log file won't be named 'jskad.log', it'll be named + 'jskad-SAKFJDS3134.log', and they'll all just pile up, + because we don't deleteOnExit. */ + + /* First, ensure that the user hasn't set conflicting options. */ + try { + if (null != System.getProperty("thdl.log.directory")) + throw new Error("You cannot set the property " + + tempDirProp + " and the property " + + logDirProp + + " at the same time because they both affect the same thing, the location of the log file."); + } catch (Exception e) { + /* SecurityExceptions, e.g., will trigger this. */ + + /* Leave logDir null. */ + } catch (Error e) { + throw e; + } + + /* Now, create the temporary file. */ + try { + logFile = File.createTempFile(prefix, suffix); + } catch (Exception e) { + noteIffyCode(); + } + } else { + /* If the user has set the system property + thdl.log.directory, respect their choice. */ + String logDir = null; + try { + logDir = System.getProperty(logDirProp); + } catch (Exception e) { + /* SecurityExceptions, e.g., will trigger this. We + leave logDir null. */ + noteIffyCode(); + } + if (null != logDir) { + logFile = new File(logDir, prefix + suffix); + } else { + /* Create the log file in the current directory. For + Windows users, this is often the desktop. + + FIXME: by default, put the log file in a smarter place. + */ + logFile = new File(prefix + suffix); + } + } try { PrintStream logFilePrintStream = new PrintStream(new FileOutputStream(logFile)); + System.out.println("Logging to " + + logFile.getAbsolutePath().toString() + + "; please include the contents of this file in any bug reports."); PrintStream psOut = new TeeStream(System.out, logFilePrintStream); PrintStream psErr = new TeeStream(System.err, logFilePrintStream); System.setErr(psErr);