/*
The contents of this file are subject to the Common Public Attribution License
Version 1.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.projity.com/license . The License is based on the Mozilla Public
License Version 1.1 but Sections 14 and 15 have been added to cover use of
software over a computer network and provide for limited attribution for the
Original Developer. In addition, Exhibit A has been modified to be consistent
with Exhibit B.

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
specific language governing rights and limitations under the License. The
Original Code is OpenProj. The Original Developer is the Initial Developer and
is Projity, Inc. All portions of the code written by Projity are Copyright (c)
2006, 2007. All Rights Reserved. Contributors Projity, Inc.

Alternatively, the contents of this file may be used under the terms of the
Projity End-User License Agreeement (the Projity License), in which case the
provisions of the Projity License are applicable instead of those above. If you
wish to allow use of your version of this file only under the terms of the
Projity License and not to allow others to use your version of this file under
the CPAL, indicate your decision by deleting the provisions above and replace
them with the notice and other provisions required by the Projity  License. If
you do not delete the provisions above, a recipient may use your version of this
file under either the CPAL or the Projity License.

[NOTE: The text of this license may differ slightly from the text of the notices
in Exhibits A and B of the license at http://www.projity.com/license. You should
use the latest text at http://www.projity.com/license for your modifications.
You may not remove this license text from the source files.]

Attribution Information: Attribution Copyright Notice: Copyright � 2006, 2007
Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
an open source solution from Projity. Attribution URL: http://www.projity.com
Graphic Image as provided in the Covered Code as file:  openproj_logo.png with
alternatives listed on http://www.projity.com/logo

Display of Attribution Information is required in Larger Works which are defined
in the CPAL as a work which combines Covered Code or portions thereof with code
not governed by the terms of the CPAL. However, in addition to the other notice
obligations, all copies of the Covered Code in Executable and Source Code form
distributed must, as a form of attribution of the original author, include on
each user interface screen the "OpenProj" logo visible to all users.  The
OpenProj logo should be located horizontally aligned with the menu bar and left
justified on the top left of the screen adjacent to the File menu.  The logo
must be at least 100 x 25 pixels.  When users click on the "OpenProj" logo it
must direct them back to http://www.projity.com.
*/
package com.projity.print;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DecimalFormat;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.SpinnerNumberModel;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.projity.offline_graphics.SVGRenderer;
import com.projity.pm.graphic.graph.GraphParams;
import com.projity.strings.Messages;
import com.projity.util.Environment;
/**
 *
 */
public class PageSetup{
	private static final long serialVersionUID = 1L;

	public static final double INCH=2.54;
	public static final double POINT=INCH/72;

	private GraphPageable document;
	private ExtendedPageFormat pageFormat;
	private ExtendedPrintService extendedPrintService;

	public static PageSetup getInstance(GraphPageable document) {
		return new PageSetup(document);
	}
	private PageSetup(GraphPageable document) {
		this.document=document;
		pageFormat=document.getPageFormat();
		//HelpUtil.addDocHelp(this,"Print_Preview"); //TODO specific help
		extendedPrintService=ExtendedPrintServiceFactory.getExtendedPrintService();
	}


	protected JTabbedPane tabbedPane;

	protected JComboBox paperSize;
	protected JButton printerPageSetup;
	protected JCheckBox singlePagePaperSize;
	protected JFormattedTextField paperWidth,paperHeight;
	protected JLabel paperWidthLabel,paperHeightLabel;

	protected JLabel marginLeftLabel,marginRightLabel,marginTopLabel,marginBottomLabel;
	protected JFormattedTextField marginLeft,marginRight,marginTop,marginBottom;

	protected JComboBox orientation;
	protected String portrait,landscape,reverseLandscape;

	protected JCheckBox printSpreadSheet,printGantt;

	protected JRadioButton scaleTo,fitTo;
	protected JSpinner fitToWidth,fitToHeight,scaleToWidth,scaleToHeight;
	protected JLabel fitToWidthLabel,fitToHeightLabel,scaleToWidthLabel,scaleToHeightLabel,scaleToProportions,scaleToProportions2;
	protected JCheckBox constrainProportions;

	protected JButton refresh;

	protected double svgPaperWidth,svgPaperHeight,svgZoomX,svgZoomY;

	protected void initFont(JComponent c){
		c.setFont(c.getFont().deriveFont(8));
	}

	protected int updating;
	protected void beginUpdate(){
		updating++;
	}
	protected void endUpdate(){
		updating--;
	}
	protected boolean isUpdaping(){
		return updating>0;
	}

