001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.workbench.ui;
034:
035: import java.awt.BorderLayout;
036: import java.awt.Color;
037: import java.awt.event.ActionEvent;
038: import java.awt.event.ActionListener;
039: import java.beans.PropertyVetoException;
040:
041: import javax.swing.JButton;
042: import javax.swing.JInternalFrame;
043: import javax.swing.Timer;
044: import javax.swing.event.InternalFrameAdapter;
045: import javax.swing.event.InternalFrameEvent;
046:
047: import com.vividsolutions.jump.util.StringUtil;
048: import com.vividsolutions.jump.workbench.ui.images.IconLoader;
049:
050: /**
051: * At the bottom-left corner is an MS-Access-style record navigator for
052: * cycling through the history of documents. A new document is created when
053: * #createNewDocument is called.
054: * <P>
055: * Methods can be called regardless of whether or not the current thread is the
056: * AWT event dispatching thread.
057: */
058:
059: //Rather inefficient -- uses JEditorPane#setText rather than
060: //HTMLDocument#insertBeforeEnd. But #insertBeforeEnd is buggy (see Java Bug
061: //4496801) [Jon Aquino].
062: public class HTMLFrame extends JInternalFrame {
063:
064: private WorkbenchFrame workbenchFrame;
065: private BorderLayout borderLayout1 = new BorderLayout();
066:
067: protected boolean alwaysOnTop = false;
068: private boolean notifyingUser = false;
069: private JButton button = null;
070:
071: /**
072: * Do not use this constructor. It is here to satisfy JBuilder's GUI
073: * designer when it opens WorkbenchFrame.
074: */
075: public HTMLFrame() {
076: }
077:
078: private HTMLPanel panel = new HTMLPanel() {
079: protected void setEditorPaneText() {
080: super .setEditorPaneText();
081: notifyUser();
082: }
083: };
084:
085: public HTMLFrame(final WorkbenchFrame workbenchFrame) {
086: this .workbenchFrame = workbenchFrame;
087: try {
088: jbInit();
089: } catch (Exception e) {
090: e.printStackTrace();
091: }
092: this .setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
093: addInternalFrameListener(new InternalFrameAdapter() {
094: public void internalFrameClosing(InternalFrameEvent e) {
095: try {
096: workbenchFrame.removeInternalFrame(HTMLFrame.this );
097: } catch (Exception x) {
098: workbenchFrame.handleThrowable(x);
099: }
100: }
101:
102: public void internalFrameOpened(InternalFrameEvent e) {
103: panel.getRecordPanel().updateAppearance();
104: }
105: });
106: setSize(500, 300);
107: }
108:
109: public void setCurrentIndex(int index) {
110: panel.setCurrentIndex(index);
111: }
112:
113: public void setTitle(String s) {
114: super .setTitle(s);
115: }
116:
117: public void setBackgroundColor(Color color) {
118: panel.setBackgroundColor(color);
119: }
120:
121: public Color getBackgroundColor() {
122: return panel.getBackgroundColor();
123: }
124:
125: public int getRecordCount() {
126: return panel.getRecordCount();
127: }
128:
129: public int getCurrentIndex() {
130: return panel.getCurrentIndex();
131: }
132:
133: public void createNewDocument() {
134: panel.createNewDocument();
135: }
136:
137: public void setRecordNavigationControlVisible(boolean visible) {
138: panel.setRecordNavigationControlVisible(visible);
139: }
140:
141: /**
142: * @deprecated Use #createNewDocument instead.
143: */
144: public void clear() {
145: panel.createNewDocument();
146: }
147:
148: /**
149: * Brings the output window to the front. Adds it to the desktop if
150: * necessary.
151: */
152: public void surface() {
153: if (!workbenchFrame.hasInternalFrame(this )) {
154: workbenchFrame.addInternalFrame(this , alwaysOnTop, true);
155: }
156:
157: workbenchFrame.activateFrame(this );
158:
159: if (isIcon()) {
160: try {
161: setIcon(false);
162: } catch (PropertyVetoException e) {
163: workbenchFrame.log(StringUtil.stackTrace(e));
164: }
165: }
166:
167: moveToFront();
168: }
169:
170: /**
171: *@param level 1, 2, 3, ...
172: */
173: public void addHeader(int level, String text) {
174: panel.addHeader(level, text);
175: }
176:
177: public void addField(String label, String value) {
178: panel.addField(label, value);
179: }
180:
181: public void addField(String label, String value, String units) {
182: panel.addField(label, value, units);
183: }
184:
185: /**
186: * Appends a line of non-HTML text to the frame. Text is assumed to be non-HTML, and is
187: * HTML-escaped to avoid control-char conflict.
188: * @param text
189: */
190: public void addText(String text) {
191: panel.addText(text);
192: }
193:
194: /**
195: * Appends HTML text to the frame.
196: * @param html the HTML to append
197: */
198: public void append(final String html) {
199: panel.append(html);
200: }
201:
202: public void setButton(JButton button) {
203: this .button = button;
204: }
205:
206: private void setButtonHighlighted(boolean highlighted) {
207: if (button == null) {
208: return;
209: }
210:
211: button.setIcon(highlighted ? IconLoader.icon("Frame2.gif")
212: : IconLoader.icon("Frame.gif"));
213: }
214:
215: private void notifyUser() {
216: if (notifyingUser) {
217: return;
218: }
219:
220: if (button == null) {
221: return;
222: }
223:
224: notifyingUser = true;
225: new Timer(500, new ActionListener() {
226: private int tickCount = 0;
227:
228: public void actionPerformed(ActionEvent e) {
229: tickCount++;
230: setButtonHighlighted((tickCount % 2) == 0);
231:
232: if (tickCount == 8) {
233: Timer timer = (Timer) e.getSource();
234: timer.stop();
235: notifyingUser = false;
236: setButtonHighlighted(!isSelected());
237: }
238: }
239: }).start();
240: }
241:
242: private void jbInit() throws Exception {
243: setTitle("Output");
244: this
245: .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter() {
246: public void internalFrameActivated(
247: InternalFrameEvent e) {
248: this _internalFrameActivated(e);
249: }
250: });
251: this .getContentPane().setLayout(borderLayout1);
252: getContentPane().add(panel, BorderLayout.CENTER);
253: this .setResizable(true);
254: this .setClosable(true);
255: this .setMaximizable(true);
256: this .setIconifiable(true);
257: panel.getOKButton().addActionListener(new ActionListener() {
258: public void actionPerformed(ActionEvent e) {
259: okButton_actionPerformed(e);
260: }
261: });
262: }
263:
264: public void scrollToTop() {
265: panel.scrollToTop();
266: }
267:
268: void okButton_actionPerformed(ActionEvent e) {
269: doDefaultCloseAction();
270: }
271:
272: void this _internalFrameActivated(InternalFrameEvent e) {
273: setButtonHighlighted(false);
274: }
275: }
|