/*
 * Copyright (c) 1997-2024 IDRsolutions (https://www.idrsolutions.com)
 */
package org.jpedal.examples.viewer.gui.popups;

import org.jpedal.PdfDecoder;
import org.jpedal.PdfDecoderInt;
import org.jpedal.display.Display;
import org.jpedal.examples.viewer.gui.SwingGUI;
import org.jpedal.examples.viewer.paper.MarginPaper;
import org.jpedal.examples.viewer.paper.PaperSizes;
import org.jpedal.exception.PdfException;
import org.jpedal.io.ColorSpaceConvertor;
import org.jpedal.objects.PrinterOptions;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.Messages;

import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.SetOfIntegerSyntax;
import javax.print.attribute.standard.PageRanges;
import javax.print.attribute.standard.PrinterResolution;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.awt.print.Paper;
import java.text.NumberFormat;
import java.util.ArrayList;

public class PrintPanel extends javax.swing.JPanel {

    private int pageCount;
    private int currentPage;
    private int currentPreviewedPage = 1;
    private boolean okClicked;

    private String[] printersList;

    private final PaperSizes paperDefinitions;

    private int defaultResolution;

    private static final double mmPerSubInch = 25.4 72;

    private final PdfDecoderInt pdf;

    /**
     * Creates a panel to display the various printing options available in the Viewer
     *
     @param printersList      String array listing the available printers names
     @param defaultPrinter    String value representing the default printer option
     @param paperDefinitions  Papersizes object containing details for all supported paper sizes
     @param defaultResolution int value representing the default resolution for printing
     @param pageNumber        int value representing the page currently displayed
     @param decoder           PdfDecoderInt object representing the PDF file that is currently open
     */
    public PrintPanel(final String[] printersList, final String defaultPrinter, final PaperSizes paperDefinitions, final int defaultResolution, final int pageNumber, final PdfDecoderInt decoder) {

        pdf = decoder;
        pageCount = pdf.getPageCount();
        currentPage = pageNumber;

        this.defaultResolution = defaultResolution;

        this.paperDefinitions = paperDefinitions;

        this.printersList = printersList;

        initComponents(defaultPrinter);

    }

    /**
     * Reset the default values of the print panel to those provided
     *
     @param printersList   String array listing the available printers names
     @param defaultPrinter String value representing the default printer option
     @param pageCount      int value representing total number of pages in the document
     @param currentPage    int value representing the page currently displayed
     */
    public void resetDefaults(final String[] printersList, final String defaultPrinter, final int pageCount, final int currentPage) {

        this.printersList = printersList;
        this.pageCount = pageCount;
        this.currentPage = currentPage;

        if (pageSize.getItemCount() == 0) {
            return;
        }

        resetRangeTab();
        printHandlingCopies.setValue(1);
        if (defaultPrinter != null && !defaultPrinter.isEmpty()) {
            printerName.setSelectedItem(defaultPrinter);
        }

        printerName.setModel(new javax.swing.DefaultComboBoxModel<>(printersList));

        tabbedPane.setSelectedIndex(0);
    }

