⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ktable.java

📁 ktable 是一个由java开发的,对控制报表的项目,它最大的特点是使用独特的算法,能支持巨大的报表(千万以上?).
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/*
 * Copyright (C) 2004 by Friederich Kupzog Elektronik & Software
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 
 Authors: 
 Friederich Kupzog,  fkmk@kupzog.de, www.kupzog.de/fkmk
 Lorenz Maierhofer, lorenz.maierhofer@logicmindguide.com

 */

package de.kupzog.ktable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;

import de.kupzog.ktable.renderers.TextCellRenderer;



/**
 * Custom drawn tabel widget for SWT GUIs.
 * <p>
 * The idea of KTable is to have a flexible grid of cells to display data in it.
 * The class focuses on displaying data and not on collecting the data to
 * display. The latter is done by the <code>KTableModel</code> which has to be implemented
 * for each specific case. Some default tasks are done by a base implementation
 * called <code>KTableDefaultModel</code>. Look also into <code>KTableSortedModel</code> that provides 
 * a transparent sorting of cells.<br>
 * The table asks the table model for the amount of
 * columns and rows, the sizes of columns and rows and for the content of the
 * cells which are currently drawn. Even if the table has a million rows, it
 * won�t get slower because it only requests those cells it currently draws.
 * Only a bad table model can influence the drawing speed negatively.
 * <p>
 * When drawing a cell, the table calls a <code>KTableCellRenderer</code> to do this work.
 * The table model determines which cell renderer is used for which cell. A
 * default renderer is available (<code>KTableCellRenderer.defaultRenderer</code>), but the
 * creation of self-written renderers for specific purposes is assumed. 
 * Some default renderers are available in the package <code>de.kupzog.ktable.cellrenderers.*</code>.
 * <p>
 * KTable allows to F columns and rows. Each column can have an individual
 * size while the rows are all of the same height except the first row. Multiple
 * column and row headers are possible. These "fixed" cells will not be scrolled
 * out of sight. The column and row count always starts in the upper left corner
 * with 0, independent of the number of column headers or row headers.
 * <p>
 * It is also possible to span cells over several rows and/or columns. The KTable
 * asks the model do provide this information via <code>belongsToCell(col, row)</code>.
 * This method must return the cell the given cell should be merged with.
 * <p>
 * Changing of model values is possible by implementations of <code>KTableCellEditor</code>.
 * Again the KTable asks the model to provide an implementation. Note that there
 * are multiple celleditors available in the package <code>de.kupzog.ktable.editors</code>!
 * 
 * @author Friederich Kupzog
 * @see de.kupzog.ktable.KTableModel
 * @see de.kupzog.ktable.KTableDefaultModel
 * @see de.kupzog.ktable.KTableSortedModel
 * @see de.kupzog.ktable.KTableCellRenderer
 * @see de.kupzog.ktable.KTableCellEditor
 * @see de.kupzog.ktable.KTableCellSelectionListener
 *  
 */
public class KTable extends Canvas {    
    
    // Data and data editing facilities:
    protected KTableModel m_Model;
    protected KTableCellEditor m_CellEditor;

    // current visible:
    protected int m_TopRow;
    protected int m_LeftColumn;

    // Selection
    protected HashMap m_Selection;
    protected int m_FocusRow;
    protected int m_FocusCol;
    protected int m_MainFocusRow; 
    protected int m_MainFocusCol;
    protected int m_ClickColumnIndex;
    protected int m_ClickRowIndex;
    private int m_Style=SWT.NONE;
    
    // important measures
    protected int m_RowsVisible;
    protected int m_RowsFullyVisible;
    protected int m_ColumnsVisible;
    protected int m_ColumnsFullyVisible;

    // column sizes
    protected int m_ResizeColumnIndex;
    protected int m_ResizeColumnLeft;
    protected int m_ResizeRowIndex;
    protected int m_ResizeRowTop;
    protected int m_NewRowSize;
    protected int m_NewColumnSize;
    protected boolean m_Capture = false;
    protected Image m_LineRestore;
    protected int m_LineX;
    protected int m_LineY;

    // resize area
    protected int m_ResizeAreaSize = 10;
    
    // diverse
    protected Display m_Display;
    protected ArrayList cellSelectionListeners;
    protected ArrayList cellDoubleClickListeners;
    protected ArrayList cellResizeListeners;
    protected Cursor m_defaultCursor;
    protected Point  m_defaultCursorSize;
    protected Cursor m_defaultRowResizeCursor;
    protected Cursor m_defaultColumnResizeCursor;
    protected String m_nativTooltip;

    //////////////////////////////////////////////////////////////////////////////
    // CONSTRUCTOR & DISPOSE
    //////////////////////////////////////////////////////////////////////////////