	protected void initControls() {
		beginUpdate();

		printerPageSetup=new JButton(Messages.getString("PageSetupDialog.PrinterPageSetup"));
		printerPageSetup.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				PageFormat newPageFormat=document.printerPageFormatDialog(pageFormat);
				if (newPageFormat!=null){
					pageFormat.setPageFormat(newPageFormat);
					//printerPaperSize.setSelected(true);
					Dimension d=new Dimension();
					d.setSize(pageFormat.getPaper().getWidth(),pageFormat.getPaper().getHeight());
					beginUpdate();
					updatePageSize(false);
					updateOrientation();
					paperSize.setSelectedItem(PageSizes.dimensionToPageSize(d));
					endUpdate();
					refresh();
				}
			}
		});
		initFont(printerPageSetup);

		//paper
		singlePagePaperSize=new JCheckBox("",false);
		singlePagePaperSize.addItemListener(new ItemListener(){
			public void itemStateChanged(ItemEvent e) {
				beginUpdate();
				boolean selected=singlePagePaperSize.isSelected();
				//pageFormat.setSinglePage(selected);

				boolean customPaper=PageSizes.isCustomPageSize(paperSize.getSelectedItem());
				printerPageSetup.setEnabled(!selected);
				paperSize.setEnabled(!selected);
				orientation.setEnabled(!selected);
				paperWidthLabel.setEnabled(!selected&&customPaper);
				paperWidth.setEnabled(!selected&&customPaper);
				paperHeightLabel.setEnabled(!selected&&customPaper);
				paperHeight.setEnabled(!selected&&customPaper);
				if (selected) scaleTo.setSelected(true);


				if (selected){
					svgPaperWidth=pageFormat.getPaper().getWidth();
					svgPaperHeight=pageFormat.getPaper().getHeight();
					SVGRenderer renderer=document.getRenderer();
					Dimension d=renderer.getCanvasSize();
					GraphParams params=renderer.getParams();
					double w=pageFormat.getOrientation()==PageFormat.PORTRAIT?d.getWidth():d.getHeight();
					double h=pageFormat.getOrientation()==PageFormat.PORTRAIT?d.getHeight():d.getWidth();
					int footerH=params.getConfiguration().getPrintFooterHeight();
					double[] margins=pageFormat.getMargins(false);
					if (pageFormat.getOrientation()==PageFormat.PORTRAIT) h+=footerH;
					else w+=footerH;
					w=w*document.getTotalZoomX()+margins[0]+margins[1];
					h=h*document.getTotalZoomY()+margins[2]+margins[3];
					updateImageableArea(w,h);
				}else{
					updateImageableArea(svgPaperWidth,svgPaperHeight);
				}

				endUpdate();
				refresh();
			}
		});
		initFont(singlePagePaperSize);
		paperSize=new JComboBox(PageSizes.getPageSizes());
		paperSize.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				Dimension d=PageSizes.pageSizeToDimension(paperSize.getSelectedItem());
				boolean customPaper=PageSizes.isCustomPageSize(paperSize.getSelectedItem());
				boolean selected=!singlePagePaperSize.isSelected();
				paperSize.setEnabled(selected);
				paperWidthLabel.setEnabled(selected&&customPaper);
				paperWidth.setEnabled(selected&&customPaper);
				paperHeightLabel.setEnabled(selected&&customPaper);
				paperHeight.setEnabled(selected&&customPaper);
				if (isUpdaping()) return;
				if (d!=null){
					updateImageableArea(d.getWidth(),d.getHeight());
					beginUpdate();
					paperWidth.setValue(toUserUnit(d.getWidth()));
					paperHeight.setValue(toUserUnit(d.getHeight()));
					endUpdate();
				}
				refresh();
			}
		});
		initFont(paperSize);
		paperSize.setEnabled(false);
		paperWidthLabel=new JLabel(Messages.getString("PageSetupDialog.PaperSizeSettings.Custom.Width"));
		paperWidthLabel.setEnabled(false);
		initFont(paperWidthLabel);
		DecimalFormat decimalFormat=new DecimalFormat("#0.00");
		paperWidth=new JFormattedTextField(decimalFormat);
		paperWidth.setEnabled(false);
		paperWidth.addPropertyChangeListener("value",new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent e) {
				if (isUpdaping()) return;
				updateImageableArea(toPoints(((Number)e.getNewValue()).doubleValue()),-1.0);
				refresh();
			}
		});
		initFont(paperWidth);
		paperHeightLabel=new JLabel(Messages.getString("PageSetupDialog.PaperSizeSettings.Custom.Height"));
		paperHeightLabel.setEnabled(false);
		initFont(paperHeightLabel);
		paperHeight=new JFormattedTextField(decimalFormat);
		paperHeight.setEnabled(false);
		paperHeight.addPropertyChangeListener("value",new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent e) {
				if (isUpdaping()) return;
				updateImageableArea(-1.0,toPoints(((Number)e.getNewValue()).doubleValue()));
				refresh();
			}
		});
		initFont(paperHeight);

		Dimension d=new Dimension();
		d.setSize(pageFormat.getPaper().getWidth(),pageFormat.getPaper().getHeight());
		paperSize.setSelectedItem(PageSizes.dimensionToPageSize(d));
		initFont(paperSize);

		//margins
		marginLeftLabel=new JLabel(Messages.getString("PageSetupDialog.Margins.Left"));
		initFont(marginLeftLabel);
		marginLeft=new JFormattedTextField(decimalFormat);
		marginLeft.addPropertyChangeListener("value",new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent e) {
				if (isUpdaping()) return;
				updateImageableArea(toPoints(((Number)e.getNewValue()).doubleValue()), -1.0, -1.0, -1.0);
				refresh();
			}
		});
		initFont(marginLeft);

		marginRightLabel=new JLabel(Messages.getString("PageSetupDialog.Margins.Right"));
		initFont(marginRightLabel);
		marginRight=new JFormattedTextField(decimalFormat);
		marginRight.addPropertyChangeListener("value",new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent e) {
				if (isUpdaping()) return;
				updateImageableArea(-1.0, toPoints(((Number)e.getNewValue()).doubleValue()), -1.0, -1.0);
				refresh();
			}
		});
		initFont(marginRight);

		marginTopLabel=new JLabel(Messages.getString("PageSetupDialog.Margins.Top"));
		initFont(marginTopLabel);
		marginTop=new JFormattedTextField(decimalFormat);
		marginTop.addPropertyChangeListener("value",new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent e) {
				if (isUpdaping()) return;
				updateImageableArea(-1.0, -1.0, toPoints(((Number)e.getNewValue()).doubleValue()), -1.0);
				refresh();
			}
		});
		initFont(marginTop);

		marginBottomLabel=new JLabel(Messages.getString("PageSetupDialog.Margins.Bottom"));
		initFont(marginBottomLabel);
		marginBottom=new JFormattedTextField(decimalFormat);
		marginBottom.addPropertyChangeListener("value",new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent e) {
				if (isUpdaping()) return;
				updateImageableArea(-1.0, -1.0, -1.0, toPoints(((Number)e.getNewValue()).doubleValue()));
				refresh();
			}
		});
		initFont(marginBottom);

		portrait=Messages.getString("PageSetupDialog.Orientation.Portrait");
		landscape=Messages.getString("PageSetupDialog.Orientation.Landscape");
		reverseLandscape=Messages.getString("PageSetupDialog.Orientation.ReverseLandscape");
		orientation=new JComboBox(new Object[]{portrait,landscape,reverseLandscape});
		orientation.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				if (isUpdaping()) return;
				Object selected=orientation.getSelectedItem();
				if (portrait.equals(selected)) pageFormat.setOrientation(PageFormat.PORTRAIT);
				if (landscape.equals(selected)) pageFormat.setOrientation(PageFormat.LANDSCAPE);
				if (reverseLandscape.equals(selected)) pageFormat.setOrientation(PageFormat.REVERSE_LANDSCAPE);
				beginUpdate();
				updateOrientation();
				endUpdate();
				refresh();
			}
		});
		initFont(orientation);



		if (document.getRenderer().getParams().isSupportLeftAndRightParts()){
			printSpreadSheet=new JCheckBox(Messages.getString("PageSetupDialog.ShowSpreadSheet"),true);
			printSpreadSheet.addItemListener(new ItemListener(){
				public void itemStateChanged(ItemEvent e) {
					if (isUpdaping()) return;
					boolean selected=printSpreadSheet.isSelected();
					GraphParams params=document.getRenderer().getParams();
					params.setLeftPartVisible(selected);
					if (!selected&&!printGantt.isSelected()){
						params.setRightPartVisible(true);
						beginUpdate();
						printGantt.setSelected(true);
						endUpdate();
					}

					refresh();
				}
			});
			initFont(printSpreadSheet);
			printGantt=new JCheckBox(Messages.getString("PageSetupDialog.ShowGantt"),true);
			printGantt.addItemListener(new ItemListener(){
				public void itemStateChanged(ItemEvent e) {
					if (isUpdaping()) return;
					boolean selected=printGantt.isSelected();
					GraphParams params=document.getRenderer().getParams();
					params.setRightPartVisible(selected);
					if (!selected&&!printGantt.isSelected()){
						params.setLeftPartVisible(true);
						beginUpdate();
						printSpreadSheet.setSelected(true);
						endUpdate();
					}

					refresh();
				}
			});
			initFont(printGantt);
		}



		//scaling
		scaleToWidthLabel=new JLabel(Messages.getString("PageSetupDialog.Scaling.ScaleToWidth"));
		scaleToWidthLabel.setEnabled(!Environment.isOpenProj());
		initFont(scaleToWidthLabel);
		scaleToWidth=new JSpinner(new SpinnerNumberModel(1.0,0.05,10.0,0.1));
		scaleToWidth.setEditor(new JSpinner.NumberEditor(scaleToWidth,"#%"));
		scaleToWidth.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e) {
				double ratio=((Number)scaleToWidth.getValue()).doubleValue();
				//pageFormat.setScaleWRatio(ratio);
				document.setZoomX(ratio);
				if (constrainProportions.isSelected()){
					//pageFormat.setScaleHRatio(ratio);
					document.setZoomY(ratio);
					beginUpdate();
					scaleToHeight.setValue(ratio);
					endUpdate();
				}
				refresh();
			}
		});
		scaleToWidth.setEnabled(!Environment.isOpenProj());
		initFont(scaleToWidth);

		scaleToHeightLabel=new JLabel(Messages.getString("PageSetupDialog.Scaling.ScaleToHeight"));
		scaleToHeightLabel.setEnabled(false);
		initFont(scaleToHeightLabel);
		scaleToHeight=new JSpinner(new SpinnerNumberModel(1.0,0.05,10.0,0.1));
		scaleToHeight.setEditor(new JSpinner.NumberEditor(scaleToHeight,"#%"));
		scaleToHeight.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e) {
				if (isUpdaping()) return;
				double ratio=((Number)scaleToHeight.getValue()).doubleValue();
				//pageFormat.setScaleHRatio(ratio);
				document.setZoomY(ratio);
				refresh();
			}
		});
		scaleToHeight.setEnabled(false);
		initFont(scaleToHeight);
		constrainProportions=new JCheckBox("",true);
		constrainProportions.addItemListener(new ItemListener(){
			public void itemStateChanged(ItemEvent e) {
				boolean selected=constrainProportions.isSelected();
				scaleToHeightLabel.setEnabled(!selected);
				scaleToHeight.setEnabled(!selected);
				if (selected) scaleToHeight.setValue(scaleToWidth.getValue());
			}
		});
		constrainProportions.setEnabled(!Environment.isOpenProj());
		initFont(constrainProportions);
		scaleToProportions=new JLabel(Messages.getString("PageSetupDialog.Scaling.ScaleToProportions"));
		scaleToProportions.setEnabled(!Environment.isOpenProj());
		initFont(scaleToProportions);
		scaleToProportions2=new JLabel(Messages.getString("PageSetupDialog.Scaling.ScaleToProportions2"));
		scaleToProportions2.setEnabled(!Environment.isOpenProj());
		initFont(scaleToProportions2);


		fitToWidthLabel=new JLabel(Messages.getString("PageSetupDialog.Scaling.FitToWidth"));
		fitToWidthLabel.setEnabled(false);
		initFont(fitToWidthLabel);
		fitToWidth=new JSpinner(new SpinnerNumberModel(1,1,99999,1));
		fitToWidth.setEnabled(false);
		fitToWidth.setEditor(new JSpinner.NumberEditor(fitToWidth,"#"));
		fitToWidth.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e) {
				if (isUpdaping()) return;
				//pageFormat.setPagesW(((Number)fitToWidth.getValue()).intValue());
				updateZoom(((Number)fitToWidth.getValue()).intValue(),((Number)fitToHeight.getValue()).intValue());
				refresh();
			}
		});
		initFont(fitToWidth);
		fitToHeightLabel=new JLabel(Messages.getString("PageSetupDialog.Scaling.FitToHeight"));
		fitToHeightLabel.setEnabled(false);
		initFont(fitToHeightLabel);
		fitToHeight=new JSpinner(new SpinnerNumberModel(1,1,99999,1));
		fitToHeight.setEnabled(false);
		fitToHeight.setEditor(new JSpinner.NumberEditor(fitToHeight,"#"));
		fitToHeight.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e) {
				if (isUpdaping()) return;
				//pageFormat.setPagesH(((Number)fitToHeight.getValue()).intValue());
				updateZoom(((Number)fitToWidth.getValue()).intValue(),((Number)fitToHeight.getValue()).intValue());
				refresh();
			}
		});
		initFont(fitToHeight);


		scaleTo=new JRadioButton(Messages.getString("PageSetupDialog.Scaling.ScaleTo"),true);
		scaleTo.setEnabled(!Environment.isOpenProj());
		initFont(scaleTo);
		fitTo=new JRadioButton(Messages.getString("PageSetupDialog.Scaling.FitTo"),false);
		fitTo.setEnabled(!Environment.isOpenProj());
		initFont(fitTo);
		ButtonGroup scalingRadio=new ButtonGroup();
		scalingRadio.add(scaleTo);
		scalingRadio.add(fitTo);
		scaleTo.addItemListener(new ItemListener(){
			public void itemStateChanged(ItemEvent e) {
				boolean selected=scaleTo.isSelected();

				//pageFormat.setScalingOption(selected?ExtendedPageFormat.SCALE_TO:ExtendedPageFormat.FIT_TO);
				scaleToWidth.setEnabled(selected);
				scaleToWidthLabel.setEnabled(selected);
				boolean constrain=constrainProportions.isSelected();
				scaleToHeight.setEnabled(selected&&!constrain);
				scaleToHeightLabel.setEnabled(selected&&!constrain);
				constrainProportions.setEnabled(selected);
				scaleToProportions.setEnabled(selected);
				scaleToProportions2.setEnabled(selected);
				fitToWidth.setEnabled(!selected);
				fitToWidthLabel.setEnabled(!selected);
				fitToHeight.setEnabled(!selected);
				fitToHeightLabel.setEnabled(!selected);
				if (!selected) singlePagePaperSize.setSelected(false);


				if (selected){
					document.setZoomX(svgZoomX);
					document.setZoomY(svgZoomY);
				}else{
					svgZoomX=document.getZoomX();
					svgZoomY=document.getZoomY();
					updateZoom();
				}
				refresh();
			}
		});

		refresh=new JButton(Messages.getString("PageSetupDialog.Refresh"));
		refresh.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				refresh();
			}
		});
		initFont(refresh);

		updatePageSize(true);
		updateOrientation();
		updateFitTo();
		endUpdate();
	}


	public void refresh(){
		if (fitTo.isSelected()) updateZoom();
		document.update();
		document.getPrintPreviewFrame().updatePanel();
		beginUpdate();
		if (!fitTo.isSelected()) updateFitTo();
		endUpdate();
	}
	public void updateFitTo(){
		GraphParams params=document.getRenderer().getParams();
		fitToWidth.setValue(params.getPrintCols());
		fitToHeight.setValue(params.getPrintRows());
	}

	private void updateZoom(){
		updateZoom(((Number)fitToWidth.getValue()).intValue(),((Number)fitToHeight.getValue()).intValue());
	}

	private void updateZoom(int pw,int ph){
		double iw=pageFormat.getImageableWidth();
		double ih=pageFormat.getImageableHeight();
		SVGRenderer renderer=document.getRenderer();
		GraphParams params=renderer.getParams();
		double zw=extendedPrintService.getWRatio(pw, iw,params);
		double zh=extendedPrintService.getHRatio(ph, ih,params);
		document.setTotalZoomX(zw);
		document.setTotalZoomY(zh);
	}

	private void updateImageableArea(double w,double h){ //margin fixed
		Paper oldPaper=pageFormat.getPaper();
		double left=oldPaper.getImageableX();
		double right=oldPaper.getWidth()-oldPaper.getImageableWidth()-oldPaper.getImageableX();
		double top=oldPaper.getImageableY();
		double bottom=oldPaper.getHeight()-oldPaper.getImageableHeight()-oldPaper.getImageableY();
		if (w<0) w=oldPaper.getWidth();
		if (h<0) h=oldPaper.getHeight();
		Paper paper=new Paper();
		paper.setSize(w, h);
		paper.setImageableArea(left, top, paper.getWidth()-left-right, paper.getHeight()-top-bottom);
		pageFormat.setPaper(paper);
	}
	private void updateImageableArea(double oleft,double oright,double otop, double obottom){ //size fixed
		Paper oldPaper=pageFormat.getPaper();

		int ori=pageFormat.getOrientation();
		double left=oleft;
		double right=oright;
		double top=otop;
		double bottom=obottom;
		switch (ori){
			case PageFormat.LANDSCAPE:
				left=otop;
				right=obottom;
				top=oright;
				bottom=oleft;
				break;
			case PageFormat.REVERSE_LANDSCAPE:
				left=obottom;
				right=otop;
				top=oleft;
				bottom=oright;
				break;
		}

		double oldLeft=oldPaper.getImageableX();
		double oldRight=oldPaper.getWidth()-oldPaper.getImageableWidth()-oldPaper.getImageableX();
		double oldTop=oldPaper.getImageableY();
		double oldBottom=oldPaper.getHeight()-oldPaper.getImageableHeight()-oldPaper.getImageableY();
		if (left<0) left=oldLeft;
		if (right<0) right=oldRight;
		if (top<0) top=oldTop;
		if (bottom<0) bottom=oldBottom;
		Paper paper=new Paper();
		double w=oldPaper.getWidth(),h=oldPaper.getHeight();
		if (singlePagePaperSize.isSelected()){
			w+=left-oldLeft+right-oldRight;
			h+=top-oldTop+bottom-oldBottom;
		}
		paper.setSize(w, h);
		paper.setImageableArea(left, top, w-left-right, h-top-bottom);
		pageFormat.setPaper(paper);
	}

	private void updatePageSize(boolean round){ //round for a Linux bug
		Paper paper=pageFormat.getPaper();
		double w=round?Math.round(paper.getWidth()):paper.getWidth();
		double h=round?Math.round(paper.getHeight()):paper.getHeight();
		paperWidth.setValue(toUserUnit(w));
		paperHeight.setValue(toUserUnit(h));
	}



	private void updateOrientation(){
		Paper paper=pageFormat.getPaper();
		int ori=pageFormat.getOrientation();
		double left=paper.getImageableX();
		double right=paper.getWidth()-paper.getImageableWidth()-paper.getImageableX();
		double top=paper.getImageableY();
		double bottom=paper.getHeight()-paper.getImageableHeight()-paper.getImageableY();
		switch (ori){
			case PageFormat.PORTRAIT:
				marginLeft.setValue(toUserUnit(left));
				marginRight.setValue(toUserUnit(right));
				marginTop.setValue(toUserUnit(top));
				marginBottom.setValue(toUserUnit(bottom));
				orientation.setSelectedItem(portrait);
				break;
			case PageFormat.LANDSCAPE:
				marginLeft.setValue(toUserUnit(bottom));
				marginRight.setValue(toUserUnit(top));
				marginTop.setValue(toUserUnit(left));
				marginBottom.setValue(toUserUnit(right));
				orientation.setSelectedItem(landscape);
				break;
			case PageFormat.REVERSE_LANDSCAPE:
				marginLeft.setValue(toUserUnit(top));
				marginRight.setValue(toUserUnit(bottom));
				marginTop.setValue(toUserUnit(right));
				marginBottom.setValue(toUserUnit(left));
				orientation.setSelectedItem(reverseLandscape);
				break;
		}
	}



	public double toUserUnit(double points){
		return points*POINT;
	}
	public double toPoints(double cm){
		return cm/POINT;
	}







	public JComponent createContentPanel(boolean bar) {
		initControls();
		if (bar) return createVerticalPanel();
		else return createDialogPanel();
//		FormLayout layout = new FormLayout("350dlu:grow","fill:250dlu:grow");
//		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
//		builder.setDefaultDialogBorder();
//		builder.add(createPagePanel());
//		return builder.getPanel();
	}

	private JComponent createDialogPanel(){
		FormLayout layout = new FormLayout("p, 3dlu, p, 3dlu","p, 3dlu,p, 3dlu, p, 3dlu,p,3dlu");
		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.setDefaultDialogBorder();
		builder.add(createPrinterPanel(),cc.xyw(1,1,3));
		builder.add(createPaperPanel(),cc.xywh(1,3,1,3));
		builder.add(createOrientationPanel(),cc.xy(3,3));
		builder.add(createMarginsPanel(),cc.xy(3,5));
		builder.add(createScalingPanel(),cc.xyw(1,7,3));
		return builder.getPanel();
	}

	private JComponent createPrinterPanel(){
		FormLayout layout = new FormLayout("p","p, 3dlu");
		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		builder.append(printerPageSetup);
		return builder.getPanel();
	}

	private JComponent createVerticalPanel(){
		FormLayout layout = new FormLayout("p",printSpreadSheet==null?"p,3dlu,p,3dlu,p,3dlu,p,3dlu,p,3dlu":"p,3dlu,p,3dlu,p,3dlu,p,3dlu,p,3dlu,p,3dlu");
		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		builder.setDefaultDialogBorder();
		builder.append(printerPageSetup);
		builder.nextLine(2);
		builder.append(createFlowOrientationPanel());
		builder.nextLine(2);
		builder.append(createFlowPaperPanel());
		builder.nextLine(2);
		builder.append(createFlowMarginsPanel());
		builder.nextLine(2);
		if (printSpreadSheet!=null){
			builder.append(createFlowPartPanel());
			builder.nextLine(2);
		}
		builder.append(createFlowScalingPanel());
		return builder.getPanel();
	}

	private JComponent createPaperPanel(){
		FormLayout layout = new FormLayout(
		        "8dlu, p,p,8dlu",
				"p, 3dlu:grow,p, 2dlu");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(createPaperSizePanel(),cc.xyw(2,1,2));
		builder.add(singlePagePaperSize,cc.xy(2,3));
		JLabel l=new JLabel(Messages.getString("PageSetupDialog.PaperSizeSettings.SinglePage")+" "+Messages.getString("PageSetupDialog.PaperSizeSettings.SinglePage2"));
		initFont(l);
		builder.add(l,cc.xy(2,3));
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.Paper")));
		return panel;
	}
	private JComponent createFlowPaperPanel(){
		FormLayout layout = new FormLayout(
		        "1dlu, p,p,p:grow,1dlu",
				"p, 3dlu:grow,p,p, 2dlu");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(createFlowPaperSizePanel(),cc.xyw(2,1,3));
		builder.add(singlePagePaperSize,cc.xy(2,3));
		JLabel l=new JLabel(Messages.getString("PageSetupDialog.PaperSizeSettings.SinglePage"));
		initFont(l);
		builder.add(l,cc.xy(3,3));
		l=new JLabel(Messages.getString("PageSetupDialog.PaperSizeSettings.SinglePage2"));
		initFont(l);
		builder.add(l,cc.xy(3,4));
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.Paper")));
		return panel;
	}
	private JComponent createPaperSizePanel(){
		FormLayout layout = new FormLayout("p, 3dlu,50dlu","p, 3dlu, p, 3dlu, p");
		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(paperSize,cc.xyw(1, 1, 3));
		builder.add(paperWidthLabel,cc.xy(1,3));
		builder.add(paperWidth,cc.xy(3,3));
		builder.add(paperHeightLabel,cc.xy(1,5));
		builder.add(paperHeight,cc.xy(3,5));
		return builder.getPanel();
	}
	private JComponent createFlowPaperSizePanel(){
		FormLayout layout = new FormLayout("p, 3dlu,35dlu","p, 3dlu, p, 3dlu, p");
		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(paperSize,cc.xyw(1, 1, 3));
		builder.add(paperWidthLabel,cc.xy(1,3));
		builder.add(paperWidth,cc.xy(3,3));
		builder.add(paperHeightLabel,cc.xy(1,5));
		builder.add(paperHeight,cc.xy(3,5));
		return builder.getPanel();
	}

	private JComponent createOrientationPanel(){
		FormLayout layout = new FormLayout(
		        "8dlu, 100dlu, 8dlu",
				"p,2dlu");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(orientation,cc.xy(2,1));
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.Orientation")));
		return panel;
	}
	private JComponent createFlowOrientationPanel(){
		FormLayout layout = new FormLayout(
		        "1dlu, p:grow, 1dlu",
				"p,2dlu");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(orientation,cc.xy(2,1));
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.Orientation")));
		return panel;
	}


	private JComponent createMarginsPanel(){
		FormLayout layout = new FormLayout(
		        "8dlu, 50dlu, 3dlu, 50dlu, 8dlu",
				"p,1dlu,p,3dlu, p,1dlu,p,2dlu");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(marginLeftLabel,cc.xy(2,1));
		builder.add(marginLeft,cc.xy(2,3));
		builder.add(marginRightLabel,cc.xy(4,1));
		builder.add(marginRight,cc.xy(4,3));
		builder.add(marginTopLabel,cc.xy(2,5));
		builder.add(marginTop,cc.xy(2,7));
		builder.add(marginBottomLabel,cc.xy(4,5));
		builder.add(marginBottom,cc.xy(4,7));
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.Margins")));
		return panel;
	}
	private JComponent createFlowMarginsPanel(){
		FormLayout layout = new FormLayout(
		        "1dlu, 35dlu, 3dlu, 35dlu, 1dlu",
				"p,1dlu,p,3dlu, p,1dlu,p,2dlu");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(marginLeftLabel,cc.xy(2,1));
		builder.add(marginLeft,cc.xy(2,3));
		builder.add(marginRightLabel,cc.xy(4,1));
		builder.add(marginRight,cc.xy(4,3));
		builder.add(marginTopLabel,cc.xy(2,5));
		builder.add(marginTop,cc.xy(2,7));
		builder.add(marginBottomLabel,cc.xy(4,5));
		builder.add(marginBottom,cc.xy(4,7));
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.Margins")));
		return panel;
	}

	private JComponent createFlowPartPanel(){
		FormLayout layout = new FormLayout(
		        "1dlu, p, 1dlu",
				"p,3dlu, p");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		if (printSpreadSheet!=null) builder.add(printSpreadSheet,cc.xy(2,1));
		if (printGantt!=null) builder.add(printGantt,cc.xy(2,3));
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.ShowParts")));
		return panel;
	}

	private JComponent createScalingPanel(){
		FormLayout layout = new FormLayout(
		        "8dlu, p, 3dlu,30dlu,3dlu,p,3dlu,p,p,p,8dlu",
		        "p, 3dlu,p,10dlu,p,3dlu,p,3dlu");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(scaleTo,cc.xy(2,1));
		builder.add(scaleToWidth,cc.xy(4, 1));
		builder.add(scaleToWidthLabel,cc.xy(6, 1));
		builder.add(constrainProportions,cc.xy(8, 1));
		JLabel l=new JLabel(Messages.getString("PageSetupDialog.Scaling.FitToProportions")+" "+Messages.getString("PageSetupDialog.Scaling.FitToProportions2"));
		initFont(l);
		builder.add(scaleToProportions,cc.xy(9,1));
		builder.add(scaleToProportions2,cc.xy(10,1));
		builder.add(scaleToHeight,cc.xy(4, 3));
		builder.add(scaleToHeightLabel,cc.xy(6, 3));

		builder.add(fitTo,cc.xy(2,5));
		builder.add(fitToWidth,cc.xy(4, 5));
		builder.add(fitToWidthLabel,cc.xy(6, 5));
		builder.add(fitToHeight,cc.xy(4, 7));
		builder.add(fitToHeightLabel,cc.xy(6, 7));
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.Scaling")));
		return panel;
	}
	private JComponent createFlowScalingPanel(){
		FormLayout layout = new FormLayout(
		        "1dlu, 5dlu,p,18dlu,3dlu,p,1dlu",
		        Environment.isOpenProj()?"p, 3dlu,p,3dlu,p,3dlu,p,p,10dlu,p,3dlu,p,3dlu,p,3dlu,p,p,3dlu":"p, 3dlu,p,3dlu,p,3dlu,p,p,10dlu,p,3dlu,p,3dlu,p,3dlu");

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		CellConstraints cc = new CellConstraints();
		builder.add(scaleTo,cc.xyw(2,1,5));
		builder.add(scaleToWidth,cc.xyw(3, 3,2));
		builder.add(scaleToWidthLabel,cc.xy(6, 3));
		builder.add(scaleToHeight,cc.xyw(3, 5,2));
		builder.add(scaleToHeightLabel,cc.xy(6, 5));
		builder.add(constrainProportions,cc.xy(3,7));
		builder.add(scaleToProportions,cc.xyw(4,7,3));
		builder.add(scaleToProportions2,cc.xyw(4,8,4));

		builder.add(fitTo,cc.xyw(2,10,5));
		builder.add(fitToWidth,cc.xyw(3, 12,2));
		builder.add(fitToWidthLabel,cc.xy(6, 12));
		builder.add(fitToHeight,cc.xyw(3, 14,2));
		builder.add(fitToHeightLabel,cc.xy(6, 14));
		if (Environment.isOpenProj()){
			JLabel l=new JLabel(Messages.getString("PageSetupDialog.PODOnly"));
			l.setEnabled(false);
			initFont(l);
			builder.add(l,cc.xyw(2, 16, 5));
			l=new JLabel(Messages.getString("PageSetupDialog.PODOnly2"));
			l.setEnabled(false);
			initFont(l);
			builder.add(l,cc.xyw(2, 17, 5));
		}
		JPanel panel=builder.getPanel();
		panel.setBorder(new TitledBorder(Messages.getString("PageSetupDialog.Scaling")));
		return panel;
	}


}
