matheos.texte.OngletTexte.java Source code

Java tutorial

Introduction

Here is the source code for matheos.texte.OngletTexte.java

Source

/**
 * Copyright 2012,2013 Franois Billioud
 *
 * This file is part of MathEOS.
 *
 * MathEOS is free software: you can redistribute it and/or modify under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation.
 *
 * MathEOS is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY.
 *
 * You should have received a copy of the GNU General Public License along with
 * MathEOS. If not, see <http://www.gnu.org/licenses/>.
 *
 *
 * Additional Terms according section 7 of GNU/GPL V3 :
 *
 * These additional terms refer to the source code of matheos.
 *
 * According to GNU GPL v3, section 7 b) :
 * You should mention any contributor of the work as long as his/her contribution
 * is meaningful in a covered work. If you convey a source code using a part of the
 * source code of MathEOS, you should keep the original author in the resulting
 * source code. If you propagate a covered work with the same objectives as the
 * Program (help student to attend maths classes with an adapted software), you
 * should mention Ludovic Faubourg, Frdric Marinoni as author of the idea of
 * this software. In any case, if you propagate a covered work you have to mention
 * Franois Billioud and Guillaume Varoquaux as author of the realisation of MathEOS
 * software. The paternity of the authors have to appear in a legible, unobscured
 * manner, showing clearly their link to the covered work in any document,
 * web pages,... which describe the project or participate to the distribution of
 * the covered work.
 */
package matheos.texte;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JScrollPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.CSS;
import javax.swing.text.html.HTMLEditorKit;
import matheos.IHM;
import matheos.elements.Onglet.OngletCours;
import matheos.sauvegarde.Data;
import matheos.sauvegarde.DataTP;
import matheos.sauvegarde.DataTexte;
import matheos.texte.composants.JLabelNote;
import matheos.texte.composants.JLabelTP;
import matheos.utils.boutons.ActionComplete;
import matheos.utils.boutons.Bouton;
import matheos.utils.dialogue.DialogueComplet;
import matheos.utils.dialogue.DialogueEvent;
import matheos.utils.dialogue.DialogueListener;
import matheos.utils.fichiers.Adresse;
import matheos.utils.interfaces.ComponentInsertionListener;
import matheos.utils.managers.ColorManager;
import matheos.utils.managers.CursorManager;
import matheos.utils.managers.PermissionManager;
import matheos.utils.objets.Blinking;
import matheos.utils.texte.EditeurIO;
import matheos.utils.texte.EditeurKit;
import matheos.utils.texte.JMathTextPane;

/**
 *
 * @author Franois Billioud
 */
@SuppressWarnings("serial")
public abstract class OngletTexte extends OngletCours {

    private static final float[] ZOOM = { 1f, 1.7f, 3f };
    private int indexZoom = 0;
    Editeur editeur;
    JScrollPane scrollPane;
    protected Bouton creation;
    private Blinking blinking;
    private final ActionComplete actionInsererImage = new ActionInsererImage();
    private final ActionCorrection actionCorriger = new ActionCorrection();

    public OngletTexte() {
        editeur = new Editeur();
        scrollPane = new JScrollPane(editeur, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.getVerticalScrollBar().setUnitIncrement(100);
        scrollPane.setWheelScrollingEnabled(true);
        scrollPane.getViewport().addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {//On s'assure du bon affichage des composants enfants en cas de scroll
                for (Component c : editeur.getComponents()) {
                    c.repaint();
                }
            }
        });
        add(scrollPane, BorderLayout.CENTER);

        EditeurKit editeurKit = editeur.getEditeurKit();
        barreOutils.addBoutonOnLeft(editeurKit.getBoutonBold());
        barreOutils.addBoutonOnLeft(editeurKit.getBoutonItalic());
        barreOutils.addBoutonOnLeft(editeurKit.getBoutonUnderline());
        barreOutils.addBoutonOnLeft(editeurKit.getBoutonStrike());
        barreOutils.addSeparateurOnLeft();

