/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ro.nextreports.designer.grid; import javax.swing.*; import javax.swing.event.MouseInputListener; import ro.nextreports.designer.Globals; import ro.nextreports.designer.LayoutHelper; import ro.nextreports.designer.grid.plaf.BasicGridHeaderUI; import ro.nextreports.designer.grid.plaf.GridUI; import ro.nextreports.designer.util.I18NSupport; import ro.nextreports.designer.util.Show; import ro.nextreports.engine.ReportLayout; import ro.nextreports.engine.ReportGroup; import ro.nextreports.engine.exporter.ResultExporter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.*; import java.util.List; import java.util.ArrayList; /** * @author Decebal Suiu */ public class JGridHeader extends JGrid { private static final String uiClassID = "GridHeaderUI"; private boolean resize; private boolean allowSelection; private Popup popup; private JToolTip toolTip; public static final int MINIMUM_COLUMN_SIZE = 10; public static final int MAXIMUM_COLUMN_SIZE = 1500; // Install UI delegate static { UIManager.getDefaults().put(uiClassID, BasicGridHeaderUI.class.getName()); } public JGridHeader(final JGrid viewport, final int orientation, boolean resize, boolean allowSelection) { this.resize = resize; this.allowSelection=allowSelection; toolTip = createToolTip(); spanModel = new DefaultSpanModel(); // setCellRenderer(Object.class, new GridHeaderRenderer()); // moved down selectionModel = new DefaultSelectionModel(); if (orientation == SwingConstants.HORIZONTAL) { columnHeaderModel = viewport.getColumnHeaderModel(); model = new ColumnHeaderGridModel(columnHeaderModel); rowHeaderModel = new DefaultHeaderModel(1, DEFAULT_ROW_HEIGHT, SwingConstants.VERTICAL); } else { rowHeaderModel = viewport.getRowHeaderModel(); model = new RowHeaderGridModel(rowHeaderModel); columnHeaderModel = new DefaultHeaderModel(1, DEFAULT_COLUMN_WIDTH, SwingConstants.HORIZONTAL); // tooltip for group band addMouseMotionListener(new MouseMotionAdapter() { public void mouseMoved(MouseEvent event) { show(event); } private void show(MouseEvent event) { Point p = event.getPoint(); int row = Globals.getReportGrid().rowAtPoint(p); int column = Globals.getReportGrid().columnAtPoint(p); String bandName = Globals.getReportGrid().getBandName(row); int bandRow = Globals.getReportGrid().getBandLocation(bandName).getRow(row); String groupName = null; if (bandName.startsWith(ReportLayout.GROUP_HEADER_BAND_NAME_PREFIX)) { groupName = bandName.substring(ReportLayout.GROUP_HEADER_BAND_NAME_PREFIX.length()); } else if (bandName.startsWith(ReportLayout.GROUP_FOOTER_BAND_NAME_PREFIX)) { groupName = bandName.substring(ReportLayout.GROUP_FOOTER_BAND_NAME_PREFIX.length()); } if (groupName != null) { ReportGroup group = LayoutHelper.getReportLayout().getGroup(groupName); setToolTipText(group.getColumn()); } else { setToolTipText(null); } } }); } create(model, spanModel, rowHeaderModel, columnHeaderModel, selectionModel); setCellRenderer(Object.class, new GridHeaderRenderer()); // !? review createDefaults ?! updateUI(); } @Override public GridUI getUI() { return (GridUI) ui; } @Override public void setUI(GridUI gridUI) { if (ui != gridUI) { super.setUI(gridUI); repaint(); } } @Override public void updateUI() { // register(or not) listener for selection if (allowSelection) { setUI(new BasicGridHeaderUI()); } else { setUI(new BasicGridHeaderUI() { @Override protected MouseInputListener createMouseInputListener() { return null; } }); } // register listener for cell resize if (resize) { setUI(new BasicGridHeaderUI() { protected MouseInputListener createMouseInputListener() { return new HeaderResizeMouseInputListener(); } }); } repaintManager.resizeAndRepaint(); } @Override public String getUIClassID() { return "GridHeaderUI"; } protected void showToolTip(MouseEvent event) { toolTip.setTipText(getToolTipText(event)); // Trick is to hide a previous popup before showing a new one if (popup != null) popup.hide(); Point pt = getLocationOnScreen(); int x = pt.x + event.getPoint().x; int y = pt.y - 20; PopupFactory factory = PopupFactory.getSharedInstance(); popup = factory.getPopup(this, toolTip, x, y); popup.show(); } private static class RowHeaderGridModel extends AbstractGridModel { private HeaderModel headerModel; public RowHeaderGridModel(HeaderModel rowModel) { headerModel = rowModel; } public Object getValueAt(int row, int column) { String bandName = Globals.getReportGrid().getBandName(row); int bandRow = Globals.getReportGrid().getBandLocation(bandName).getRow(row); String result; if (bandName.startsWith(ReportLayout.GROUP_HEADER_BAND_NAME_PREFIX)) { result = I18NSupport.getString("band.group.header.name").substring(0, 1).toUpperCase() + bandName.substring(ReportLayout.GROUP_HEADER_BAND_NAME_PREFIX.length()); } else if (bandName.startsWith(ReportLayout.GROUP_FOOTER_BAND_NAME_PREFIX)) { result = I18NSupport.getString("band.group.footer.name").substring(0, 1).toUpperCase() + bandName.substring(ReportLayout.GROUP_FOOTER_BAND_NAME_PREFIX.length()); } else if (bandName.equals(ReportLayout.PAGE_HEADER_BAND_NAME) || bandName.equals(ReportLayout.PAGE_FOOTER_BAND_NAME)) { result = String.valueOf("Z" + bandRow); } else { result = String.valueOf(I18NSupport.getString("band." + bandName.toLowerCase() + ".name").substring(0, 1).toUpperCase() + bandRow); } return result; } public boolean isCellEditable(int row, int column) { return false; } public void setValueAt(Object value, int row, int column) { } public int getRowCount() { return headerModel.getCount(); } public int getColumnCount() { return 1; } } private static class ColumnHeaderGridModel extends AbstractGridModel { private HeaderModel headerModel; public ColumnHeaderGridModel(HeaderModel columnModel) { headerModel = columnModel; } public Object getValueAt(int row, int column) { return String.valueOf(column); } public boolean isCellEditable(int row, int column) { return false; } public void setValueAt(Object value, int row, int column) { } public int getRowCount() { return 1; } public int getColumnCount() { return headerModel.getCount(); } } protected class HeaderResizeMouseInputListener implements MouseInputListener { private boolean dragging = false; private boolean start = false; private Rectangle r; // Give user some leeway for selections. private final int PROX_DIST = 3; private int row; private int column; private int width; private String oldTooltip; public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { start = true; oldTooltip = getToolTipText(); if (getCursor() != Cursor.getDefaultCursor()) { // If cursor is set for resizing, allow dragging. if (LayoutHelper.getReportLayout().isUseSize()) { dragging = true; // take care of double clicks (seen as two mouse pressed followed by mouse released actions) // meaning the width remains the same if (start) { Point p = e.getPoint(); p.setLocation(p.x - PROX_DIST - 1, p.y); row = rowAtPoint(p); column = columnAtPoint(p); r = getCellBounds(row, column); width = r.width; } } } } public void mouseReleased(MouseEvent e) { if (dragging & LayoutHelper.getReportLayout().isUseSize()) { SwingUtilities.invokeLater(new Runnable() { public void run() { int total = 0; List<Integer> columnsWidth = new ArrayList<Integer>(); for (int i = 0, n = getColumnCount(); i < n; i++) { if (i == column) { total += width; columnsWidth.add(width); } else { total += getColumnWidth(i); columnsWidth.add(getColumnWidth(i)); } } LayoutHelper.getReportLayout().setColumnsWidth(columnsWidth); // repaint headers Globals.getReportLayoutPanel().getReportGridPanel().repaintHeaders(); Globals.getReportDesignerPanel().refresh(); if (Globals.getA4Warning()) { if (ResultExporter.A4_LANDSCAPE_PIXELS < total) { Show.info(I18NSupport.getString("width.action.exceed.landscape")); } else if (ResultExporter.A4_PORTRAIT_PIXELS < total) { Show.info(I18NSupport.getString("width.action.exceed.portrait")); } } } }); dragging = false; // popup may be null -> on double click if (popup != null) { popup.hide(); } setToolTipText(oldTooltip); oldTooltip = null; } } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseDragged(MouseEvent e) { if (dragging) { Point p = e.getPoint(); // adjust the point to left with the PROX_DIST : so we know that the left cell from the // mouse will be resized (otherwise can be the left or the right one : undeterministic) p.setLocation(p.x - PROX_DIST - 1, p.y); if (start) { start = false; row = rowAtPoint(p); column = columnAtPoint(p); r = getCellBounds(row, column); } int type = getCursor().getType(); switch (type) { case Cursor.E_RESIZE_CURSOR: if (p.x >= r.x + r.width) { width = p.x - r.x; } else if (p.x <= r.x) { width = r.width; } else { width = p.x - r.x; } break; default: } if (width < MINIMUM_COLUMN_SIZE) { width = MINIMUM_COLUMN_SIZE; } else if (width > MAXIMUM_COLUMN_SIZE) { width = MAXIMUM_COLUMN_SIZE; } setToolTipText(I18NSupport.getString("width.text") + " : " + String.valueOf(width)); showToolTip(e); } } public void mouseMoved(MouseEvent e) { Point p = e.getPoint(); if (!isOverRect(p)) { if (getCursor() != Cursor.getDefaultCursor()) { // If cursor is not over rect reset it to the default. setCursor(Cursor.getDefaultCursor()); } return; } // Locate cursor relative to center of rect. int outcode = getOutcode(p); int row = rowAtPoint(p); int column = columnAtPoint(p); Rectangle r = getCellBounds(row, column); switch (outcode) { case Rectangle.OUT_RIGHT: if (Math.abs(p.x - (r.x + r.width)) < PROX_DIST) { if (LayoutHelper.getReportLayout().isUseSize()) { setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); } } break; default: // center setCursor(Cursor.getDefaultCursor()); } } // // Make a smaller Rectangle and use it to locate the // cursor relative to the Rectangle center. private int getOutcode(Point p) { int row = rowAtPoint(p); int column = columnAtPoint(p); Rectangle r = (Rectangle) getCellBounds(row, column).clone(); r.grow(-PROX_DIST, -PROX_DIST); return r.outcode(p.x, p.y); } // // Make a larger Rectangle and check to see if the // cursor is over it. private boolean isOverRect(Point p) { int row = rowAtPoint(p); int column = columnAtPoint(p); Rectangle r = (Rectangle) getCellBounds(row, column).clone(); r.grow(PROX_DIST, PROX_DIST); return r.contains(p); } } }