alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor.view.spi;

import javax.swing.text.View;

/**
 * Wrapper around a view that caches computed layout information
 * about preferred, minimum and maximum span along minor axis
 * and the preferred span along the major axis.
 * 
* It's primarily intended to be used for views being children * of GapBoxView based implementations. *
* After a change occurs in the wrapped view it calls * getParent().preferenceChanged(this, width, height) * the parent view will notify the layout state by calling * {@link #viewPreferenceChanged(width, height)} to mark * that the cached values need to be updated. *
* At some point later the parent view calls * {@link #updateLayout()} to update the layout of the child * and synchronize the caching variables. * *

* The layout state keeps one of the axes (either View.X_AXIS * or View.Y_AXIS as the major one i.e. the children * are laid out along that axis. The other axis is called minor. *
* The layout along the major axis dedicates the span * equal to preferred span of the given view (wrapped by a layout state). *
* Span along minor axis is more complex and it's specific * to particular implementations of {@link ViewLayoutState.Parent}. * *

* It's encouraged that all the view implementations * wishing to be used as children * of GapBoxView based implementations * in this framework implement this interface. *
* The benefit for the view implementing this interface * is that no default wrapper object implementing * this interface needs to be created which saves memory. *
* Moreover unlike the default wrapper * the view can better decide which values really need to be cached * and which (e.g. maximum or minimum span being equal to preferred span) * do not need to be cached * which can furhter eliminate certain caching variables * and save additional memory. *
* Another reason is faster finding of the index value of the child view * in its parent view (e.g. in preferenceChanged()) * which is constant time compared to logartihmic time (binary search used). * * @author Miloslav Metelka * @version 1.00 */ public interface ViewLayoutState { /** * Get the view that this layout state is wrapping. * @return view that this layout state is wrapping. */ public View getView(); /** * Check whether this layout state and its associated * view is flyweight (there is just one immutable shared instance of it). * * @return true if this layout state and its associated view * are flyweight or false if not. */ public boolean isFlyweight(); /** * Get the raw index of the view (wrapped by this layout state) * in its parent view. *
* Storing of the index is useful for the parent which * can then find the child's index in a constant time. *
* * @return raw integer index that must be post-processed * by parent (if it uses gap-based storage) to become a real index. *
* Returned valud is undefined for flyweight layout states. */ public int getViewRawIndex(); /** * Parent can set the index of the view (wrapped by this layout state) * in itself. *
* This method must not be called on flyweight layout states. * * @param viewRawIndex raw index value. It can differ from * the real index because parent could preprocess * it because of possible use of a gap translation. */ public void setViewRawIndex(int viewRawIndex); /** * Select which axis will be used as major axis by this layout state. * @param majorAxis major axis either View.X_AXIS * or View.Y_AXIS. * @return either this layout state if this state * is able to work with the given major axis * or another layout state if this state is only * able to work over the other major axis. * *

* A view (e.g. a flyweight view) * that implements this interface can decide to only allow * one axis as the major one. *
* That should mostly be fine because usually the view is tiled * only along one axis. *
* The view may throw IllegalStateException * in such case. */ public ViewLayoutState selectLayoutMajorAxis(int majorAxis); /** * Get the preferred span along major axis. *
* The value is expected to be cached for fast access. * *

* If the preferred span of the wrapped view changes * then the value of the major axis span must change as well * typically once the next layout state update takes place. *
* The wrapped view should call View.preferenceChanged * in its parent once its preferred span changes. * The parent view will later call * i.e. updateLayout() to update * the variable holding the preferred span along major axis. *
* Parent.majorAxisPreferenceChanged() * must be called immediately after that change * to notify the parent. * *

* Although the value is returned as double * (see {@link #getLayoutMajorAxisOffset()}) * it can be maintained as float if the resolution of the float * is sufficient to create proper deltas * in Parent#majorAxisPreferenceChanged(). *
* For example if a document has millions of lines it's necessary * to maintain line offsets in document view as doubles * but assuming that each line is only up to several tenths of pixels high * it's enough to hold line height as float in line view layout state. */ public double getLayoutMajorAxisPreferredSpan(); /** * Get the raw visual offset of the view along the parent view's * major axis. * *

* Double is chosen instead of float because for y as major axis * the truncation could occur when computing the offset * for large files with many lines or for very long lines. *
* The resolution of mantissa of floats is 23 bits * so assuming the line height is e.g. 17 pixels * and we have more than 250.000 lines in the docuemnt * (which is a lot to write but not so much for e.g. * generated xml files) the last bit would be lost * resulting in every odd line being shifted one * pixel above incorrectly. *
* The views can still decide to use floats for internal storage * of this value if the precision is sufficient. * * @return raw double visual offset along major axis. It must be post-processed * by parent (if it uses gap-based storage) to become a real index. *
* Returned valud is undefined for flyweight layout states. */ public double getLayoutMajorAxisRawOffset(); /** * Parent can set the view's raw offset along the parent view's * major axis using this method. *
* This method must not be called on flyweight layout states. * * @param layoutMajorAxisRawOffset raw offset value along the major axis. * It is not particularly useful without postprocessing by the parent. */ public void setLayoutMajorAxisRawOffset(double layoutMajorAxisRawOffset); /** * Get the preferred span of the view along minor axis. *
* The value is expected to be cached for fast access. * *

* If there is a dedicated variable for this value then * that variable should be updated during {@link #updateLayout()} * which usually happens some time after the view * has called View.preferenceChanged() * in the parent. *
* After the value gets updated the layout state must immediately call * Parent.minorAxisPreferenceChanged() * to notify the parent about the change of minor span. */ public float getLayoutMinorAxisPreferredSpan(); /** * Get the minimum span of the view along minor axis. *
* The value is expected to be cached for fast access. *
* By default GapBoxView implementations * do not use the minimum span of their children * so the particular layout state may decide not to cache * the minimum span value and return preferred span instead * to save memory that would otherwise be used for caching variables. * *

* If there is a dedicated variable for this value then * that variable should be updated during {@link #updateLayout()} * which usually happens once the view * has called View.preferenceChanged() * in the parent. *
* After the value gets updated the layout state must immediately call * Parent.minorAxisPreferenceChanged() * to notify the parent about the change of minor span. */ public float getLayoutMinorAxisMinimumSpan(); /** * Get the maximum span of the view along minor axis. *
* The value is expected to be cached for fast access. *
* As the default GapBoxView implementations * do not use the maximum span of their children * the particular layout state may decide not to cache * the maximum span value and return preferred span instead * to save memory that would otherwise be used for caching variables. * *

* If there is a dedicated variable for this value then * that variable gets updated by {@link #updateLayout()} * which usually happens once the view * has called View.preferenceChanged() * in the parent. *
* After the value gets updated the layout state must immediately call * Parent.minorAxisPreferenceChanged() * to notify the parent about the change of minor span. */ public float getLayoutMinorAxisMaximumSpan(); /** * Get alignment along the minor axis. *
* The value is expected to be cached for fast access. * *

* If there is a dedicated variable for this value then * that variable gets updated by {@link #updateLayout()} * which usually happens once the view * has called View.preferenceChanged() * in its parent view which in turn calls {@link #viewPreferenceChanged()}. *
* After the value gets updated the layout state must call * Parent.minorAxisPreferenceChanged() * to notify the parent about the change of minor span. */ public float getLayoutMinorAxisAlignment(); /** * Do actual layout updating. *
* The first thing to do * is to see if any work actually needs to be done. *
* Certain views such as line-wrapping views may react * to View.setSize() being called on them * by changing its preferred span along an axis. * For such views the actual internal updating must be done twice * (because of another call to parent.preferenceChanged()). *
* Anyway upon exit of this method the {@link #isLayoutValid()} * must return true. *
* This method must be no-op for flyweight layout states * because they should have their values up-to-date since * their construction without ever calling this method. *
* The view is responsible for repainting itself if that's necessary. * * Prior to asking the component to repaint the appropriate region */ public void updateLayout(); /** * Notify this layout state that the preferences has changed * for the view that it wraps. *
* This gets called in response to the wrapped view calling * View.preferenceChanged() in its parent. *
* Usually this method only makes sense when the layout state * is a generic wrapper around a black-box view. If layout state * and the view are one object then this method is usually no-op. *
* The layout state should just mark its internal state as changed * but wait for layout update (that will be called by parent) * to update the layout variables. *
* This method must be no-op for flyweight layout states. * * @param width true if the width preference has changed * @param height true if the height preference has changed */ public void viewPreferenceChanged(boolean width, boolean height); /** * Parent calls this method to mark the current size of the view as invalid * so that the next layout update of this layout state * will call View.setSize() * using {@link #getLayoutMajorAxisPreferredSpan()} for major axis span * and {@link ViewLayoutState.Parent#getMinorAxisSpan(ViewLayoutState)} * for minor axis span. *
* Parent is responsible for scheduling of layout update for the child * after calling this method. *
* This method must be no-op for flyweight layout states. */ public void markViewSizeInvalid(); /** * Check whether there are any layout duties present. * * @return true if there are no layout duties or false * if the layout needs to be udpated. *
* Flyweight layout states must always return true here. */ public boolean isLayoutValid(); /** * Interface that the parent view of the view * wrapped by ViewLayoutState * is expected to implement. */ public interface Parent { /** * By using this method a child layout state notifies its parent that * its requirement for span along the major axis has changed * against the previous value. *
* It can be done anytime but typically during * {@link #updateLayout()} execution. *
* The child will be automatically scheduled for repaint (together * with all children that follow it in the parent view) after * this method gets called. * * @param child child layout state which preference has changed. * @param majorAxisSpanDelta delta between the new span and the original span. */ public void majorAxisPreferenceChanged(ViewLayoutState child, double majorAxisSpanDelta); /** * By using this method a child layout state notifies its parent that * either preferred, minimum or maximum spans or aligment * along the minor axis has changed against their previous values. *
* It can be done anytime but typically during * {@link #updateLayout()} execution. * * @param child child layout state which preference has changed. */ public void minorAxisPreferenceChanged(ViewLayoutState child); /** * Notify this view that layout of the particular child * has become invalid and needs to be updated. *
* The parent can update the child's layout either immediately * or later. */ public void layoutInvalid(ViewLayoutState child); /** * Get span of the given child along the minor axis. *
* Parent computes the span according to its own layout policy * for the children. *
* This method is typically called from the layout state's methods * and is thus useful for non-flyweight layout states only * as flyweights do not maintain the parent. * * @param child child layout state for which the span is being * determined. */ public float getMinorAxisSpan(ViewLayoutState child); /** * Inform the parent that the child layout state needs a repaint. *
* This method can be called anytime although usually * it's called during the layout state's updateLayout(). *
* This method can be called repetively. The lowest offsets * should finally be used by the parent. * * @param child child that needs its area to be repainted. * @param majorAxisOffset offset along the major axis defining * the begining of the repaint region. If the allocation * has changed along the major axis the view is fully repainted * (see majorAxisPreferenceChanged()). *
* This parameter is typically zero but can be used * e.g. for line-wrapping views when typing on the last line. * @param minorAxisOffset offset along the minor axis * defining the begining of the repaint region. * @param majorAxisSpan span along the major axis * that should be repainted. If it is set to zero then * it means that the end of the repaint region along the major axis * span is determined by the span allocated for the child * in this parent. * @param minorAxisSpan span along the minor axis * that should be repainted. If it is set to zero then * it means that the end of the repaint region along the minor axis * span is determined by the span of this parent. */ public void repaint(ViewLayoutState child, double majorAxisOffset, double majorAxisSpan, float minorAxisOffset, float minorAxisSpan); } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.