/** * Copyright (c) 2014 - 2017 Frank Appel * 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 * * Contributors: * Frank Appel - initial API and implementation */ package com.codeaffine.eclipse.swt.widget.scrollable.context; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Scrollable; public class AdaptionContext<T extends Scrollable> { public static final int OVERLAY_OFFSET = 40; private final ScrollbarVisibility scrollbarVisibility; private final Point originOfScrollableOrdinates; private final Map<Class<?>, Object> attributes; private final ScrollableControl<T> scrollable; private final Reconciliation reconciliation; private final SizeComputer sizeComputer; private final Rectangle visibleArea; private final int verticalBarOffset; private final Composite adapter; private final int borderWidth; private final int itemHeight; private final int offset; public AdaptionContext( Composite adapter, ScrollableControl<T> scrollable ) { this( adapter, scrollable, 1, null, new SizeComputer( scrollable, adapter ), new HashMap<>() ); } private AdaptionContext( Composite adapter, ScrollableControl<T> scrollable, int itemHeight, Reconciliation reconciliation, SizeComputer sizeComputer, Map<Class<?>, Object> attributes ) { this.attributes = attributes; this.sizeComputer = sizeComputer; this.scrollbarVisibility = new ScrollbarVisibility( sizeComputer, scrollable, adapter.getClientArea(), itemHeight ); this.reconciliation = reconciliation == null ? new Reconciliation( adapter, scrollable ) : reconciliation; this.verticalBarOffset = computeVerticalBarOffset( scrollable ); this.offset = new OffsetComputer( scrollable ).compute(); this.visibleArea = computeVisibleArea( adapter, scrollable ); this.borderWidth = scrollable.getBorderWidth(); this.originOfScrollableOrdinates = new Point( visibleArea.x - borderWidth, visibleArea.y - borderWidth ); this.scrollable = scrollable; this.adapter = adapter; this.itemHeight = itemHeight; } public AdaptionContext<T> newContext( int itemHeight ) { return new AdaptionContext<T>( adapter, scrollable, itemHeight, reconciliation, sizeComputer, attributes ); } public AdaptionContext<T> newContext() { return new AdaptionContext<T>( adapter, scrollable, itemHeight, reconciliation, sizeComputer, attributes ); } public <A> void put( Class<A> key, A value ) { attributes.put( key, value ); } public <A> A get( Class<A> key ) { return key.cast( attributes.get( key ) ); } public Reconciliation getReconciliation() { return reconciliation; } public Composite getAdapter() { return adapter; } public ScrollableControl<T> getScrollable() { return scrollable; } public int getOffset() { return offset; } public Point getOriginOfScrollableOrdinates() { return originOfScrollableOrdinates; } public Point getPreferredSize() { return sizeComputer.getPreferredSize(); } public void updatePreferredSize() { sizeComputer.updatePreferredSize(); } public void adjustPreferredWidthIfHorizontalBarIsVisible() { sizeComputer.adjustPreferredWidthIfHorizontalBarIsVisible(); } public boolean isVerticalBarVisible() { return scrollbarVisibility.isVerticalBarVisible(); } public boolean isHorizontalBarVisible() { return scrollbarVisibility.isHorizontalBarVisible(); } public Rectangle getVisibleArea() { return visibleArea; } public int getHorizontalAdapterSelection() { ScrollBar horizontalBar = getAdapter().getHorizontalBar(); if( horizontalBar != null ) { return horizontalBar.getSelection(); } return 0; } public int getVerticalBarOffset() { return verticalBarOffset; } public boolean isScrollableReplacedByAdapter() { return scrollable.isChildOf( adapter.getParent() ); } public int getBorderWidth() { return borderWidth; } private static int computeVerticalBarOffset( ScrollableControl<? extends Scrollable> scrollable ) { int result = scrollable.getVerticalBarSize().x; if( result == 0 ) { result = OVERLAY_OFFSET; } return result; } private static Rectangle computeVisibleArea( Composite adapter, ScrollableControl<? extends Scrollable> scrollable ) { Rectangle area = adapter.getClientArea(); int borderAdjustment = scrollable.getBorderWidth() * 2; return new Rectangle( area.x, area.y, area.width + borderAdjustment, area.height + borderAdjustment ); } }