org.cruxframework.crux.widgets.client.grid.FrozenCellsScrollHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.cruxframework.crux.widgets.client.grid.FrozenCellsScrollHandler.java

Source

/*
 * Copyright 2014 cruxframework.org.
 * 
 * Licensed 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 org.cruxframework.crux.widgets.client.grid;

import java.util.Date;

import org.cruxframework.crux.core.client.animation.HorizontalMotionAnimation;
import org.cruxframework.crux.core.client.animation.VerticalMotionAnimation;
import org.cruxframework.crux.core.client.collection.FastList;
import org.cruxframework.crux.core.client.executor.BeginEndExecutor;
import org.cruxframework.crux.widgets.client.grid.AbstractTablelessGridStructure.Line;
import org.cruxframework.crux.widgets.client.grid.AbstractTablelessGridStructure.Lines;

import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.user.client.Element;

/**
 * Handles the positioning of rows and cells during scrolling
 * @author Gesse Dafe
 */
class FrozenCellsScrollHandler extends BeginEndExecutor implements ScrollHandler {
    private static final int MAX_SCROLL_INACTIVITY_MILLIS = 200;

    private static final int LAST_FROZEN_COLUMN_INDEX_CACHE_TTL_MILLIS = 5000;

    private AbstractTablelessGridStructure tablelessStruct;
    private long lastDiscoverCall = 0;
    private int lastFrozenColumnIndex = -1;

    private int lastHorizontalScrollPosition = 0;
    private int lastVerticalScrollPosition = 0;

    /**
     * @param grid
     * @param lines
     */
    public FrozenCellsScrollHandler(AbstractTablelessGridStructure tablelessStruct) {
        super(MAX_SCROLL_INACTIVITY_MILLIS);
        this.tablelessStruct = tablelessStruct;
    }

    /**
     * @see com.google.gwt.event.dom.client.ScrollHandler#onScroll(com.google.gwt.event.dom.client.ScrollEvent)
     */
    public void onScroll(ScrollEvent event) {
        super.execute();
    }

    @Override
    protected void doEndAction() {
        int numLines = tablelessStruct.getLines().getWidgetCount();

        if (numLines > 0) {
            int vertScrollPos = tablelessStruct.getGrid().getScrollingArea().getScrollPosition();
            int horScrollPos = tablelessStruct.getGrid().getScrollingArea().getHorizontalScrollPosition();

            maybeFreezeHeaders(vertScrollPos);
            maybeFreezeColumns(horScrollPos);

            lastVerticalScrollPosition = vertScrollPos;
            lastHorizontalScrollPosition = horScrollPos;
        }
    }

    @Override
    protected void doBeginAction() {
        // nothing to do
    }

    /**
     * Freezes the grid columns that are assigned with <code>frozen=true</code>  
     * @param newHorizontalScrollPosition
     */
    private void maybeFreezeColumns(int newHorizontalScrollPosition) {
        boolean isHorizontalScroll = newHorizontalScrollPosition != lastHorizontalScrollPosition;

        if (isHorizontalScroll && tablelessStruct.getGrid().hasFrozenColumns()) {
            Lines lines = tablelessStruct.getLines();
            int numLines = lines.getWidgetCount();
            int lastFrozenCol = discoverLastFrozenColIndex(lines.getLine(0));

            for (int i = 0; i < numLines; i++) {
                if (tablelessStruct.canFreezeColumns(i)) {
                    Line line = lines.getLine(i);

                    for (int j = 0; j <= lastFrozenCol; j++) {
                        Element cellElem = line.getCell(j).getElement();

                        Style style = cellElem.getStyle();
                        style.setZIndex(i == 0 ? 4 : 2);
                        style.setOpacity(1);

                        HorizontalMotionAnimation columnAnimation = new HorizontalMotionAnimation(cellElem);
                        columnAnimation.move(getIntegerPixelMeasure(cellElem.getStyle().getLeft()),
                                newHorizontalScrollPosition, 200);
                    }
                }
            }
        }
    }

    private int getIntegerPixelMeasure(String measure) {
        if (measure.contains("px")) {
            measure = measure.replace("px", "");
        }
        measure = measure.trim();
        if (measure.length() > 0) {
            return (int) Math.round(Double.parseDouble(measure));
        }

        return 0;
    }

    /**
     * Freezes the header line if the grid is assigned with <code>freezeHeaders=true</code>
     */
    private void maybeFreezeHeaders(int newVerticalScrollPosition) {
        boolean isVerticalScroll = newVerticalScrollPosition != lastVerticalScrollPosition;

        if (isVerticalScroll && tablelessStruct.getGrid().hasFrozenHeaders()) {
            Element headerLineElement = tablelessStruct.getLines().getLine(0).getElement();

            Style style = headerLineElement.getStyle();
            style.setZIndex(3);
            style.setOpacity(1);

            VerticalMotionAnimation headerAnimation = new VerticalMotionAnimation(headerLineElement);
            headerAnimation.move(headerLineElement.getOffsetTop(), newVerticalScrollPosition, -1);
        }
    }

    /**
     * Finds the last (left to right) column assigned with <code>frozen=true</code>
     * @param headerLine
     * @return
     */
    private int discoverLastFrozenColIndex(Line headerLine) {
        long now = new Date().getTime();
        boolean skipCache = (now - lastDiscoverCall) > LAST_FROZEN_COLUMN_INDEX_CACHE_TTL_MILLIS;

        if (skipCache) {
            lastDiscoverCall = now;

            this.lastFrozenColumnIndex = -1;
            AbstractGrid<?> grid = tablelessStruct.getGrid();
            FastList<ColumnDefinition> defs = grid.getColumnDefinitions().getDefinitions();
            int offset = (grid.hasRowDetailsIconColumn() ? 1 : 0) + (grid.hasSelectionColumn() ? 1 : 0);
            int numCols = defs.size();

            for (int i = 0; i < numCols; i++) {
                ColumnDefinition def = defs.get(i);
                if (def.isVisible() && def.isFrozen()) {
                    this.lastFrozenColumnIndex = i + offset;
                }
            }
        }

        return this.lastFrozenColumnIndex;
    }
}