    private void resetRangeTab() {
        pagesFrom.setText("1");
        pagesTo.setText(String.valueOf(pageCount));
        printRangeAll.setSelected(true);
        printRangeSubset.setSelectedIndex(0);
        printRangeReversePages.setSelected(false);
    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */

    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">
    @SuppressWarnings({"OverlyLongMethod""java:S138"})
    private void initComponents(final String startingPrinter) {

        buttonGroup1 = new javax.swing.ButtonGroup();
        printerPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        tabbedPane = new javax.swing.JTabbedPane();
        printerName = new javax.swing.JComboBox<>();
        pageSize = new javax.swing.JComboBox<>();
        jLabel10 = new JLabel();
        jLabel11 = new javax.swing.JLabel();
        jLabel12 = new javax.swing.JLabel();
        jLabel13 = new javax.swing.JLabel();
        jLabel14 = new javax.swing.JLabel();
        jLabel15 = new javax.swing.JLabel();
        left = new javax.swing.JSpinner();
        right = new javax.swing.JSpinner();
        top = new javax.swing.JSpinner();
        bottom = new javax.swing.JSpinner();
        resolution = new javax.swing.JComboBox<>();
        printRangePanel = new javax.swing.JPanel();
        pagesFrom = new javax.swing.JTextField();
        printRangeCurrentPage = new javax.swing.JRadioButton();
        printRangeAll = new javax.swing.JRadioButton();
        printRangeCurrentView = new javax.swing.JRadioButton();
        printRangeFrom = new javax.swing.JRadioButton();
        jLabel4 = new javax.swing.JLabel();
        printRangeSubset = new javax.swing.JComboBox<>();
        printRangeReversePages = new javax.swing.JCheckBox();
        jLabel7 = new javax.swing.JLabel();
        pagesTo = new javax.swing.JTextField();
        pageHandlingPanel = new javax.swing.JPanel();
        final JPanel previewPanel = new JPanel();
        previewComponent = new javax.swing.JComponent() {
            @Override
            public void paintComponent(final Graphics g) {
                printPreview((Graphics2Dg);
            }
        };
        previewSlider = new CustomSlider();
        jLabel8 = new javax.swing.JLabel();
        printHandlingCopies = new javax.swing.JSpinner();
        jLabel9 = new javax.swing.JLabel();
        printHandlingScaling = new javax.swing.JComboBox<>();
        autoRotateCenter = new javax.swing.JCheckBox();
        paperSourceByPDF = new javax.swing.JCheckBox();
        grayscale = new javax.swing.JCheckBox();
        okButton = new javax.swing.JButton();

        cancelButton = new javax.swing.JButton();

        nameElements();

        setLayout(null);

        add(tabbedPane);
        tabbedPane.setBounds(107400339);

        createPrinterPanel(startingPrinter);

        createPrintRangePanel();

        createPageHandlingPanel();

        //START Preview PANEL
        previewPanel.setLayout(null);

        previewPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null,
                Messages.getMessage("PdfViewerLabel.PrintPreview"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
                javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", Font.PLAIN, 11)));

        previewPanel.add(previewComponent);
        previewComponent.setBounds(55220275);

        previewPanel.add(previewSlider);
        previewSlider.setBounds(528022040);
        previewSlider.resetValue();
        updatePreview();

        add(previewPanel);
        previewPanel.setBounds(4207230330);
        //END Preview PANEL

        okButton.setText(Messages.getMessage("PdfMessage.Ok"));

        okButton.addActionListener(evt -> okEvent());

        add(okButton);
        okButton.setBounds(4453489023);

        cancelButton.setText(Messages.getMessage("PdfMessage.Cancel"));

        cancelButton.addActionListener(evt -> cancelEvent());

        add(cancelButton);
        cancelButton.setBounds(5603489023);


    // </editor-fold>

    private void createPageHandlingPanel() {
        //START Page Handling PANEL
        pageHandlingPanel.setLayout(new GridBagLayout());
        final GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5555);

        jLabel8.setText(Messages.getMessage("PdfViewerPrint.Copies"));
        pageHandlingPanel.add(jLabel8, setGridBagConstraints(gbc, 001));

        printHandlingCopies.setModel(new SpinnerNumberModel(111_000, 1));
        gbc.fill = GridBagConstraints.VERTICAL;
        gbc.insets = new Insets(0000);
        gbc.anchor = GridBagConstraints.WEST;
        printHandlingCopies.setMinimumSize(new Dimension(6522));
        printHandlingCopies.setPreferredSize(new Dimension(6522));
        pageHandlingPanel.add(printHandlingCopies, setGridBagConstraints(gbc, 101));
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.insets = new Insets(5555);

        jLabel9.setText(Messages.getMessage("PdfViewerPrint.PageScaling"));
        pageHandlingPanel.add(jLabel9, setGridBagConstraints(gbc, 011));

        printHandlingScaling.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{
                Messages.getMessage("PdfViewerPrint.NoScaling"),
                Messages.getMessage("PdfViewerPrint.FitToPrinterMargins"),
                Messages.getMessage("PdfViewerPrint.ReduceToPrinterMargins")}));
        printHandlingScaling.setSelectedIndex(PrinterOptions.LAST_SCALING_CHOICE);
        gbc.insets = new Insets(5050);
        pageHandlingPanel.add(printHandlingScaling, setGridBagConstraints(gbc, 111));
        gbc.insets = new Insets(5555);
        printHandlingScaling.addItemListener(e -> updatePreview());

        autoRotateCenter.setSelected(true);
        autoRotateCenter.setText((Messages.getMessage("PdfViewerPrint.AutoRotateAndCenter")));
        autoRotateCenter.setBorder(javax.swing.BorderFactory.createEmptyBorder(0000));
        autoRotateCenter.setMargin(new java.awt.Insets(0000));
        pageHandlingPanel.add(autoRotateCenter, setGridBagConstraints(gbc, 022));
        autoRotateCenter.addItemListener(e -> updatePreview());

        paperSourceByPDF.setText(Messages.getMessage("PdfViewerPrint.ChoosePaperByPdfSize"));
        paperSourceByPDF.setBorder(javax.swing.BorderFactory.createEmptyBorder(0000));
        paperSourceByPDF.setMargin(new java.awt.Insets(0000));
        pageHandlingPanel.add(paperSourceByPDF, setGridBagConstraints(gbc, 032));
        paperSourceByPDF.addItemListener(e -> updatePreview());


        grayscale.setText(Messages.getMessage("PdfViewerPrint.Grayscale"));
        grayscale.setBorder(javax.swing.BorderFactory.createEmptyBorder(0000));
        pageHandlingPanel.add(grayscale, setGridBagConstraints(gbc, 042));
        grayscale.setMargin(new java.awt.Insets(0000));
        grayscale.addItemListener(e -> updatePreview());

        tabbedPane.addTab(Messages.getMessage("PdfViewerPrintTab.handling"), pageHandlingPanel);
        //END Page Handling PANEL
    }

    private void createPrintRangePanel() {

        //START Print Range PANEL
        printRangePanel.setLayout(new GridBagLayout());

        setUpRangeSettings();

        addRangeOptionsToPanel();

        tabbedPane.addTab(Messages.getMessage("PdfViewerPrintTab.range"), printRangePanel);
        //END Print Range PANEL
    }

    private void setUpRangeSettings() {

        pagesFrom.setText("1");
        pagesFrom.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mousePressed(final java.awt.event.MouseEvent evt) {
                pagesBoxPressed();
            }
        });
        pagesFrom.setMinimumSize(new Dimension(6522));
        pagesFrom.setPreferredSize(new Dimension(6522));