        barreOutils.addBoutonOnLeft(editeurKit.getBoutonLeftAlined());
        barreOutils.addBoutonOnLeft(editeurKit.getBoutonCenterAlined());
        barreOutils.addBoutonOnLeft(editeurKit.getBoutonRightAlined());
        barreOutils.addSeparateurOnLeft();

        //        barreOutils.addComponentOnLeft(editeurKit.getMenuTaille());
        barreOutils.addComponentOnLeft(editeurKit.getMenuCouleur());
        barreOutils.addBoutonOnLeft(editeurKit.getBoutonTitle());
        barreOutils.addBoutonOnLeft(editeurKit.getBoutonSubTitle());

        barreOutils.addSeparateurOnRight();
        barreOutils.addBoutonOnLeft(actionCorriger);
        barreOutils.addBoutonOnLeft(actionInsererImage);
        barreOutils.addComponentOnRight(getBoutonInsertionNote());

        //boutons  afficher uniquement en mode correction
        editeur.getEditeurKit().getBoutonStrike().setVisible(false);
        getBoutonInsertionNote().setVisible(false);
        editeur.getEditeurKit().getBoutonRightAlined().setVisible(false);

        //on coute les modifs de l'diteur
        editeur.setFontSize(EditeurKit.TAILLES_PT[0]);
        editeur.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
                switch (evt.getPropertyName()) {
                case Editeur.TITLE_PROPERTY:
                    //gre le changement de titre de chapitre
                    String newTitle = (String) evt.getNewValue();
                    String[] parts = newTitle.split(":");//HACK pour supprimer un ventuel prfix (chapitre i : xxx)
                    cahier.setTitre(cahier.getIndexCourant(), parts[parts.length - 1].trim());
                    break;
                case Editeur.FONT_SIZE_PROPERTY:
                    break;
                }
            }
        });
        editeur.addMouseListener(getChangeModeListener());
        //ajoute un changeModeListener sur les composants de l'editeur
        editeur.addComponentInsertionListener(new ComponentInsertionListener() {
            @Override
            public void componentInserted(Component c) {
                c.addMouseListener(OngletTexte.this.getChangeModeListener());
                fireComponentInsertion(c);
            }

            @Override
            public void componentRemoved(Component c) {
                c.removeMouseListener(OngletTexte.this.getChangeModeListener());
                fireComponentRemoval(c);
            }
        });
    }

    @Override
    public void setActionEnabled(PermissionManager.ACTION actionID, boolean b) {
    }

    @Override
    public JLabelTP getTP(long id) {
        return editeur.getTP(id);
    }

    @Override
    public void imprimer() {
        editeur.imprime();
    }

    @Override
    public void miseEnPage() {
        editeur.miseEnPage();
    }

    @Override
    public void apercu() {
        editeur.apercu();
    }

    /**
     * Mthode grant la remise en couleur des Composants lorsque l'diteur
     * redevient actif.
     */
    @Override
    public void activeContenu(boolean b) {
        if (b || !isModePresentationEnabled()) {
            this.setEnabled(b);
            editeur.setEnabled(b);
            if (b && editeur.isShowing()) {
                editeur.requestFocusInWindow();
            }
        }
    }

    @Override
    protected void setCahierViergeState(boolean b) {
        if (isNouveauCahier() == b) {
            return;
        }
        super.setCahierViergeState(b);
        editeur.getEditeurKit().getBoutonBold().setEnabled(!b);
        editeur.getEditeurKit().getBoutonItalic().setEnabled(!b);
        editeur.getEditeurKit().getBoutonUnderline().setEnabled(!b);
        editeur.getEditeurKit().getBoutonStrike().setEnabled(!b);
        editeur.getEditeurKit().getBoutonCenterAlined().setEnabled(!b);
        editeur.getEditeurKit().getBoutonLeftAlined().setEnabled(!b);
        editeur.getEditeurKit().getBoutonRightAlined().setEnabled(!b);
        editeur.getEditeurKit().getMenuCouleur().setEnabled(!b);
        editeur.getEditeurKit().getBoutonTitle().setEnabled(!b);
        editeur.getEditeurKit().getBoutonSubTitle().setEnabled(!b);
        getBoutonInsertionNote().setEnabled(!b);
        actionCorriger.setEnabled(!b);
        actionInsererImage.setEnabled(!b);

        //on gre l'tat du bouton de cration
        //        creation.setEnabled(true);//On active le bouton de cration uniquement
        if (b) {
            blinking = new Blinking(creation);
            blinking.start();
        } else {
            blinking.arreter();
            creation.setBorder(null);
        }
    }

    /**
     * charge les donns dans l'diteur
     * @param dataTexte DataTexte contenant les donnes
     */
    @Override
    protected void chargerEditeur(Data dataTexte) {
        editeur.charger(dataTexte);
        setModeCorrectionEnabled(false);
    }

    @Override
    protected void chargerCahierVierge() {
        chargerEditeur(new DataTexte(""));
    }

    @Override
    public void zoomP() {
        if (indexZoom < ZOOM.length - 1) {
            indexZoom++;
            updateFontSize();
        }
        editeur.getHTMLEditorKit().setDefaultCursor(CursorManager.getCursor(
                indexZoom == ZOOM.length - 1 ? CursorManager.TEXT_BIG_CURSOR : CursorManager.TEXT_MEDIUM_CURSOR));
    }

    @Override
    public void zoomM() {
        if (indexZoom > 0) {
            indexZoom--;
            updateFontSize();
        }
        editeur.getHTMLEditorKit().setDefaultCursor(CursorManager
                .getCursor(indexZoom == 0 ? CursorManager.TEXT_SMALL_CURSOR : CursorManager.TEXT_MEDIUM_CURSOR));
    }

    private void updateFontSize() {
        float size = EditeurKit.TAILLES_PT[0] * ZOOM[indexZoom];
        editeur.setFontSize((int) size);
    }

    public void export2Docx(final File f) {
        final String htmlBrut = EditeurIO.getHTMLContent(editeur.getHTMLdoc());
        final Map<String, Component> map = new HashMap<>(editeur.getComponentMap());
        new Thread(new Runnable() {
            @Override
            public void run() {
                EditeurIO.export2Docx(htmlBrut, map, f);
            }
        }).start();
    }

    public void export2Pdf(final File f) {
        final Formatter formatter = editeur.getFormatter();
        new Thread(new Runnable() {
            @Override
            public void run() {
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(f);
                    Document document = new Document();
                    Book book = formatter.createBook();

                    try {
                        PdfWriter writer = PdfWriter.getInstance(document, fos);
                        document.open();
                        PdfContentByte canvas = writer.getDirectContent();
                        for (int i = 0; i < book.getNumberOfPages(); i++) {
                            document.newPage();
                            PageFormat page = book.getPageFormat(i);
                            PdfTemplate templ = canvas.createTemplate((float) page.getWidth(),
                                    (float) page.getHeight());
                            Graphics2D g2 = templ.createGraphics((float) page.getWidth(), (float) page.getHeight());
                            try {
                                book.getPrintable(i).print(g2, book.getPageFormat(i), i);
                            } catch (PrinterException ex) {
                                Logger.getLogger(OngletTexte.class.getName()).log(Level.SEVERE, null, ex);
                            }
                            canvas.addTemplate(templ, 0, 0);
                            g2.dispose();
                        }
                    } catch (DocumentException ex) {
                        Logger.getLogger(OngletTexte.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        document.close();
                    }
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(OngletTexte.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    if (fos != null) {
                        try {
                            fos.flush();
                            fos.close();
                        } catch (IOException ex) {
                            Logger.getLogger(OngletTexte.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        }).start();
    }

    public boolean hasBeenModified() {
        return editeur.hasBeenModified();
    }

    public void setModified(boolean b) {
        editeur.setModified(b);
    }

    public void annuler() {
        editeur.annuler();
    }

    public void refaire() {
        editeur.refaire();
    }

    public boolean peutAnnuler() {
        return editeur.peutAnnuler();
    }

    public boolean peutRefaire() {
        return editeur.peutRefaire();
    }

    @Override
    public long insertion(long id, String nomTP, DataTP donnees, String image, int largeur, int hauteur) {
        return id == 0 ? insererTP(image, donnees, nomTP, largeur, hauteur)
                : updateTP(id, nomTP, donnees, image, largeur, hauteur);
    }

    /**
     * Mthode grant l'insertion d'un TP dans la partie cours.
     *
     * @param image l'image du TP  insrer.
     * @param data les donnes du TP  insrer.
     * @param nomTP le nom du type de TP  insrer.
     * @param hauteur la taille initiale du TP
     * @return un long reprsentant le JLabelTP correspondant  l'onglet TP
     * insr dans l'Editeur
     */
    private long insererTP(String im, DataTP data, String nomTP, int largeur, int hauteur) {
        if (im != null) {
            JLabelTP tp = new JLabelTP(im, data, nomTP, largeur, hauteur);
            editeur.insererTP(tp);
            return tp.getId();
        }
        return 0;
    }

    /**
     * Mthode grant l'insertion d'une note ou d'un barme dans la partie cours.
     *
     * @param note le JLabelNote  insrer
     * @return un long reprsentant le JLabelNote
     */
    private long insererNote(JLabelNote note) {
        editeur.insererNote(note);
        return note.getId();
    }

    /**
     * Mthode permettant de mettre  jour un tp  partir des nouvelles donnes
     * de l'onglet tp correspondant. Si le TP n'existe plus, on en cre un
     * nouveau.
     *
     * @param id l'id {@linkplain JLabelTP}  mettre  jour
     * @param nomTP le nouveau nom du TP
     * @param data la donne Serializable caractrisant l'tat du TP
     * @param imageTP l'image de la partie TP correspondant  la sauvegarde des
     * donnes
     * @return un long reprsentant l'id du JLabelTP mis  jour, ou un nouvel id
     * si l'ancien JLabelTP a t supprim de l'Editeur par l'utilisateur
     */
    public long updateTP(long id, String nomTP, DataTP data, String imageTP, int largeur, int hauteur) {
        JLabelTP oldTP = editeur.getTP(id);
        if (oldTP == null) {
            return insererTP(imageTP, data, nomTP, largeur, hauteur);
        }
        editeur.updateTP(oldTP, data, imageTP);
        return id;
    }

    @Override
    public DataTexte getDonneesEditeur() {
        return editeur.getDonnees();
    }

    private class ActionInsererImage extends ActionComplete {
        public ActionInsererImage() {
            super("text insert image");
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            JFileChooser chooser = new JFileChooser();
            chooser.setDialogType(JFileChooser.OPEN_DIALOG);
            chooser.setFileFilter(new Adresse.ImageFileFilter());
            int choix = chooser.showOpenDialog(IHM.getMainWindow());
            if (choix == JFileChooser.APPROVE_OPTION) {
                File f = chooser.getSelectedFile();
                if (f.exists()) {
                    try {
                        Image im = ImageIO.read(f);
                        editeur.insererImage(im);
                    } catch (IOException ex) {
                    }
                }
            }
        }
    }

    private class ActionCorrection extends ActionComplete.Toggle {
        private ActionCorrection() {
            super("text correct", false);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            setModeCorrectionEnabled(isSelected());
        }
    }

    private boolean correctionEnabled = false;
    private final CaretListener strikeStyleListener = new StrikeStyleUpdater();
    private Bouton boutonInsertionNote;

    private Bouton getBoutonInsertionNote() {
        return boutonInsertionNote == null ? boutonInsertionNote = new Bouton(new ActionInsertionNote())
                : boutonInsertionNote;
    }

    protected void setModeCorrectionEnabled(boolean b) {//Active le mode o l'lve ou l'enseignant peut corriger une copie
        if (b == correctionEnabled) {
            return;
        }
        correctionEnabled = b;
        actionCorriger.setSelected(b);//Assure la cohrence entre correctionEnabled et actionCorriger

        //boutons  afficher en mode correction
        editeur.getEditeurKit().getBoutonStrike().setVisible(b);
        getBoutonInsertionNote().setVisible(b);
        editeur.getEditeurKit().getBoutonRightAlined().setVisible(b);

        //boutons  afficher en mode normal
        creation.setVisible(!b);
        editeur.getEditeurKit().getBoutonSubTitle().setVisible(!b);
        editeur.getEditeurKit().getBoutonTitle().setVisible(!b);

        //dispositions spciales
        editeur.setStyleUpdatingEnabled(!b);//le caret doit garder sa couleur en toutes circonstances en mode correction
        editeur.setCaretPosition(editeur.getSelectionStart());//Changer de mode avec une slection en cours peut amener des confusions
        if (correctionEnabled) {
            editeur.getEditeurKit().getMenuCouleur().setSelectedCouleur(EditeurKit.COULEURS[3]);
            editeur.addCaretListener(strikeStyleListener);
        } else {
            editeur.removeCaretListener(strikeStyleListener);
            editeur.getEditeurKit().getMenuCouleur().setSelectedCouleur(EditeurKit.COULEURS[0]);
        }

        getBarreOutils().revalidate();
        getBarreOutils().repaint();
    }

    /** CaretListener qui met  jour le style pour qu'il corresponde au texte o se situe le caret **/
    private class StrikeStyleUpdater implements CaretListener {
        @Override
        public void caretUpdate(CaretEvent e) {
            int referentCharacter = e.getDot();
            try {
                if (referentCharacter > 0 && !editeur.getText(referentCharacter - 1, 1).equals("\n")) {
                    referentCharacter--;
                }
            } catch (BadLocationException ex) {
                Logger.getLogger(JMathTextPane.class.getName()).log(Level.SEVERE, null, ex);
            }
            AttributeSet ast = editeur.getHTMLdoc().getCharacterElement(referentCharacter).getAttributes();
            Object textDecorationValue = ast.getAttribute(CSS.Attribute.TEXT_DECORATION);
            editeur.getEditeurKit().getBoutonStrike().setSelected(
                    textDecorationValue != null && textDecorationValue.toString().equals("line-through"));
        }
    }

    private class ActionInsertionNote extends ActionComplete {
        private ActionInsertionNote() {
            super("text insert mark");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            DialogueComplet d = new DialogueComplet("dialog mark scale");
            d.addDialogueListener(new DialogueListener() {
                @Override
                public void dialoguePerformed(DialogueEvent event) {
                    if (!event.isConfirmButtonPressed()) {
                        return;
                    }
                    JLabelNote note = new JLabelNote(event.getInputString("numerator"),
                            event.getInputString("denominator"), 50, 50);
                    try {
                        editeur.getHTMLdoc().insertString(editeur.getCaretPosition(), "\n", null);
                        new HTMLEditorKit.AlignmentAction("align right", StyleConstants.ALIGN_RIGHT)
                                .actionPerformed(
                                        new ActionEvent(editeur, ActionEvent.ACTION_PERFORMED, "align right"));
                        insererNote(note);
                        editeur.getHTMLdoc().insertString(editeur.getCaretPosition(), "\n", null);
                        new HTMLEditorKit.AlignmentAction("align left", StyleConstants.ALIGN_LEFT).actionPerformed(
                                new ActionEvent(editeur, ActionEvent.ACTION_PERFORMED, "align left"));
                    } catch (BadLocationException ex) {
                        Logger.getLogger(OngletTexte.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            });
        }
    }

}