latexstudio.editor.EditorTopComponent.java Source code

Java tutorial

Introduction

Here is the source code for latexstudio.editor.EditorTopComponent.java

Source

/*                    
 * Copyright (c) 2015 Sebastian Brudzinski
 * 
 * See the file LICENSE for copying permission.
 */
package latexstudio.editor;

import com.dropbox.core.DbxAccountInfo;
import com.dropbox.core.DbxClient;
import com.dropbox.core.DbxException;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import javax.swing.JOptionPane;
import javax.swing.text.BadLocationException;
import latexstudio.editor.files.FileService;
import latexstudio.editor.remote.Cloud;
import latexstudio.editor.remote.DbxState;
import latexstudio.editor.remote.DbxUtil;
import latexstudio.editor.settings.ApplicationSettings;
import latexstudio.editor.settings.SettingListener;
import latexstudio.editor.util.ApplicationUtils;
import org.apache.commons.io.IOUtils;
import org.fife.ui.autocomplete.AutoCompletion;
import org.fife.ui.autocomplete.BasicCompletion;
import org.fife.ui.autocomplete.CompletionProvider;
import org.fife.ui.autocomplete.DefaultCompletionProvider;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.TopComponent;

/**
 * Top component which displays the editor window.
 */
@ConvertAsProperties(dtd = "-//latexstudio.editor//Editor//EN", autostore = false)
@TopComponent.Description(preferredID = "EditorTopComponent",
        //iconBase="SET/PATH/TO/ICON/HERE", 
        persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(mode = "editor", openAtStartup = true)
@ActionID(category = "Window", id = "latexstudio.editor.EditorTopComponent")
@ActionReference(path = "Menu/Window" /*, position = 333 */)
@TopComponent.OpenActionRegistration(displayName = "#CTL_EditorAction", preferredID = "EditorTopComponent")
@Messages({ "CTL_EditorAction=Editor", "CTL_EditorTopComponent=Editor Window",
        "HINT_EditorTopComponent=This is a Editor window" })
public final class EditorTopComponent extends TopComponent {

    private boolean dirty = false;
    private boolean modified = false;
    private boolean previewDisplayed = true;
    private File currentFile;
    private DbxState dbxState;

    private AutoCompletion autoCompletion = null;
    private static final ApplicationLogger LOGGER = new ApplicationLogger("Cloud Support");

    public EditorTopComponent() {
        initComponents();
        setName(Bundle.CTL_EditorTopComponent());
        setDisplayName("welcome.tex");
        setToolTipText(Bundle.HINT_EditorTopComponent());
        putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);

        displayCloudStatus();
    }

    @SettingListener(setting = ApplicationSettings.Setting.AUTOCOMPLETE_ENABLED)
    public void setAutocompleteEnabled(boolean value) {
        if (autoCompletion != null) {
            autoCompletion.setAutoActivationEnabled(value);
        }
    }

    @SettingListener(setting = ApplicationSettings.Setting.AUTOCOMPLETE_DELAY)
    public void setAutocompleteDelay(int value) {
        if (autoCompletion != null) {
            autoCompletion.setAutoActivationDelay(value);
        }
    }

    @SettingListener(setting = ApplicationSettings.Setting.LINEWRAP_ENABLED)
    public void setLinewrapEnabled(boolean value) {
        if (rSyntaxTextArea != null) {
            rSyntaxTextArea.setLineWrap(value);
        }
    }

    /**
     * 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">                          
    private void initComponents() {

        rSyntaxTextArea = new org.fife.ui.rsyntaxtextarea.RSyntaxTextArea();
        rTextScrollPane1 = new org.fife.ui.rtextarea.RTextScrollPane(rSyntaxTextArea);

        rSyntaxTextArea.setColumns(20);
        rSyntaxTextArea.setRows(5);
        rSyntaxTextArea.setSyntaxEditingStyle(org.openide.util.NbBundle.getMessage(EditorTopComponent.class,
                "EditorTopComponent.rSyntaxTextArea.syntaxEditingStyle")); // NOI18N
        rSyntaxTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                rSyntaxTextAreaKeyReleased(evt);
            }

            public void keyTyped(java.awt.event.KeyEvent evt) {
                rSyntaxTextAreaKeyTyped(evt);
            }
        });

        rTextScrollPane1.setFoldIndicatorEnabled(true);
        rTextScrollPane1.setLineNumbersEnabled(true);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addContainerGap()
                        .addComponent(rTextScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 709, Short.MAX_VALUE)
                        .addContainerGap()));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addContainerGap()
                        .addComponent(rTextScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 546, Short.MAX_VALUE)
                        .addContainerGap()));
    }// </editor-fold>                        

    private void rSyntaxTextAreaKeyReleased(java.awt.event.KeyEvent evt) {
        dirty = true;
        setModified(true);
    }

    private void rSyntaxTextAreaKeyTyped(java.awt.event.KeyEvent evt) {
        if (currentFile == null || evt.isControlDown()) {
            return;
        }
        setDisplayName(currentFile.getName() + '*');
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private org.fife.ui.rsyntaxtextarea.RSyntaxTextArea rSyntaxTextArea;
    private org.fife.ui.rtextarea.RTextScrollPane rTextScrollPane1;
    // End of variables declaration//GEN-END:variables

    @Override
    public void componentOpened() {
        ApplicationUtils.deleteTempFiles();
        CompletionProvider provider = createCompletionProvider();
        autoCompletion = new AutoCompletion(provider);
        autoCompletion.install(rSyntaxTextArea);

        ApplicationSettings.INSTANCE.registerSettingListeners(this);

        String initFileDir = (String) ApplicationSettings.Setting.USER_LASTFILE.getValue();
        File initFile = new File(initFileDir);
        if (initFile.exists() && initFile.isFile()) {
            String content = FileService.readFromFile(initFileDir);
            setEditorContent(content);
            setCurrentFile(initFile);
        } else {
            InputStream is = null;
            try {
                is = getClass().getResource("/openlatexstudio/welcome.tex").openStream();
                String welcomeMessage = IOUtils.toString(is);
                setEditorContent(welcomeMessage);
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            } finally {
                IOUtils.closeQuietly(is);
            }
        }
    }

    @Override
    public void componentClosed() {
    }

    public String getEditorContent() {
        return rSyntaxTextArea.getText();
    }

    public void setEditorContent(String text) {
        rSyntaxTextArea.setText(text);
        dirty = true;
    }

    public boolean isDirty() {
        return dirty;
    }

    public void setDirty(boolean dirty) {
        this.dirty = dirty;
    }

    public boolean isModified() {
        return modified;
    }

    public void setModified(boolean modified) {
        this.modified = modified;
    }

    public boolean isPreviewDisplayed() {
        return previewDisplayed;
    }

    public void setPreviewDisplayed(boolean previewDisplayed) {
        this.previewDisplayed = previewDisplayed;
    }

    public void undoAction() {
        rSyntaxTextArea.undoLastAction();
    }

    public void redoAction() {
        rSyntaxTextArea.redoLastAction();
    }

    public File getCurrentFile() {
        return currentFile;
    }

    public void setCurrentFile(File currentFile) {
        this.currentFile = currentFile;

        if (currentFile != null) {
            setDisplayName(currentFile.getName());
            ApplicationSettings.Setting.USER_LASTFILE.setValue(currentFile.getAbsolutePath());
            ApplicationSettings.INSTANCE.save();
        }
    }

    public DbxState getDbxState() {
        return dbxState;
    }

    public void setDbxState(DbxState dbxState) {
        this.dbxState = dbxState;
    }

    private String findStartSymbol() {
        int carretCoordinates;
        while (true) {
            carretCoordinates = rSyntaxTextArea.getSelectionStart();
            if (rSyntaxTextArea.getSelectedText().startsWith("\n") || rSyntaxTextArea.getSelectionStart() == 0) {
                if (rSyntaxTextArea.getSelectionStart() != 0) {
                    rSyntaxTextArea.select(carretCoordinates + 1, rSyntaxTextArea.getSelectionEnd());
                } else {
                    rSyntaxTextArea.select(carretCoordinates, rSyntaxTextArea.getSelectionEnd());
                }
                return rSyntaxTextArea.getSelectedText();
            } else {
                carretCoordinates--;
                rSyntaxTextArea.select(carretCoordinates, rSyntaxTextArea.getSelectionEnd());
            }
        }
    }

    public void commentOutText() {
        String highlightedTextArea = rSyntaxTextArea.getSelectedText();

        if (highlightedTextArea != null) { // Some text is highlighted case
            highlightedTextArea = findStartSymbol();

            if (highlightedTextArea.startsWith("%")) {
                rSyntaxTextArea.replaceSelection(highlightedTextArea.replace("%", ""));
            } else {
                String[] array = highlightedTextArea.split("\n");
                StringBuilder commentedCodeBuilder = new StringBuilder();
                for (int i = 0; i < array.length; i++) {
                    array[i] = (array[i].charAt(0) == '%') ? array[i] : "%" + array[i];
                    if (i != array.length - 1) {
                        array[i] = array[i] + "\n";
                    }
                    commentedCodeBuilder.append(array[i]);
                }
                rSyntaxTextArea.replaceSelection(commentedCodeBuilder.toString());
            }
        } else { // Nothing is highlighted case
            try {
                int currentOffsetFromLineStart = rSyntaxTextArea.getCaretOffsetFromLineStart();
                int currentCaretPosition = rSyntaxTextArea.getCaretPosition();
                int lineStartPosition = currentCaretPosition - currentOffsetFromLineStart;
                int lineLength = rSyntaxTextArea.getLineEndOffsetOfCurrentLine();

                String firstChar = rSyntaxTextArea.getText(lineStartPosition, lineLength - lineStartPosition);
                if (firstChar.startsWith("%")) {
                    rSyntaxTextArea.replaceRange("", lineStartPosition, lineStartPosition + 1);
                } else {
                    rSyntaxTextArea.replaceRange("%", lineStartPosition, lineStartPosition);
                }
            } catch (BadLocationException ex) {
                Exceptions.printStackTrace(ex);
            }
        }

    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0");
        // TODO store your settings
    }

    void readProperties(java.util.Properties p) {
        String version = p.getProperty("version");
        // TODO read your settings according to their version
    }

    private CompletionProvider createCompletionProvider() {
        DefaultCompletionProvider provider = new DefaultCompletionProvider();
        provider.setAutoActivationRules(true, "");

        URL[] urls = new URL[3];
        urls[0] = getClass().getResource("/openlatexstudio/tex.cwl");
        urls[1] = getClass().getResource("/openlatexstudio/latex-document.cwl");
        urls[2] = getClass().getResource("/openlatexstudio/latex-mathsymbols.cwl");

        for (URL url : urls) {
            InputStream is = null;
            try {
                is = url.openStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String line;
                while ((line = br.readLine()) != null) {
                    if (!line.startsWith("#")) {
                        provider.addCompletion(new BasicCompletion(provider, line.substring(1)));
                    }
                }
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            } finally {
                IOUtils.closeQuietly(is);
            }
        }

        return provider;
    }

    private void displayCloudStatus() {

        boolean isConnected = false;
        String message;
        DbxAccountInfo info = null;

        // Check Dropbox connection
        DbxClient client = DbxUtil.getDbxClient();
        if (client != null) {
            String userToken = client.getAccessToken();
            if (userToken != null && !userToken.isEmpty()) {
                try {
                    info = client.getAccountInfo();
                    isConnected = true;
                } catch (DbxException ex) {
                    // simply stay working locally.
                }
            }
        }

        if (isConnected) {
            message = "Connected to Dropbox account as " + info.displayName + ".";
            Cloud.getInstance().setStatus(Cloud.Status.DBX_CONNECTED, " (" + info.displayName + ")");
        } else {
            message = "Working locally.";
            Cloud.getInstance().setStatus(Cloud.Status.DISCONNECTED);
        }

        LOGGER.log(message);
    }

    public UnsavedWorkState canOpen() {

        if (isModified() && !isPreviewDisplayed()) {
            int userChoice = JOptionPane.showConfirmDialog(this,
                    "This document has been modified. Do you want to save it first?", "Save document",
                    JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
            if (userChoice == JOptionPane.YES_OPTION) {
                return UnsavedWorkState.SAVE_AND_OPEN;
            } else if (userChoice == JOptionPane.NO_OPTION) {
                return UnsavedWorkState.OPEN;
            } else {
                return UnsavedWorkState.CANCEL;
            }

        } else {
            return UnsavedWorkState.OPEN;
        }
    }
}