        jLabel7.setText(Messages.getMessage("PdfViewerPrint.PagesTo"));
        pagesTo.setText(String.valueOf(pageCount));
        pagesTo.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mousePressed(final java.awt.event.MouseEvent evt) {
                pagesBoxPressed();
            }
        });
        pagesTo.setMinimumSize(new Dimension(6522));
        pagesTo.setPreferredSize(new Dimension(6522));

        printRangeReversePages.setText(Messages.getMessage("PdfViewerPrint.ReversePages"));
        printRangeReversePages.setBorder(javax.swing.BorderFactory.createEmptyBorder(0000));
        printRangeReversePages.setMargin(new java.awt.Insets(0000));
        printRangeReversePages.addItemListener(e -> updatePreview());

        jLabel4.setText(Messages.getMessage("PdfViewerPrint.Subset"));
        printRangeSubset.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{
                Messages.getMessage("PdfViewerPrint.AllPagesInRange"), Messages.getMessage("PdfViewerPrint.OddPagesOnly"),
                Messages.getMessage("PdfViewerPrint.EvenPagesOnly")}));
        printRangeSubset.addItemListener(e -> updatePreview());

        printRangeCurrentPage.setText(Messages.getMessage("PdfViewerRadioButton.CurrentPage"));
        printRangeCurrentPage.setBorder(javax.swing.BorderFactory.createEmptyBorder(0000));
        printRangeCurrentPage.setMargin(new java.awt.Insets(0000));
        printRangeCurrentPage.setOpaque(false);
        printRangeCurrentPage.addItemListener(evt -> currentPageStateChanged());

        printRangeAll.setSelected(true);
        printRangeAll.setText(Messages.getMessage("PdfViewerRadioButton.All"));
        printRangeAll.setBorder(javax.swing.BorderFactory.createEmptyBorder(0000));
        printRangeAll.setMargin(new java.awt.Insets(0000));
        printRangeAll.setOpaque(false);
        printRangeAll.addItemListener(evt -> allStateChanged());

        printRangeCurrentView.setText(Messages.getMessage("PdfViewerPrint.CurrentView"));
        printRangeCurrentView.setBorder(javax.swing.BorderFactory.createEmptyBorder(0000));
        printRangeCurrentView.setEnabled(true);
        printRangeCurrentView.setMargin(new java.awt.Insets(0000));
        printRangeCurrentView.setOpaque(false);
        //Disable in non single mode
        if (pdf.getDisplayView() != Display.SINGLE_PAGE) {
            printRangeCurrentView.setEnabled(false);
            printRangeCurrentView.setToolTipText(Messages.getMessage("PageLayoutMessage.SinglePageOnly"));
        else {
            printRangeCurrentView.setEnabled(true);
            printRangeCurrentView.setToolTipText(null);
        }
        printRangeCurrentView.addItemListener(evt -> printRangeCurrentView());

        printRangeFrom.setText(Messages.getMessage("PdfViewerPrint.PagesFrom"));
        printRangeFrom.setBorder(javax.swing.BorderFactory.createEmptyBorder(0000));
        printRangeFrom.setMargin(new java.awt.Insets(0000));
        printRangeFrom.setOpaque(false);
        printRangeFrom.addItemListener(evt -> pagesFromStateChanged());

        buttonGroup1.add(printRangeCurrentPage);
        buttonGroup1.add(printRangeAll);
        buttonGroup1.add(printRangeCurrentView);
        buttonGroup1.add(printRangeFrom);
    }

    private void addRangeOptionsToPanel() {

        final GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5555);

        printRangePanel.add(printRangeAll, setGridBagConstraints(gbc, 001));
        printRangePanel.add(printRangeCurrentView, setGridBagConstraints(gbc, 011));
        printRangePanel.add(printRangeCurrentPage, setGridBagConstraints(gbc, 021));
        printRangePanel.add(printRangeFrom, setGridBagConstraints(gbc, 031));
        printRangePanel.add(jLabel4, setGridBagConstraints(gbc, 041));
        printRangePanel.add(printRangeReversePages, setGridBagConstraints(gbc, 053));

        gbc.insets = new Insets(0000);
        printRangePanel.add(pagesFrom, setGridBagConstraints(gbc, 131));

        gbc.insets = new Insets(5050);
        printRangePanel.add(printRangeSubset, setGridBagConstraints(gbc, 144));
        gbc.insets = new Insets(5555);

        printRangePanel.add(jLabel7, setGridBagConstraints(gbc, 231));

        gbc.insets = new Insets(0000);
        printRangePanel.add(pagesTo, setGridBagConstraints(gbc, 331));

    }

    private void createPrinterPanel(final String startingPrinter) {

        //START Printer PANEL
        printerPanel.setLayout(new GridBagLayout());
        final GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5555);

        jLabel1.setText(Messages.getMessage("PdfViewerPrint.Name"));
        printerPanel.add(jLabel1, setGridBagConstraints(gbc, 001));

        jLabel2.setText(Messages.getMessage("PdfViewerPrint.PageSize"));
        printerPanel.add(jLabel2, setGridBagConstraints(gbc, 011));

        printerName.setModel(new javax.swing.DefaultComboBoxModel<>(printersList));
        printerPanel.add(printerName, setGridBagConstraints(gbc, 105));

        addPrinterChangeListener();

        pageSize.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{"Loading..."}));
        pageSize.setEnabled(false);
        resolution.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{"Loading..."}));
        resolution.setEnabled(false);
        okButton.setEnabled(false);

        loadPrinterDefaults(startingPrinter);

        pageSize.addItemListener(e -> {
            updatePreview();
            updateMargins();
        });
        pageSize.setMinimumSize(new Dimension(4022));
        pageSize.setPreferredSize(new Dimension(4022));
        printerPanel.add(pageSize, setGridBagConstraints(gbc, 115));

        jLabel10.setText(Messages.getMessage("PdfViewerPrintMargins.margin"));
        printerPanel.add(jLabel10, setGridBagConstraints(gbc, 021));

        jLabel11.setText(Messages.getMessage("PdfViewerPrintMargins.left"));
        printerPanel.add(jLabel11, setGridBagConstraints(gbc, 121));

        left.setModel(new CustomSpinnerModel());
        left.setMinimumSize(new Dimension(6522));
        left.setPreferredSize(new Dimension(6522));
        printerPanel.add(left, setGridBagConstraints(gbc, 221));

        jLabel12.setText(Messages.getMessage("PdfViewerPrintMargins.right"));
        printerPanel.add(jLabel12, setGridBagConstraints(gbc, 321));

        right.setModel(new CustomSpinnerModel());
        right.setMinimumSize(new Dimension(6522));
        right.setPreferredSize(new Dimension(6522));
        printerPanel.add(right, setGridBagConstraints(gbc, 421));

        jLabel13.setText(Messages.getMessage("PdfViewerPrintMargins.top"));
        printerPanel.add(jLabel13, setGridBagConstraints(gbc, 131));

        top.setModel(new CustomSpinnerModel());
        top.setMinimumSize(new Dimension(6522));
        top.setPreferredSize(new Dimension(6522));
        printerPanel.add(top, setGridBagConstraints(gbc, 231));

        jLabel14.setText(Messages.getMessage("PdfViewerPrintMargins.bottom"));
        printerPanel.add(jLabel14, setGridBagConstraints(gbc, 331));

        bottom.setModel(new CustomSpinnerModel());
        bottom.setMinimumSize(new Dimension(6522));
        bottom.setPreferredSize(new Dimension(6522));
        printerPanel.add(bottom, setGridBagConstraints(gbc, 431));

        addMarginChangeListener();

        jLabel15.setText(Messages.getMessage("PdfViewerPrintResolution.text"));
        printerPanel.add(jLabel15, setGridBagConstraints(gbc, 041));

        printerPanel.add(resolution, setGridBagConstraints(gbc, 145));

        tabbedPane.addTab(Messages.getMessage("PdfViewerPrintTab.printer"), printerPanel);
        //END Printer PANEL
    }

    private static GridBagConstraints setGridBagConstraints(final GridBagConstraints gbc, final int x, final int y, final int width) {

        gbc.gridx = x;
        gbc.gridy = y;
        gbc.gridwidth = width;

        return gbc;
    }

    private void addPrinterChangeListener() {
        printerName.addItemListener(e -> {

            previewComponent.repaint();

            okButton.setEnabled(false);
            pageSize.setEnabled(false);

            pageSize.setModel(new DefaultComboBoxModel<>(new String[]{"Loading..."}));
            resolution.setEnabled(false);
            resolution.setModel(new DefaultComboBoxModel<>(new String[]{"Loading..."}));

            SwingUtilities.invokeLater(() -> {

                final PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);

                PrintService p = null;
                for (final PrintService p1 : ps) {

                    if (p1.getName().equals(printerName.getSelectedItem())) {
                        p = p1;
                    }
                }

                if (p != null) {

                    resolution.setModel(new DefaultComboBoxModel<>(getAvailableResolutions(p)));

                    final int resInd = getDefaultResolutionIndex();
                    if (resolution.getModel().getSize() > resInd) {
                        resolution.setSelectedIndex(resInd);
                    }
                    resolution.setEnabled(true);
                    paperDefinitions.setPrintService(p);

                    pageSize.setModel(new DefaultComboBoxModel<>(getAvailablePaperSizes()));

                    final int pageInd = paperDefinitions.getDefaultPageIndex();
                    if (pageSize.getModel().getSize() > pageInd) {
                        pageSize.setSelectedIndex(pageInd);
                    }
                    pageSize.setEnabled(true);
                    okButton.setEnabled(true);

                }

                updateMargins();
            });
        });
    }

    private void addMarginChangeListener() {
        final ChangeListener marginListener = new ChangeListener() {
            static final double mmToSubInch = 72 25.4;

            @Override
            public void stateChanged(final ChangeEvent e) {
                final MarginPaper paper = getSelectedPaper();
                if (paper == null) {
                    return;
                }

                final double l = (Doubleleft.getValue() * mmToSubInch;
                final double r = (Doubleright.getValue() * mmToSubInch;
                final double t = (Doubletop.getValue() * mmToSubInch;
                final double b = (Doublebottom.getValue() * mmToSubInch;
                paper.setImageableArea(l, t, (paper.getWidth() - l- r, (paper.getHeight() - t- b);
                updatePreview();
            }
        };

        left.addChangeListener(marginListener);
        right.addChangeListener(marginListener);
        top.addChangeListener(marginListener);
        bottom.addChangeListener(marginListener);
    }

    private String getDefaultPrinterName(final String startingPrinter) {

        final String printerFlag = System.getProperty("org.jpedal.defaultPrinter");
        String printerToUse = null;
        if (printerFlag != null) {
            for (final String aPrintersList : printersList) {
                if (printerFlag.equals(aPrintersList)) {
                    printerToUse = aPrintersList;
                    break;
                }
            }
        else {
            printerToUse = startingPrinter;
        }

        //Finally check system default incase nothing has been set
        if (printerToUse == null || printerToUse.isEmpty()) {
            final PrintService printer = PrintServiceLookup.lookupDefaultPrintService();
            if (printer != null) {
                printerToUse = printer.getName();
            }
        }
        return printerToUse;
    }

    private void loadPrinterDefaults(final String startingPrinter) {
        final Thread t = new Thread(() -> {

            final String printerToUse = getDefaultPrinterName(startingPrinter);

            final PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);
            PrintService p = null;
            for (final PrintService p1 : ps) {
                if (p1.getName().equals(printerToUse)) {
                    p = p1;
                }
            }

            if (p != null) {
                paperDefinitions.setPrintService(p);
                resolution.setModel(new DefaultComboBoxModel<>(getAvailableResolutions(p)));
                final int defaultResolution = getDefaultResolutionIndex();
                if (resolution.getModel().getSize() > defaultResolution) {
                    resolution.setSelectedIndex(defaultResolution);
                }
                resolution.setEnabled(true);
                pageSize.setModel(new DefaultComboBoxModel<>(getAvailablePaperSizes()));
                final int defaultPageSize = paperDefinitions.getDefaultPageIndex();
                if (defaultPageSize < pageSize.getModel().getSize()) {
                    pageSize.setSelectedIndex(defaultPageSize);
                }
                pageSize.setEnabled(true);
                okButton.setEnabled(true);

            }

            updateMargins();
        });
        t.setDaemon(true);
        t.start();
    }

    private static String[] getAvailableResolutions(final PrintService p) {
        final PrinterResolution[] resolutions = (PrinterResolution[]) p.getSupportedAttributeValues(PrinterResolution.class, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);

        if (resolutions == null) {
            return new String[]{"Default"};
        }

        final String[] names = new String[resolutions.length];
        for (int i = 0; i < resolutions.length; i++) {
            final PrinterResolution res = resolutions[i];
            names[i= res.getCrossFeedResolution(PrinterResolution.DPI"x" + res.getFeedResolution(PrinterResolution.DPI" dpi";
        }

        return names;
    }

    /**
     * Gets the resolution value currently selected based on printer and selected resolution index
     *
     @return PrinterResolution object representing the selected resolutions or null if no supported resolution is found.
     */
    public PrinterResolution getResolution() {
        final PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);
        PrintService p = null;
        for (final PrintService p1 : ps) {
            if (p1.getName().equals(printerName.getSelectedItem())) {
                p = p1;
            }
        }

        if (p == null) {
            return null;
        }

        final PrinterResolution[] resolutions = ((PrinterResolution[]) p.getSupportedAttributeValues(PrinterResolution.class, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null));

        if (resolutions == null) {
            return null;
        }

        return resolutions[resolution.getSelectedIndex()];
    }

    private int getDefaultResolutionIndex() {
        //get print service
        final PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);
        PrintService p = null;
        for (final PrintService p1 : ps) {
            if (p1.getName().equals(printerName.getSelectedItem())) {
                p = p1;
            }
        }

        if (p == null) {
            return 0;
        }

        //get available resolutions
        final PrinterResolution[] resolutions = (PrinterResolution[]) p.getSupportedAttributeValues(PrinterResolution.class, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);

        if (resolutions == null) {
            return 0;
        }

        if (defaultResolution == -1) {
            defaultResolution = 600;
        }

        //find nearest resolution
        int minDiff = Integer.MAX_VALUE;
        int indexToUse = 0;
        for (int i = 0; i < resolutions.length; i++) {
            final PrinterResolution res = resolutions[i];
            int cfDiff = res.getCrossFeedResolution(PrinterResolution.DPI- defaultResolution;
            if (cfDiff < 0) {
                cfDiff = -cfDiff;
            }
            int fDiff = res.getFeedResolution(PrinterResolution.DPI- defaultResolution;
            if (fDiff < 0) {
                fDiff = -fDiff;
            }

            if (cfDiff + fDiff < minDiff) {
                minDiff = cfDiff + fDiff;
                indexToUse = i;
            }
        }

        return indexToUse;
    }

    private void updateMargins() {

        final MarginPaper p = getSelectedPaper();

        if (p == null) {
            return;
        }

        //Update minimum values
        ((CustomSpinnerModelleft.getModel()).setMinValue(p.getMinX() * mmPerSubInch);
        ((CustomSpinnerModeltop.getModel()).setMinValue(p.getMinY() * mmPerSubInch);
        ((CustomSpinnerModelright.getModel()).setMinValue((p.getWidth() - p.getMaxRX()) * mmPerSubInch);
        ((CustomSpinnerModelbottom.getModel()).setMinValue((p.getHeight() - p.getMaxBY()) * mmPerSubInch);


        //Set values to min
        final Double a = (double0;
        left.setValue(a);
        top.setValue(a);
        right.setValue(a);
        bottom.setValue(a);

    }

    private void printPreview(final Graphics2D g2) {
        final int w = previewComponent.getWidth();
        final int h = previewComponent.getHeight();
        int pageWidth, pageHeight;

        //In print current view use the visible area of the screen instead of the page heights
        if (printRangeCurrentView.isSelected()) {
            pageWidth = (int) (pdf.getVisibleRect().getWidth() (pdf.getScaling()));
            pageHeight = (int) (pdf.getVisibleRect().getHeight() (pdf.getScaling()));
        else {
            pageWidth = pdf.getPdfPageData().getCropBoxWidth(currentPreviewedPage);
            pageHeight = pdf.getPdfPageData().getCropBoxHeight(currentPreviewedPage);
        }

        //set paper size and printable area
        final Paper p = getPaperForPreview(pageWidth, pageHeight);
        if (p == null) {
            g2.setColor(getForeground());
            g2.drawString(Messages.getMessage("PdfPrintPreview.Loading")(w / 225(h / 25);
            return;
        }

        //Set offsets
        int lO = 25;
        int tO = 30;
        final int rO = 5;
        final int bO = 25;

        final double paperHeightInInches = p.getHeight() 72d;
        final double paperWidthInInches = p.getWidth() 72d;

        //Calculate scaling
        final double wScale = (w - (lO + rO)) / p.getWidth();
        final double hScale = (h - (tO + bO)) / p.getHeight();
        final double scale = Math.min(wScale, hScale);

        //Scale all values
        p.setSize(scale * p.getWidth(), scale * p.getHeight());
        p.setImageableArea(scale * p.getImageableX(), scale * p.getImageableY(), scale * p.getImageableWidth(), scale * p.getImageableHeight());

        pageWidth = (int) (scale * pageWidth);
        pageHeight = (int) (scale * pageHeight);

        double pageScale = 1;
        if (printHandlingScaling.getSelectedIndex() == 1    //Fit
                || (printHandlingScaling.getSelectedIndex() == && (pageWidth > p.getImageableWidth() || pageHeight > p.getImageableHeight()))) { //Reduce
            pageScale = p.getImageableWidth() / pageWidth;
            if ((p.getImageableHeight() / pageHeight< pageScale) {
                pageScale = p.getImageableHeight() / pageHeight;
            }

            pageWidth = (int) (pageScale * pageWidth);
            pageHeight = (int) (pageScale * pageHeight);
        }

        //Include any centering
        lO += (w - (lO + rO + p.getWidth())) 2;
        tO += (h - (tO + bO + p.getHeight())) 2;

        drawPreviewArea(g2, lO, tO, (intp.getWidth()(intp.getHeight()(intp.getImageableX()(intp.getImageableY()(intp.getImageableWidth()(intp.getImageableHeight());
        drawPreviewWidthBar(g2, lO, tO, (intp.getWidth(), paperWidthInInches, getForeground());
        drawPreviewHeightBar(g2, lO, tO, (intp.getHeight(), paperHeightInInches, getForeground());


        //draw page
        drawPreviewPage(g2, lO, tO, pageWidth, pageHeight, (intp.getImageableX() 1(intp.getImageableY() 1(intp.getImageableWidth() 1(intp.getImageableHeight() 1);

        //Draw border
        drawPreviewBorder(g2, lO, tO, (intp.getWidth()(intp.getHeight(), pageScale, h);
    }

    private Paper getPaperForPreview(final int pageWidth, final int pageHeight) {

        final Paper p = new Paper();
        if (paperSourceByPDF.isSelected()) {
            p.setSize(pageWidth, pageHeight);
            p.setImageableArea(00, pageWidth, pageHeight);
        else {
            final MarginPaper mp = paperDefinitions.getSelectedPaper((StringpageSize.getSelectedItem());
            if (mp != null) {
                p.setSize(mp.getWidth(), mp.getHeight());
                p.setImageableArea(mp.getImageableX(), mp.getImageableY(), mp.getImageableWidth(), mp.getImageableHeight());
            else {
                return null;
            }
        }

        //check auto rotate
        if (autoRotateCenter.isSelected()
                && ((pageWidth > pageHeight && p.getImageableWidth() < p.getImageableHeight())
                || (pageWidth < pageHeight && p.getImageableWidth() > p.getImageableHeight()))) {

            p.setSize(p.getHeight(), p.getWidth());
            p.setImageableArea(p.getImageableY(), p.getImageableX(), p.getImageableHeight(), p.getImageableWidth());
        }

        return p;
    }

    private static void drawPreviewBorder(final Graphics2D g2, final int lO, final int tO,
                                          final int pW, final int pH, final double pageScale, final int h) {
        g2.setClip(null);
        g2.drawRect(lO, tO, pW, pH);

        final NumberFormat f = NumberFormat.getNumberInstance();
        f.setMaximumFractionDigits(0);
        g2.drawString(Messages.getMessage("PdfPrintPreview.UnitScale"+ f.format(pageScale * 100'%'5, h - 5);

    }

    private void drawPreviewPage(final Graphics2D g2, final int lO, final int tO,
                                 final int pageWidth, final int pageHeight,
                                 final int iX, final int iY, final int iW, final int iH) {
        try {
            BufferedImage img;

            //print current view uses current display on PdfDecoder
            if (printRangeCurrentView.isSelected()) {
                img = new BufferedImage((intpdf.getVisibleRect().getWidth()(intpdf.getVisibleRect().getHeight(), BufferedImage.TYPE_INT_ARGB);
                final Graphics g = img.getGraphics();
                g.translate((int-pdf.getVisibleRect().getX()(int-pdf.getVisibleRect().getY());

                //store border and background and restore after paint
                final Border bStore = ((JComponentpdf).getBorder();
                final Color cStore = ((Componentpdf).getBackground();
                ((JComponentpdf).setBorder(BorderFactory.createEmptyBorder());
                ((Componentpdf).setBackground(Color.WHITE);
                ((PdfDecoderpdf).paintComponent(g);
                ((JComponentpdf).setBorder(bStore);
                ((Componentpdf).setBackground(cStore);
            else {
                img = pdf.getPageAsImage(currentPreviewedPage);
            }

            if (grayscale.isSelected()) {
                img = ColorSpaceConvertor.convertColorspace(img, BufferedImage.TYPE_BYTE_GRAY);
            }

            g2.setClip(lO + iX, tO + iY, iW, iH);

            final int centeringX = (int) ((iW - pageWidth2d);
            final int centeringY = (int) ((iH - pageHeight2d);

            g2.drawImage(img, lO + iX + centeringX, tO + iY + centeringY, pageWidth, pageHeight, null);
        catch (final PdfException e) {
            LogWriter.writeLog("Caught a PDFException " + e);
        }
    }

    private static void drawPreviewArea(final Graphics2D g2, final int lO, final int tO,
                                  final int pW, final int pH,
                                  final int iX, final int iY, final int iW, final int iH) {
        //Fill page background
        g2.setPaint(Color.WHITE);
        g2.fillRect(lO, tO, pW, pH);

        //Draw printable area
        g2.setPaint(Color.RED);
        g2.drawLine(lO + iX, tO, lO + iX, tO + pH);
        g2.drawLine(lO, tO + iY, lO + pW, tO + iY);
        g2.drawLine(lO + iW + iX, tO, lO + iW + iX, tO + pH);
        g2.drawLine(lO, tO + iH + iY, lO + pW, tO + iH + iY);
    }

    private static void drawPreviewWidthBar(final Graphics2D g2, final int lO, final int tO,
                                  final int pW,  final double paperWidthInInches, final Color col) {

        g2.setPaint(col);

        //Draw width bar
        final NumberFormat f = NumberFormat.getNumberInstance();
        f.setMaximumFractionDigits(1);
        final String widthString = f.format(paperWidthInInches);
        final int tLen = widthString.length() 3;

        g2.drawString(widthString, lO + (pW / 2- tLen, tO - 5);
        g2.drawLine(lO, tO - 15, lO, tO - 5);
        g2.drawLine(lO + pW, tO - 15, lO + pW, tO - 5);
        g2.drawLine(lO, tO - 10(lO + (pW / 2- tLen6, tO - 10);
        g2.drawLine((lO + (pW / 2+ tLen6, tO - 10, lO + pW, tO - 10);
        g2.drawLine(lO, tO - 10, lO + 5, tO - 15);
        g2.drawLine(lO, tO - 10, lO + 5, tO - 5);
        g2.drawLine(lO + pW, tO - 10, lO + pW - 5, tO - 15);
        g2.drawLine(lO + pW, tO - 10, lO + pW - 5, tO - 5);
    }

    private static void drawPreviewHeightBar(final Graphics2D g2, final int lO, final int tO,
                                  final int pH, final double paperHeightInInches, final Color col) {

        g2.setPaint(col);

        //Draw width bar
        final NumberFormat f = NumberFormat.getNumberInstance();
        f.setMaximumFractionDigits(1);

        //Draw height bar
        final String heightString = f.format(paperHeightInInches);
        final int tLen = heightString.length() 3;

        g2.drawString(heightString, (lO - 12- tLen, tO + (pH / 25);
        g2.drawLine(lO - 15, tO, lO - 5, tO);
        g2.drawLine(lO - 15, tO + pH, lO - 5, tO + pH);
        g2.drawLine(lO - 10, tO, lO - 10(tO + (pH / 2)) 8);
        g2.drawLine(lO - 10((tO + (pH / 2)) 8), lO - 10, tO + pH);
        g2.drawLine(lO - 10, tO, lO - 5, tO + 5);
        g2.drawLine(lO - 10, tO, lO - 15, tO + 5);
        g2.drawLine(lO - 10, tO + pH, lO - 15, tO + pH - 5);
        g2.drawLine(lO - 10, tO + pH, lO - 5, tO + pH - 5);

    }

    private void nameElements() {
        okButton.setName("ok");
        cancelButton.setName("cancel");
        pageSize.setName("size");
        printerName.setName("printer");
        autoRotateCenter.setName("autoRot");
        paperSourceByPDF.setName("paperSource");
        printHandlingScaling.setName("scaling");
        tabbedPane.setName("tabPane");
        setName("printDialog");
    }

    private void updatePreview() {
        int selection = previewSlider.getValue();

        //check for illogical settings
        final SetOfIntegerSyntax set = getPrintRange();
        final int pagePrintCount;

        if (set == null) {

            //Illogical - preview nothing
            currentPreviewedPage = 0;

            pagePrintCount = 0;
        else {

            final int[][] ranges = set.getMembers();

            //calculate length
            int count = 0;
            for (final int[] range1 : ranges) {
                count += range1[1(range1[01);
            }
            final int[] pagesToPrint = new int[count];
            pagePrintCount = pagesToPrint.length;

            //populate array with page numbers
            count = 0;
            for (final int[] range : ranges) {
                final int rangeLength = range[1(range[01);
                for (int j = 0; j < rangeLength; j++) {
                    pagesToPrint[count= range[0+ j;
                    count++;
                }
            }

            //check selection value
            if (selection > pagePrintCount) {
                selection = 1;
                previewSlider.resetValue();
            }

            //Work out which page to preview
            if (printRangeReversePages.isSelected()) {
                currentPreviewedPage = pagesToPrint[pagesToPrint.length - selection];
            else {
                currentPreviewedPage = pagesToPrint[selection - 1];
            }
        }

        //recalculate previewSlider
        previewSlider.setMaxValue(pagePrintCount);

        //redraw
        previewComponent.repaint();
    }


    private void pagesBoxPressed() {
        printRangeFrom.setSelected(true);
        printRangeSubset.setEnabled(true);
        printRangeReversePages.setEnabled(true);
        updatePreview();
    }

    private void pagesFromStateChanged() {
        if (printRangeFrom.isSelected()) {
            printRangeSubset.setEnabled(true);
            printRangeReversePages.setEnabled(true);
            updatePreview();
        }
    }

    private void printRangeCurrentView() {
        if (printRangeCurrentView.isSelected()) {
            printRangeSubset.setEnabled(false);
            printRangeReversePages.setEnabled(false);
            updatePreview();
        }
    }

    private void currentPageStateChanged() {
        if (printRangeCurrentPage.isSelected()) {
            printRangeSubset.setEnabled(false);
            printRangeReversePages.setEnabled(false);
            updatePreview();
        }
    }

    private void allStateChanged() {
        if (printRangeAll.isSelected()) {
            printRangeSubset.setEnabled(true);
            printRangeReversePages.setEnabled(true);
            updatePreview();
        }
    }

    private void cancelEvent() {
        okClicked = false;
        getTopLevelAncestor().setVisible(false);
    }

    private void okEvent() {
        okClicked = true;
        getTopLevelAncestor().setVisible(false);
    }

    // Variables declaration - do not modify
    private javax.swing.JCheckBox autoRotateCenter;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton cancelButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel15;
    private javax.swing.JSpinner left;
    private javax.swing.JSpinner right;
    private javax.swing.JSpinner top;
    private javax.swing.JSpinner bottom;
    private JComboBox<String> resolution;
    private javax.swing.JButton okButton;
    private javax.swing.JPanel pageHandlingPanel;
    private javax.swing.JComponent previewComponent;
    private CustomSlider previewSlider;
    private JComboBox<String> pageSize;
    private javax.swing.JTextField pagesFrom;
    private javax.swing.JTextField pagesTo;
    private javax.swing.JCheckBox paperSourceByPDF;
    private javax.swing.JCheckBox grayscale;
    private javax.swing.JSpinner printHandlingCopies;
    private JComboBox<String> printHandlingScaling;
    private javax.swing.JRadioButton printRangeAll;
    private javax.swing.JRadioButton printRangeCurrentPage;
    private javax.swing.JRadioButton printRangeCurrentView;
    private javax.swing.JRadioButton printRangeFrom;
    private javax.swing.JPanel printRangePanel;
    private javax.swing.JCheckBox printRangeReversePages;
    private JComboBox<String> printRangeSubset;
    private JComboBox<String> printerName;
    private javax.swing.JPanel printerPanel;
    private javax.swing.JTabbedPane tabbedPane;
    // End of variables declaration

    /**
     * Get the range of pages to be printed.
     * If the range is specified so no pages possible, such as printing all
     * even pages between 1 and 1, this method will return null.
     *
     @return SetOfIntegerSyntax object containing the page numbers of pages to be printed or null if no pages are applicable
     */
    @SuppressWarnings({"OverlyLongMethod""java:S138"})
    public SetOfIntegerSyntax getPrintRange() {

        SetOfIntegerSyntax pageRange = null;

        if (printRangeAll.isSelected()) {

            pageRange = new PageRanges(1, pageCount);

            if (printRangeSubset.getSelectedIndex() == 0) {
                return pageRange;
            }

            if (printRangeSubset.getSelectedIndex() == 1) {
                pageRange = getPageRange1(pageRange, 1);
            else if (printRangeSubset.getSelectedIndex() == 2) {
                pageRange = getPageRange1(pageRange, 0);
            }

        else if (printRangeCurrentPage.isSelected()) {

            pageRange = new PageRanges(currentPage);

        else if (printRangeCurrentView.isSelected()) {

            pageRange = new PageRanges(currentPage);

        else if (printRangeFrom.isSelected()) {

            int start, end;
            try {
                start = Integer.parseInt(pagesFrom.getText());
            catch (final NumberFormatException e) {
                LogWriter.writeLog("Exception in setting page range " + e);

                pagesFrom.setText("1");
                start = 1;
            }
            try {
                end = Integer.parseInt(pagesTo.getText());
            catch (final NumberFormatException e) {

                LogWriter.writeLog("Exception in setting page range " + e);

                pagesTo.setText(String.valueOf(pageCount));
                end = pageCount;
            }

            //Check values in range
            start = limitValueToFullPageRange(start, pageCount);
            end = limitValueToFullPageRange(end, pageCount);
            pagesFrom.setText(String.valueOf(start));
            pagesTo.setText(String.valueOf(end));

            if (start > end) {
                final int tmp = end;
                end = start;
                start = tmp;

                if (SwingGUI.showMessages) {
                    JOptionPane.showMessageDialog(this, Messages.getMessage("PdfViewerPrint.SwapValues"));
                }
            }
            pageRange = new PageRanges(start, end);

            if (printRangeSubset.getSelectedIndex() == 0) {
                return pageRange;
            }

            if (printRangeSubset.getSelectedIndex() == 1) {
                final StringBuilder membersStr = new StringBuilder();
                int i = -1;
                while ((i = pageRange.next(i)) != -1) {
                    if (i % == 1) {
                        membersStr.append(i).append(',');
                    }
                }

                String members = membersStr.toString();
                final StringBuilder sb = new StringBuilder(members);
                if (members.isEmpty()) {
                    return null;
                }

                sb.deleteCharAt(members.length() 1);
                members = sb.toString();

                pageRange = new PageRanges(members);
            else if (printRangeSubset.getSelectedIndex() == 2) {
                final StringBuilder membersStr = new StringBuilder();
                int i = -1;
                while ((i = pageRange.next(i)) != -1) {
                    if (i % == 0) {
                        membersStr.append(i).append(',');
                    }
                }

                String members = membersStr.toString();
                final StringBuilder sb = new StringBuilder(members);
                final int length = members.length();
                if (length > 0) {
                    sb.deleteCharAt(length - 1);
                }
                members = sb.toString();

                if (!members.isEmpty()) {
                    pageRange = new PageRanges(members);
                else {
                    pageRange = null;
                }
            }
        }

        return pageRange;
    }

    private static SetOfIntegerSyntax getPageRange1(SetOfIntegerSyntax pageRange, final int i2) {
        final StringBuilder membersStr = new StringBuilder();
        int i = -1;
        while ((i = pageRange.next(i)) != -1) {
            if (i % == i2) {
                membersStr.append(i).append(',');
            }
        }

        String members = membersStr.toString();
        final StringBuilder sb = new StringBuilder(members);
        sb.deleteCharAt(members.length() 1);
        members = sb.toString();

        pageRange = new PageRanges(members);
        return pageRange;
    }

    private static int limitValueToFullPageRange(final int value, final int pageCount) {
        final int returnValue;
        if (value < 1) {
            returnValue = 1;
        else {
            returnValue = Math.min(value, pageCount);
        }

        return returnValue;
    }

    /**
     * Get the number of copies to be printed as set in the print panel.
     *
     @return int value representing the number of copies to be printed.
     */
    public int getCopies() {
        final String copies = printHandlingCopies.getValue().toString();
        return Integer.parseInt(copies);
    }

    /**
     * Get the page scaling selected in the print panel
     * The possible values and their variables include,
     <p>
     * PrinterOptions.PAGE_SCALING_NONE = 0
     * PrinterOptions.PAGE_SCALING_FIT_TO_PRINTER_MARGINS = 1
     * PrinterOptions.PAGE_SCALING_REDUCE_TO_PRINTER_MARGINS = 2
     * see org.jpedal.objects.PrinterOptions for all values
     *
     @return int value representing the page scaling to be used (see org.jpedal.objects.PrinterOptions for all values)
     */
    public int getPageScaling() {

        final int option = printHandlingScaling.getSelectedIndex();

        int value = 0;
        //make choice
        switch (option) {
            case 0//No scaling
                break;

            case 1//Fit to scaling
                value = PrinterOptions.PAGE_SCALING_FIT_TO_PRINTER_MARGINS;
                break;

            case 2//Reduce to scaling
                value = PrinterOptions.PAGE_SCALING_REDUCE_TO_PRINTER_MARGINS;
                break;

        }

        //remember last option for next print dialog
        PrinterOptions.LAST_SCALING_CHOICE = value;

        return value;
    }

    /**
     * Get the name of the printer selected in the print panel
     *
     @return String value representing the name of a printer or null if no printer selected
     */
    public String getPrinter() {

        if (printerName == null) {
            return "";
        else {

            if (printerName.getSelectedItem() == null) {
                return null;
            else {
                return printerName.getSelectedItem().toString();
            }
        }
    }

    public boolean okClicked() {
        return okClicked;
    }

    public boolean isAutoRotateAndCenter() {
        return autoRotateCenter.isSelected();
    }

    public boolean isPaperSourceByPDFSize() {
        return paperSourceByPDF.isSelected();
    }

    public boolean isPrintingCurrentView() {
        return printRangeCurrentView.isSelected();
    }

    private String[] getAvailablePaperSizes() {
        return paperDefinitions.getAvailablePaperSizes();
    }

    /**
     * return selected Paper
     *
     @return the selected paper
     */
    public MarginPaper getSelectedPaper() {
        return paperDefinitions.getSelectedPaper((StringpageSize.getSelectedItem());
    }

    /**
     * return printers default orientation
     *
     @return an int value to show if page is landscape or portrait [reverse landscape = 2, portrait = 1, landscape = 0]
     */
    public int getSelectedPrinterOrientation() {
        return paperDefinitions.getDefaultPageOrientation();
    }

    public boolean isPagesReversed() {
        return printRangeReversePages.isSelected();
    }

    public boolean isOddPagesOnly() {
        return printRangeSubset.getSelectedIndex() == 1;
    }

    public boolean isEvenPagesOnly() {
        return printRangeSubset.getSelectedIndex() == 2;
    }

    public boolean isMonochrome() {
        return grayscale.isSelected();
    }

    private class CustomSlider extends JPanel {
        private int value = 1, maxValue = 100;
        private static final int rightMargin = 9;
        private static final int leftMargin = 9;
        private boolean dragging;

        CustomSlider() {
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseDragged(final MouseEvent e) {
                    if (dragging) {
                        value = (int) ((((double) (e.getX() - leftMargin(getWidth() (leftMargin + rightMargin))) (maxValue - 1)) 1.5);
                        if (value > maxValue) {
                            value = maxValue;
                        }
                        if (value < 1) {
                            value = 1;
                        }
                        updatePreview();
                        repaint();
                    }
                }
            });
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(final MouseEvent e) {
                    if (e.getY() 20) {
                        final double newValue = (((double) (e.getX() - leftMargin(getWidth() (leftMargin + rightMargin))) (maxValue - 1)) 1;
                        if (newValue > value) {
                            value++;
                        else if (newValue < value) {
                            value--;
                        }

                        if (value > maxValue) {
                            value = maxValue;
                        }
                        if (value < 1) {
                            value = 1;
                        }
                        updatePreview();
                        repaint();
                    }
                }

                @Override
                public void mousePressed(final MouseEvent e) {
                    if (e.getY() 20) {
                        dragging = true;
                    }
                }

                @Override
                public void mouseReleased(final MouseEvent e) {
                    dragging = false;
                }
            });
        }

        @Override
        public void paint(final Graphics g) {
            final Graphics2D g2 = (Graphics2Dg;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            final int w = getWidth();
            final int h = getHeight();

            //fill background
            g2.setPaint(getBackground());
            g2.fillRect(00, w, h);

            //draw text
            g2.setPaint(getForeground());
            g2.drawString(Messages.getMessage("PdfPrintPreview.Sheet"+ value + ' ' + Messages.getMessage("PdfPrintPreview.SheetOf"+ maxValue, 2, h - 3);

            //draw line
            g2.setPaint(Color.LIGHT_GRAY);
            g2.fillRect(leftMargin + 111, w - ((leftMargin + rightMargin1)3);
            g2.setPaint(Color.GRAY);
            g2.drawLine(leftMargin, 12, w - rightMargin, 12);

            //draw knob
            final float pageX = leftMargin + (((float) (value - 1(maxValue - 1)) (w - (leftMargin + rightMargin)));
            final Shape number = new Ellipse2D.Float(pageX - 66.5f1212);
            final Shape number2 = new Ellipse2D.Float(pageX - 48.5f88);
            g2.setPaint(Color.BLACK);
            g2.fill(number);
            g2.setPaint(Color.WHITE);
            g2.fill(number2);
        }

        void resetValue() {
            value = 1;
            repaint();
        }

        void setMaxValue(final int maxValue) {
            if (maxValue != this.maxValue) {
                value = 1;
                this.maxValue = maxValue;
                updatePreview();
                return;
            }
            repaint();
        }

        int getValue() {
            return value;
        }
    }

    private static class CustomSpinnerModel extends SpinnerNumberModel {
        private double value;
        private final ArrayList<ChangeListener> listeners = new ArrayList<>();
        private double minValue;

        @SuppressWarnings("ManualMinMaxCalculation")
        @Override
        public Object getPreviousValue() {
            if (value <= minValue) {
                return null;
            }
            if (value - 0.5 < minValue) {
                return minValue;
            }
            return value - 0.5;
        }

        @Override
        public Object getNextValue() {
            return value + 0.5;
        }

        @Override
        public Object getValue() {
            return value;
        }

        @Override
        public void addChangeListener(final ChangeListener l) {
            listeners.add(l);
        }

        @Override
        public void removeChangeListener(final ChangeListener l) {
            listeners.remove(l);
        }

        @Override
        public void setValue(final Object value) {
            try {
                final double newValue = (Doublevalue;
                this.value = Math.max(newValue, minValue);
            catch (final Exception e) {

                LogWriter.writeLog("Exception in setting print value " + e);

                throw new IllegalArgumentException();
            }
            final ChangeEvent e = new ChangeEvent(this);
            for (final ChangeListener listener : listeners) {
                if (listener != null) {
                    listener.stateChanged(e);
                }
            }
        }

        void setMinValue(final double minValue) {
            this.minValue = minValue;
            setValue(getValue());
        }
    }
}