    /**
     * Creates a new KTable.
     * 
     * possible styles: 
     * <ul>
     * <li><b>SWT.V_SCROLL</b> - show vertical scrollbar and allow vertical scrolling by arrow keys</li>
     * <li><b>SWT.H_SCROLL</b> - show horizontal scrollbar and allow horizontal scrolling by arrow keys</li>
     * <li><b>SWTX.AUTO_SCROLL</b> - Dynamically shows vertical and horizontal scrollbars when they are necessary.</li>
     * <li><b>SWTX.FILL_WITH_LASTCOL</b> - Makes the table enlarge the last column to always fill all space.</li>
     * <li><b>SWTX.FILL_WITH_DUMMYCOL</b> - Makes the table fill any remaining space with dummy columns to fill all space.</li>
     * <li><b>SWT.FLAT</b> - Does not paint a dark outer border line.</li>
     * <li><b>SWT.MULTI</b> - Sets the "Multi Selection Mode".
     * In this mode, more than one cell or row can be selected.
     * The user can achieve this by shift-click and ctrl-click.
     * The selected cells/rows can be scattored ofer the complete table.
     * If you pass false, only a single cell or row can be selected.
     * This mode can be combined with the "Row Selection Mode".</li>
     * <li><b>SWT.FULL_SELECTION</b> - Sets the "Full Selection Mode".
     * In the "Full Selection Mode", the table always selects a complete row.
     * Otherwise, each individual cell can be selected.
     * This mode can be combined with the "Multi Selection Mode".</li>
     * <li><b>SWTX.EDIT_ON_KEY</b> - Activates a possibly present cell editor
     * on every keystroke. (Default: only ENTER). However, note that editors
     * can specify which events they accept.</li>
     * <li><b>SWTX.MARK_FOCUS_HEADERS</b> - Makes KTable draw left and top header cells
     * in a different style when the focused cell is in their row/column.
     * This mimics the MS Excel behavior that helps find the currently
     * selected cell(s).</li>
     * <li><b>SWT.HIDE_SELECTION</b> - Hides the selected cells when the KTable
     * looses focus.</li>
     * After creation a table model should be added using setModel().
     */
    public KTable(Composite parent, int style) {
        // Initialize canvas to draw on.
        super(parent, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | style);
        
        m_Style = style;
 
        //inits
        m_Display = Display.getCurrent();
        m_Selection = new HashMap();
        m_CellEditor = null;

        m_TopRow = 0;
        m_LeftColumn = 0;
        m_FocusRow = 0;
        m_FocusCol = 0;
        m_RowsVisible = 0;
        m_RowsFullyVisible = 0;
        m_ColumnsVisible = 0;
        m_ColumnsFullyVisible = 0;
        m_ResizeColumnIndex = -1;
        m_ResizeRowIndex = -1;
        m_ResizeRowTop = -1;
        m_NewRowSize = -1;
        m_NewColumnSize = -1;
        m_ResizeColumnLeft = -1;
        m_ClickColumnIndex = -1;
        m_ClickRowIndex = -1;

        m_LineRestore = null;
        m_LineX = 0;
        m_LineY = 0;

        cellSelectionListeners = new ArrayList(10);
        cellDoubleClickListeners = new ArrayList(10);
        cellResizeListeners = new ArrayList(10);

        // Listener creation
        createListeners();
        
        // handle tooltip initialization:
	    m_nativTooltip = super.getToolTipText();
	    super.setToolTipText("");
	    
	    // apply various style bits:
	    if ((style & SWTX.AUTO_SCROLL) == SWTX.AUTO_SCROLL) {
	        addListener(SWT.Resize, new Listener() {
	            public void handleEvent(Event event) {
	                updateScrollbarVisibility();
	            }
	        });
            addCellResizeListener(new KTableCellResizeListener() {
                public void rowResized(int row, int newHeight) {
                    updateScrollbarVisibility();
                }
                public void columnResized(int col, int newWidth) {
                    updateScrollbarVisibility();   
                    }
            });
	    }	    
    }

    public void dispose() {

    	if (m_defaultCursor != null)
            m_defaultCursor.dispose();
        
    	if (m_defaultRowResizeCursor != null)
    		m_defaultRowResizeCursor.dispose();
    	
       	if (m_defaultColumnResizeCursor != null)
    		m_defaultColumnResizeCursor.dispose();

       	super.dispose();

    }

    protected void createListeners() {

        addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent event) {
                onPaint(event);
            }
        });

        addControlListener(new ControlAdapter() {
            public void controlResized(ControlEvent e) {
                redraw();
            }
        });

        addMouseListener(new MouseAdapter() {
            public void mouseDown(MouseEvent e) {
                onMouseDown(e);
            }

            public void mouseUp(MouseEvent e) {
                onMouseUp(e);
            }

            public void mouseDoubleClick(MouseEvent e) {
                onMouseDoubleClick(e);
            }
        });

        addMouseMoveListener(new MouseMoveListener() {
            public void mouseMove(MouseEvent e) {
                onMouseMove(e);
            }
        });

        addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                onKeyDown(e);
            }
        });
        
        addCellSelectionListener(new KTableCellSelectionAdapter() {
            
            private Point[] oldSelections;
            
            public void cellSelected(int col, int row, int statemask) {
                if (isHighlightSelectionInHeader() && (statemask & SWT.SHIFT) == 0) {
					Point[] selections = getCellSelection();
					GC gc = new GC(KTable.this);

					repaintRelevantCells(gc, oldSelections);
					repaintRelevantCells(gc, selections);
					
					gc.dispose();
					oldSelections = selections;
                }
        	}
            
			private void repaintRelevantCells(GC gc, Point[] selections) {
			    if (selections==null) return;
			    Rectangle bounds = getClientArea();
                Rectangle oldClipping = gc.getClipping();
                int fixedWidth =  0;
                int fixedHeight = 0;
                for (int k=0; k<m_Model.getFixedHeaderColumnCount(); k++)
                    fixedWidth += getCellRectIgnoreSpan(k, 0).width+1;
                for (int k=0; k<m_Model.getFixedHeaderRowCount(); k++)
                    fixedHeight += getCellRectIgnoreSpan(0, k).height+1;
                
                for (int i=0; i<selections.length; i++) {
			        int col = selections[i].x; 
                    int row = selections[i].y;
                    for (int j=0; j<getModel().getFixedHeaderColumnCount(); j++) {
                        Point valid = getValidCell(j, row);
                        // allow painting of GC only on columns, not on rows:
                        Rectangle rowClip = new Rectangle(1,1+fixedHeight,fixedWidth,bounds.height-1-fixedHeight);                        
                        rowClip.intersect(oldClipping);
                        gc.setClipping(rowClip);
                        drawCell(gc, valid.x, valid.y);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -