001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hssf.contrib.view;
019:
020: import java.awt.*;
021: import java.awt.event.*;
022: import java.io.*;
023: import javax.swing.*;
024: import javax.swing.table.*;
025: import javax.swing.event.*;
026:
027: import org.apache.poi.hssf.usermodel.*;
028:
029: /**
030: * This class presents the sheets to the user.
031: *
032: *
033: * @author Andrew C. Oliver
034: * @author Jason Height
035: */
036: public class SViewerPanel extends JPanel {
037: /** This field is the magic number to convert from a Character width to a
038: * java pixel width.
039: *
040: * When the "normal" font size in a workbook changes, this effects all
041: * of the heights and widths. Unfortunately there is no way to retrieve this
042: * information, hence the MAGIC number.
043: *
044: * This number may only work for the normal style font size of Arial size 10.
045: *
046: */
047: private static final int magicCharFactor = 7;
048: /** Reference to the woorkbook that is being displayed*/
049: private HSSFWorkbook wb;
050: /** Reference to the tabs component*/
051: private JTabbedPane sheetPane;
052: /** Reference to the cell renderer that is used to render all cells*/
053: private SVTableCellRenderer cellRenderer;
054: /** Reference to the cell editor that is used to edit all cells.
055: * Only constructed if editing is allowed
056: */
057: private SVTableCellEditor cellEditor;
058: /** Flag indicating if editing is allowed. Otherwise the viewer is in
059: * view only mode.
060: */
061: private boolean allowEdits;
062:
063: /**Construct the representation of the workbook*/
064: public SViewerPanel(HSSFWorkbook wb, boolean allowEdits) {
065: this .wb = wb;
066: this .allowEdits = allowEdits;
067:
068: initialiseGui();
069: }
070:
071: private void initialiseGui() {
072: cellRenderer = new SVTableCellRenderer(this .wb);
073: if (allowEdits)
074: cellEditor = new SVTableCellEditor(this .wb);
075:
076: //Initialise the Panel
077: sheetPane = new JTabbedPane(JTabbedPane.BOTTOM);
078:
079: if (allowEdits)
080: sheetPane.addMouseListener(createTabListener());
081: int sheetCount = wb.getNumberOfSheets();
082: for (int i = 0; i < sheetCount; i++) {
083: String sheetName = wb.getSheetName(i);
084: //Add the new sheet to the tabbed pane
085: sheetPane
086: .addTab(sheetName, makeSheetView(wb.getSheetAt(i)));
087: }
088: setLayout(new BorderLayout());
089: add(sheetPane, BorderLayout.CENTER);
090: }
091:
092: protected JComponent makeSheetView(HSSFSheet sheet) {
093: JTable sheetView = new JTable(new SVTableModel(sheet));
094: sheetView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
095: sheetView.setDefaultRenderer(HSSFCell.class, cellRenderer);
096: if (allowEdits)
097: sheetView.setDefaultEditor(HSSFCell.class, cellEditor);
098: JTableHeader header = sheetView.getTableHeader();
099: //Dont allow column reordering
100: header.setReorderingAllowed(false);
101: //Only allow column resizing if editing is allowed
102: header.setResizingAllowed(allowEdits);
103:
104: //Set the columns the correct size
105: TableColumnModel columns = sheetView.getColumnModel();
106: for (int i = 0; i < columns.getColumnCount(); i++) {
107: TableColumn column = columns.getColumn(i);
108: short width = sheet.getColumnWidth((short) i);
109: //256 is because the width is in 256ths of a character
110: column.setPreferredWidth(width / 256 * magicCharFactor);
111: }
112:
113: //Set the rows to the correct size
114: int rows = sheet.getPhysicalNumberOfRows();
115: Insets insets = cellRenderer.getInsets();
116: //Need to include the insets in the calculation of the row height to use.
117: int extraHeight = insets.bottom + insets.top;
118: for (int i = 0; i < rows; i++) {
119: HSSFRow row = sheet.getRow(i);
120: if (row == null) {
121: sheetView.setRowHeight(i, (int) sheet
122: .getDefaultRowHeightInPoints()
123: + extraHeight);
124: } else {
125: sheetView.setRowHeight(i, (int) row.getHeightInPoints()
126: + extraHeight);
127: }
128: }
129:
130: //Add the row header to the sheet
131: SVRowHeader rowHeader = new SVRowHeader(sheet, sheetView,
132: extraHeight);
133: JScrollPane scroll = new JScrollPane(sheetView);
134: scroll.setRowHeaderView(rowHeader);
135: return scroll;
136: }
137:
138: public void paint(Graphics g) {
139: //JMH I am only overriding this to get a picture of the time taken to paint
140: long start = System.currentTimeMillis();
141: super .paint(g);
142: long elapsed = System.currentTimeMillis() - start;
143: System.out.println("Paint time = " + elapsed);
144: }
145:
146: protected MouseListener createTabListener() {
147: return new TabListener();
148: }
149:
150: /** This class defines the default MouseListener that listens to
151: * mouse events in the tabbed pane
152: *
153: * The default is to popup a menu when the event occurs over a tab
154: */
155: private class TabListener implements MouseListener {
156: public JPopupMenu popup;
157:
158: public TabListener() {
159: popup = new JPopupMenu("Sheet");
160: popup.add(createInsertSheetAction());
161: popup.add(createDeleteSheetAction());
162: popup.add(createRenameSheetAction());
163: }
164:
165: protected Action createInsertSheetAction() {
166: return new InsertSheetAction();
167: }
168:
169: protected Action createDeleteSheetAction() {
170: return new DeleteSheetAction();
171: }
172:
173: protected Action createRenameSheetAction() {
174: return new RenameSheetAction();
175: }
176:
177: /** This method will display the popup if the mouseevent is a popup event
178: * and the event occurred over a tab
179: */
180: protected void checkPopup(MouseEvent e) {
181: if (e.isPopupTrigger()) {
182: int tab = sheetPane.getUI().tabForCoordinate(sheetPane,
183: e.getX(), e.getY());
184: if (tab != -1) {
185: popup.show(sheetPane, e.getX(), e.getY());
186: }
187: }
188: }
189:
190: public void mouseClicked(MouseEvent e) {
191: checkPopup(e);
192: }
193:
194: public void mousePressed(MouseEvent e) {
195: checkPopup(e);
196: }
197:
198: public void mouseReleased(MouseEvent e) {
199: checkPopup(e);
200: }
201:
202: public void mouseEntered(MouseEvent e) {
203: }
204:
205: public void mouseExited(MouseEvent e) {
206: }
207: }
208:
209: /** This class defines the action that is performed when the sheet is renamed*/
210: private class RenameSheetAction extends AbstractAction {
211: public RenameSheetAction() {
212: super ("Rename");
213: }
214:
215: public void actionPerformed(ActionEvent e) {
216: int tabIndex = sheetPane.getSelectedIndex();
217: if (tabIndex != -1) {
218: String newSheetName = (String) JOptionPane
219: .showInputDialog(sheetPane,
220: "Enter a new Sheetname",
221: "Rename Sheet",
222: JOptionPane.QUESTION_MESSAGE);
223: if (newSheetName != null) {
224: wb.setSheetName(tabIndex, newSheetName);
225: sheetPane.setTitleAt(tabIndex, newSheetName);
226: }
227: }
228: }
229: }
230:
231: /** This class defines the action that is performed when a sheet is inserted*/
232: private class InsertSheetAction extends AbstractAction {
233: public InsertSheetAction() {
234: super ("Insert");
235: }
236:
237: public void actionPerformed(ActionEvent e) {
238: //Create a new sheet then search for the sheet and make sure that the
239: //sheetPane shows it.
240: HSSFSheet newSheet = wb.createSheet();
241: for (int i = 0; i < wb.getNumberOfSheets(); i++) {
242: HSSFSheet sheet = wb.getSheetAt(i);
243: if (newSheet == sheet) {
244: sheetPane.insertTab(wb.getSheetName(i), null,
245: makeSheetView(sheet), null, i);
246: }
247: }
248: }
249: }
250:
251: /** This class defines the action that is performed when the sheet is deleted*/
252: private class DeleteSheetAction extends AbstractAction {
253: public DeleteSheetAction() {
254: super ("Delete");
255: }
256:
257: public void actionPerformed(ActionEvent e) {
258: int tabIndex = sheetPane.getSelectedIndex();
259: if (tabIndex != -1) {
260: if (JOptionPane
261: .showConfirmDialog(
262: sheetPane,
263: "Are you sure that you want to delete the selected sheet",
264: "Delete Sheet?",
265: JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
266: wb.removeSheetAt(tabIndex);
267: sheetPane.remove(tabIndex);
268: }
269: }
270: }
271: }
272:
273: public boolean isEditable() {
274: return allowEdits;
275: }
276:
277: /**Main method*/
278: public static void main(String[] args) {
279: try {
280: FileInputStream in = new FileInputStream(args[0]);
281: HSSFWorkbook wb = new HSSFWorkbook(in);
282: in.close();
283:
284: SViewerPanel p = new SViewerPanel(wb, true);
285: JFrame frame;
286: frame = new JFrame() {
287: protected void processWindowEvent(WindowEvent e) {
288: super .processWindowEvent(e);
289: if (e.getID() == WindowEvent.WINDOW_CLOSING) {
290: System.exit(0);
291: }
292: }
293:
294: public synchronized void setTitle(String title) {
295: super .setTitle(title);
296: enableEvents(AWTEvent.WINDOW_EVENT_MASK);
297: }
298: };
299: frame.setTitle("Viewer Frame");
300: frame.getContentPane().add(p, BorderLayout.CENTER);
301: frame.setSize(800, 640);
302: Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
303: frame.setLocation((d.width - frame.getSize().width) / 2,
304: (d.height - frame.getSize().height) / 2);
305: frame.setVisible(true);
306: } catch (IOException ex) {
307: ex.printStackTrace();
308: System.exit(1);
309: }
310: }
311: }
|