--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr;
+
+import org.apache.fop.fo.FObj;
+import org.apache.fop.area.Area;
+
+import java.util.Iterator;
+
+/**
+ * The base class for all LayoutManagers.
+ */
+public abstract class AbstractLayoutManager implements LayoutManager {
+ protected LayoutManager parentLM;
+ protected FObj fobj;
+
+
+ public AbstractLayoutManager(FObj fobj) {
+ this.fobj = fobj;
+ this.parentLM = null;
+ }
+
+ public void setParentLM(LayoutManager lm) {
+ this.parentLM = lm;
+ }
+
+
+ /**
+ * Propagates to lower level layout managers. It iterates over the
+ * children of its FO, asks each for its LayoutManager and calls
+ * its generateAreas method.
+ */
+ public void generateAreas() {
+ Iterator children = fobj.getChildren();
+ while (children.hasNext()) {
+ LayoutManager lm = ((FObj)children.next()).getLayoutManager();
+ lm.setParentLM(this);
+ if (lm != null) {
+ lm.generateAreas();
+ }
+ }
+ flush(); // Add last area to parent
+ }
+
+// /**
+// * Ask the parent LayoutManager to add the current (full) area to the
+// * appropriate parent area.
+// * @param bFinished If true, this area is finished, either because it's
+// * completely full or because there is no more content to put in it.
+// * If false, we are in the middle of this area. This can happen,
+// * for example, if we find floats in a line. We stop the current area,
+// * and add it (temporarily) to its parent so that we can see if there
+// * is enough space to place the float(s) anchored in the line.
+// */
+// protected void flush(Area area, boolean bFinished) {
+// if (area != null) {
+// // area.setFinished(true);
+// parentLM.addChild(area, bFinished); // ????
+// if (bFinished) {
+// setCurrentArea(null);
+// }
+// }
+// }
+
+ /**
+ * Force current area to be added to parent area.
+ */
+ abstract protected void flush();
+
+
+ /**
+ * Return an Area which can contain the passed childArea. The childArea
+ * may not yet have any content, but it has essential traits set.
+ * In general, if the LayoutManager already has an Area it simply returns
+ * it. Otherwise, it makes a new Area of the appropriate class.
+ * It gets a parent area for its area by calling its parent LM.
+ * Finally, based on the dimensions of the parent area, it initializes
+ * its own area. This includes setting the content IPD and the maximum
+ * BPD.
+ */
+ abstract public Area getParentArea(Area childArea);
+
+
+ public boolean generatesInlineAreas() {
+ return false;
+ }
+
+ public boolean generatesLineAreas() {
+ return false;
+ }
+
+ /**
+ * Add a child area to the current area. If this causes the maximum
+ * dimension of the current area to be exceeded, the parent LM is called
+ * to add it.
+ */
+ abstract public void addChild(Area childArea) ;
+
+ /** Do nothing */
+ public boolean splitArea(Area areaToSplit, SplitContext context) {
+ context.nextArea = areaToSplit;
+ return false;
+ }
+
+}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr;
+
+import org.apache.fop.fo.FObj;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.BlockParent;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.MinOptMax;
+
+import java.util.Iterator;
+
+/**
+ * Base LayoutManager class for all areas which stack their child
+ * areas in the block-progression direction, such as Flow, Block, ListBlock.
+ */
+public abstract class BlockStackingLayoutManager
+ extends AbstractLayoutManager {
+ /** Reference to FO whose areas it's managing or to the traits
+ * of the FO.
+ */
+ LayoutManager curChildLM = null;
+ BlockParent parentArea = null;
+
+ public BlockStackingLayoutManager(FObj fobj) {
+ super(fobj);
+ }
+
+
+
+ public boolean splitArea(Area area, SplitContext splitContext) {
+ // Divide area so that it will be within targetLength if possible
+ // If not, it can be shorter, but not longer.
+ /* Iterate over contents of the area. */
+
+ // Need to figure out if we can do this generically
+ // Logically a BlockStacking LM only handles Block-type areas
+ if (!(area instanceof BlockParent)) {
+ return false;
+ }
+ Iterator areaIter = ((BlockParent)area).getChildAreas().iterator();
+
+
+ BreakCost minBreakCost = null;
+ MinOptMax remainBPD = splitContext.targetBPD;
+ splitContext.nextArea = area;
+
+ while (areaIter.hasNext()) {
+ Area childArea = (Area)areaIter.next();
+ if (remainBPD.max < childArea.getAllocationBPD().min) {
+ // Past the end point: try to break it
+ // TODO: get a LayoutManager to do the split of the child
+ // area, either Area => LM or Area => gen FO => LM
+ LayoutManager childLM = childArea.getGeneratingFObj().
+ getLayoutManager();
+ splitContext.targetBPD = remainBPD;
+ if (childLM.splitArea(childArea, splitContext) == false) {
+ // Can't split, so must split this area before childArea
+ // Can we pass the iter?
+ // If already saw several a potential break, use it
+ if (minBreakCost != null) {
+ /* Split 'area', placing all children after
+ * minBreakCost.getArea() into a new area,
+ * which we store in the splitContext.
+ */
+ // splitContext.nextArea = area.splitAfter(minBreakCost.getArea());
+ }
+ else {
+ /* This area will be shorter than the desired minimum.
+ * Split before the current childArea (which will be
+ * the first area in the newly created Area.
+ */
+ //splitContext.nextArea = area.splitBefore(childArea);
+ }
+ }
+ else return true; // childLM has done the work for us!
+ // Set cost, dimension ???
+ break;
+ }
+ else {
+ remainBPD.subtract(childArea.getAllocationBPD());
+ if (remainBPD.min < 0) {
+ // Potential breakpoint: remember break Position and
+ // break "cost" (constraint violation)
+ BreakCost breakCost = evaluateBreakCost(area, childArea);
+ minBreakCost = breakCost.chooseLowest(minBreakCost);
+ }
+ }
+ //Note: size of area when split can depend on conditional
+ // space, border and padding of the split area!!!
+ }
+ // True if some part of area can be placed, false if none is placed
+ return (splitContext.nextArea != area);
+
+ }
+
+ private BreakCost evaluateBreakCost(Area parent, Area child) {
+ return new BreakCost(child,0);
+ }
+
+ /** return current area being filled
+ */
+ protected BlockParent getCurrentArea() {
+ return this.parentArea;
+ }
+
+
+ /**
+ * Set the current area being filled.
+ */
+ protected void setCurrentArea(BlockParent parentArea) {
+ this.parentArea = parentArea;
+ }
+
+
+
+ protected MinOptMax resolveSpaceSpecifier(Area nextArea) {
+ SpaceSpecifier spaceSpec = new SpaceSpecifier();
+// Area prevArea = getCurrentArea().getLast();
+// if (prevArea != null) {
+// spaceSpec.addSpace(prevArea.getSpaceAfter());
+// }
+// spaceSpec.addSpace(nextArea.getSpaceBefore());
+ return spaceSpec.resolve();
+ }
+
+ /**
+ * Add the childArea to the passed area.
+ * Called by child LayoutManager when it has filled one of its areas.
+ * The LM should already have an Area in which to put the child.
+ * See if the area will fit in the current area.
+ * If so, add it. Otherwise initiate breaking.
+ * @param childArea the area to add: will be some block-stacked Area.
+ * @param parentArea the area in which to add the childArea
+ */
+ protected void addChildToArea(Area childArea, BlockParent parentArea) {
+ // This should be a block-level Area (Block in the generic sense)
+ if (!(childArea instanceof Block)) {
+ System.err.println("Child not a Block in BlockStackingLM!");
+ return;
+ }
+
+ // See if the whole thing fits, including space before
+ // Calculate space between last child in curFlow and childArea
+ MinOptMax targetDim = parentArea.getAvailBPD();
+ MinOptMax spaceBefore = resolveSpaceSpecifier(childArea) ;
+ targetDim.subtract(spaceBefore);
+ if (targetDim.max >= childArea.getAllocationBPD().min) {
+ //parentArea.addBlock(new InterBlockSpace(spaceBefore));
+ parentArea.addBlock((Block)childArea);
+ return;
+ }
+ else {
+ // Probably need something like max BPD so we don't get into
+ // infinite loops with large unbreakable chunks
+ SplitContext splitContext = new SplitContext(targetDim);
+
+ LayoutManager childLM = childArea.getGeneratingFObj().
+ getLayoutManager();
+ if (childLM.splitArea(childArea, splitContext)) {
+ //parentArea.addBlock(new InterBlockSpace(spaceBefore));
+ parentArea.addBlock((Block)childArea);
+ }
+ flush(); // hand off current area to parent
+ getParentArea(splitContext.nextArea);
+ // Check that reference IPD hasn't changed!!!
+ // If it has, we must "reflow" the content
+ addChild(splitContext.nextArea);
+ }
+ }
+
+
+ /**
+ * Add the childArea to the current area.
+ * Called by child LayoutManager when it has filled one of its areas.
+ * The LM should already have an Area in which to put the child.
+ * See if the area will fit in the current area.
+ * If so, add it. Otherwise initiate breaking.
+ * @param childArea the area to add: will be some block-stacked Area.
+ */
+ public void addChild(Area childArea) {
+ addChildToArea((Block)childArea, getCurrentArea());
+ }
+
+ /**
+ * Force current area to be added to parent area.
+ */
+ protected void flush() {
+ parentLM.addChild(getCurrentArea());
+ }
+
+
+}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr;
+
+import org.apache.fop.area.Area;
+
+
+/**
+ * Evaluate and store the cost of breaking an Area at a given point.
+ */
+public class BreakCost {
+ private Area breakArea;
+
+ private int cost; // Will be more complicated than this!
+
+ public BreakCost(Area breakArea, int cost) {
+ this.breakArea = breakArea;
+ this.cost = cost;
+ }
+
+ Area getArea() {
+ return breakArea;
+ }
+
+ public BreakCost chooseLowest(BreakCost otherCost) {
+ return this;
+ }
+}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.properties.Constants;
+import org.apache.fop.area.*;
+
+/**
+ * LayoutManager for an fo:flow object.
+ * Its parent LM is the PageLayoutManager.
+ * This LM is responsible for getting columns of the appropriate size
+ * and filling them with block-level areas generated by its children.
+ */
+public class FlowLayoutManager extends BlockStackingLayoutManager {
+
+ /** Array of areas currently being filled stored by area class */
+ private BlockParent[] currentAreas = new BlockParent[Area.CLASS_MAX];
+
+ /**
+ * This is the top level layout manager.
+ * It is created by the PageSequence FO.
+ */
+ public FlowLayoutManager(FObj fobj) {
+ super(fobj);
+ }
+
+
+
+ /**
+ * Add child area to a the correct container, depending on its
+ * area class. A Flow can fill at most one area container of any class
+ * at any one time. The actual work is done by BlockStackingLM.
+ */
+ public void addChild(Area childArea) {
+ addChildToArea(childArea,
+ this.currentAreas[childArea.getAreaClass()]);
+ }
+
+ public Area getParentArea(Area childArea) {
+ // Get an area from the Page
+ BlockParent parentArea =
+ (BlockParent)parentLM.getParentArea(childArea);
+ this.currentAreas[parentArea.getAreaClass()] = parentArea;
+ setCurrentArea(parentArea);
+ return parentArea;
+ }
+
+
+}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr;
+
+
+import org.apache.fop.area.Area;
+
+/**
+ * The interface for all LayoutManagers.
+ */
+public interface LayoutManager {
+ public void generateAreas();
+ public Area getParentArea (Area childArea);
+ public void addChild (Area childArea);
+ public boolean splitArea(Area areaToSplit, SplitContext context);
+ public void setParentLM(LayoutManager lm);
+}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.area.*;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.properties.Constants;
+
+/**
+ * LayoutManager for a PageSequence and its flow.
+ * It manages all page-related layout.
+ */
+public class PageLayoutManager extends AbstractLayoutManager
+ implements Runnable{
+
+ private PageSequence pageseq;
+ /** True if haven't yet laid out any pages.*/
+ private boolean bFirstPage;
+ /** Current page being worked on. */
+ private PageViewport curPage;
+
+ /** Body region of the current page */
+ private BodyRegion curBody;
+
+ /** Current span being filled */
+ private Span curSpan;
+
+ /** Number of columns in current span area. */
+ private int curSpanColumns;
+
+
+ /** Current flow-reference-area (column) being filled. */
+ private Flow curFlow;
+
+ /** Manager which handles a queue of all pages which are completely
+ * laid out and ready for rendering, except for resolution of ID
+ * references?
+ */
+ private AreaTree areaTree;
+
+ /**
+ * This is the top level layout manager.
+ * It is created by the PageSequence FO.
+ */
+ public PageLayoutManager(AreaTree areaTree, PageSequence pageseq) {
+ super( pageseq);
+ this.areaTree = areaTree;
+ }
+
+
+ /**
+ * The layout process is designed to be able to be run in a thread.
+ * In theory it can run at the same
+ * time as FO tree generation, once the layout-master-set has been read.
+ * We can arrange it so that the iterator over the fobj children waits
+ * until the next child is available.
+ * As it produces pages, it adds them to the AreaTree, where the
+ * rendering process can also run in a parallel thread.
+ */
+ public void run() {
+ generateAreas();
+ }
+
+
+ /**
+ * For now, only handle normal flow areas.
+ */
+ public void addChild(Area childArea) {
+ if (childArea.getAreaClass() == Area.CLASS_NORMAL) {
+ placeFlowRefArea(childArea);
+ }
+ else ; // TODO: all the others!
+ }
+
+ /**
+ * Place a FlowReferenceArea into the current span. The FlowLM is
+ * responsible for making sure that it will actually fit in the
+ * current span area. In fact the area has already been added to the
+ * current span, so we are just checking to see if the span is "full",
+ * possibly moving to the next column or to the next page.
+ */
+ protected void placeFlowRefArea(Area area) {
+ // assert (curSpan != null);
+ // assert (area == curFlow);
+ // assert (curFlow == curSpan.getFlow(curSpan.getColumnCount()-1));
+ // assert (area.getBPD().min < curSpan.getHeight());
+ // Last column on this page is filled
+ // See if the flow is full. The Flow LM can add an area before
+ // it's full in the case of a break or a span.
+ // Also in the case of a float to be placed. In that case, there
+ // may be further material added later.
+ // The Flow LM sets the "finished" flag on the Flow Area if it has
+ // completely filled it. In this case, if on the last column
+ // end the page.
+
+ // Alternatively the child LM indicates to parent that it's full?
+ if (area.getAllocationBPD().max >= curSpan.getMaxBPD().min) {
+ // Consider it filled
+ if (curSpan.getColumnCount() == curSpanColumns) {
+ finishPage();
+ }
+ else curFlow = null; // Create new flow on next getParentArea()
+ }
+ }
+
+
+ protected void placeAbsoluteArea(Area area) {
+ }
+
+
+ protected void placeBeforeFloat(Area area) {
+ }
+
+
+ protected void placeSideFloat(Area area) {
+ }
+
+ protected void placeFootnote(Area area) {
+ // After doing this, reduce available space on the curSpan.
+ // This has to be propagated to the curFlow (FlowLM) so that
+ // it can adjust its limit for composition (or it just asks
+ // curSpan for BPD before doing the break?)
+ // If multi-column, we may have to balance to find more space
+ // for a float. When?
+ }
+
+
+
+ private PageViewport makeNewPage(boolean bIsBlank, boolean bIsLast) {
+ finishPage();
+ try {
+ curPage = pageseq.createPage(bIsBlank, bIsLast);
+ } catch (FOPException fopex) { /* ???? */ }
+ curBody = (BodyRegion) curPage.getPage().
+ getRegion(RegionReference.BODY).getRegion();
+ return curPage;
+ }
+
+ private void finishPage() {
+ if (curPage != null) {
+ // Layout static content into the regions
+ // Need help from pageseq for this
+ // Queue for ID resolution and rendering
+ areaTree.addPage(curPage);
+ curPage = null;
+ curBody = null;
+ curSpan=null;
+ curFlow=null;
+ }
+ }
+
+ /**
+ * This is called from FlowLayoutManager when it needs to start
+ * a new flow container (while generating areas).
+ * @param area The area for which a container is needed. It must be
+ * some kind of block-level area. It must have area-class, break-before
+ * and span properties set.
+ */
+ public Area getParentArea(Area childArea) {
+ int aclass = childArea.getAreaClass() ;
+ if (aclass == Area.CLASS_NORMAL) {
+ // TODO: how to get properties from the Area???
+ // Need span, break
+ int breakVal = Constants.AUTO; // childArea.getBreakBefore();
+ if (breakVal != Constants.AUTO) {
+ // We may be forced to make new page
+ handleBreak(breakVal);
+ }
+ else if (curPage == null) {
+ makeNewPage(false, false);
+ }
+ // Now we should be on the right kind of page
+ boolean bNeedSpan = false;
+ int span = Constants.NONE; // childArea.getSpan()
+ int numCols=1;
+ if (span == Constants.ALL) {
+ // Assume the number of columns is stored on the curBody object.
+ //numCols = curBody.getProperty(NUMBER_OF_COLUMNS);
+ }
+ if (curSpan == null) {
+ createBodyMainReferenceArea();
+ bNeedSpan = true;
+ }
+ else if (numCols != curSpanColumns) {
+ // TODO: BALANCE EXISTING COLUMNS
+ if (curSpanColumns > 1) {
+ // balanceColumns();
+ }
+ bNeedSpan = true;
+ }
+ if (bNeedSpan) {
+ // Make a new span and the first flow
+ createSpan(numCols);
+ }
+ else if (curFlow == null) {
+ createFlow();
+ }
+ return curFlow;
+ }
+ else {
+ if (curPage == null) {
+ makeNewPage(false, false);
+ }
+ // Now handle different kinds of areas
+ if (aclass == Area.CLASS_BEFORE_FLOAT) {
+ BeforeFloat bf = curBody.getBeforeFloat();
+ if (bf == null) {
+ bf = new BeforeFloat();
+ curBody.setBeforeFloat(bf);
+ }
+ return bf;
+ }
+ else if (aclass == Area.CLASS_FOOTNOTE) {
+ Footnote fn = curBody.getFootnote();
+ if (fn == null) {
+ fn = new Footnote();
+ curBody.setFootnote(fn);
+ }
+ return fn;
+ }
+ // TODO!!! other area classes (side-float, absolute, fixed)
+ return null;
+ }
+ }
+
+
+ /**
+ * Depending on the kind of break condition, make new column
+ * or page. May need to make an empty page if next page would
+ * not have the desired "handedness".
+ */
+ protected void handleBreak(int breakVal) {
+ if (breakVal == Constants.COLUMN) {
+ if (curSpan != null &&
+ curSpan.getColumnCount() != curSpanColumns) {
+ // Move to next column
+ createFlow();
+ return;
+ }
+ // else need new page
+ breakVal = Constants.PAGE;
+ }
+ if (needEmptyPage(breakVal)) {
+ curPage = makeNewPage(true, false);
+ }
+ if (needNewPage(breakVal)) {
+ curPage = makeNewPage(false, false);
+ }
+ }
+
+
+ /**
+ * If we have already started to layout content on a page,
+ * and there is a forced break, see if we need to generate
+ * an empty page.
+ * Note that if not all content is placed, we aren't sure whether
+ * it will flow onto another page or not, so we'd probably better
+ * block until the queue of layoutable stuff is empty!
+ */
+ private boolean needEmptyPage(int breakValue) {
+ return false;
+// if (breakValue == Constants.PAGE || curPage.isEmpty()) {
+// // any page is OK or we already have an empty page
+// return false;
+// }
+// else {
+// /* IF we are on the kind of page we need, we'll need a new page. */
+// if (curPage.getPageNumber()%2 != 0) {
+// // Current page is odd
+// return (breakValue == Constants.ODD_PAGE);
+// }
+// else {
+// return (breakValue == Constants.EVEN_PAGE);
+// }
+// }
+ }
+
+ /**
+ * See if need to generate a new page for a forced break condition.
+ * TODO: methods to see if the current page is empty and to get
+ * its number.
+ */
+ private boolean needNewPage(int breakValue) {
+ return false;
+// if (curPage.isEmpty()) {
+// if (breakValue == Constants.PAGE) {
+// return false;
+// }
+// else if (curPage.getPageNumber()%2 != 0) {
+// // Current page is odd
+// return (breakValue == Constants.EVEN_PAGE);
+// }
+// else {
+// return (breakValue == Constants.ODD_PAGE);
+// }
+// }
+// else {
+// return true;
+// }
+ }
+
+
+ private void createBodyMainReferenceArea() {
+ curBody.setMainReference(new MainReference());
+ }
+
+
+
+ private Flow createFlow() {
+ curFlow = new Flow();
+ // Set IPD and max BPD on the curFlow from curBody
+ curSpan.addFlow(curFlow);
+ return curFlow;
+ }
+
+ private void createSpan(int numCols) {
+ // check number of columns (= all in Body or 1)
+ // If already have a span, get its size and position (as MinMaxOpt)
+ // This determines the position of the new span area
+ // Attention: space calculation between the span areas.
+
+// MinOptMax newpos ;
+// if (curSpan != null) {
+// newpos = curSpan.getPosition(BPD);
+// newpos.add(curSpan.getDimension(BPD));
+// }
+// else newpos = new MinOptMax();
+ curSpan = new Span(numCols);
+ //curSpan.setPosition(BPD, newpos);
+ curBody.getMainReference().addSpan(curSpan);
+ createFlow();
+ }
+
+ // See finishPage...
+ protected void flush() {}
+
+}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr;
+
+import org.apache.fop.area.Area;
+import org.apache.fop.area.MinOptMax;
+import org.apache.fop.datatypes.Space;
+
+
+/**
+ * Accumulate a sequence of space-specifiers (XSL space type) on
+ * areas with a stacking constraint. Provide a way to resolve these into
+ * a single MinOptMax value.
+ */
+public class SpaceSpecifier {
+
+ /**
+ * Combine passed space property value with any existing space.
+ */
+ public void addSpace(Space moreSpace) {
+ }
+
+ public MinOptMax resolve() {
+ return new MinOptMax();
+ }
+}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.layoutmgr;
+
+import org.apache.fop.area.Area;
+import org.apache.fop.area.MinOptMax;
+
+public class SplitContext {
+
+ Area nextArea;
+ MinOptMax targetBPD;
+
+ public SplitContext(MinOptMax targetBPD) {
+ this.targetBPD = targetBPD;
+ nextArea = null;
+ }
+
+}