org.pepstock.jem.gwt.client.editor.AbstractSyntaxHighlighter.java Source code

Java tutorial

Introduction

Here is the source code for org.pepstock.jem.gwt.client.editor.AbstractSyntaxHighlighter.java

Source

/**
JEM, the BEE - Job Entry Manager, the Batch Execution Environment
Copyright (C) 2012-2015   Andrea "Stock" Stocchero
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.pepstock.jem.gwt.client.editor;

import org.pepstock.jem.gwt.client.Sizes;
import org.pepstock.jem.gwt.client.commons.Images;
import org.pepstock.jem.gwt.client.commons.Styles;
import org.pepstock.jem.gwt.client.events.EventBus;
import org.pepstock.jem.gwt.client.events.FontSizeEvent;
import org.pepstock.jem.gwt.client.events.FontSizeEventHandler;
import org.pepstock.jem.gwt.client.security.CurrentUser;
import org.pepstock.jem.gwt.client.security.PreferencesKeys;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.VerticalAlign;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Abstract class which manages ACE editor, delegating attributes to set to editor and
 * Menubar.
 * 
 * @author Andrea "Stock" Stocchero
 * @version 1.4   
 *
 */
public abstract class AbstractSyntaxHighlighter extends VerticalPanel implements SyntaxHighlighter {

    static {
        Styles.INSTANCE.common().ensureInjected();
    }

    private String content = null;

    private Editor editor = null;

    private boolean editorStarted = false;

    private MenuBar menu = new MenuBar();

    private MenuItem selectedFontItem = null;

    private boolean changed = false;

    private boolean readOnly = false;

    private MenuItem small = null;
    private MenuItem medium = null;
    private MenuItem large = null;
    private MenuItem extraLarge = null;

    private HandlerRegistration eventRegistration = null;

    private FontSize currentFontSize = null;

    /**
     * Empty constructor. Editor element ID will be calculated
     * automatically (a progressive number) and initial text is empty.
     */
    public AbstractSyntaxHighlighter() {
        this(null);
    }

    /**
     * Creates the editor using a specific element ID. Text is empty.
     * @param id element id of editor
     */
    public AbstractSyntaxHighlighter(String id) {
        // sets CSS
        // pay attention to zIndex. MUST be SET HIGH
        menu.addStyleName(Styles.INSTANCE.common().editMenuBar());
        menu.setHeight(Sizes.toString(Sizes.TABBAR_HEIGHT_PX));
        menu.setAnimationEnabled(true);
        add(menu);

        // if id is null, use empty constructor
        if (id == null) {
            editor = new Editor();
        } else {
            editor = new Editor(id);
        }
        add(editor);
    }

    /**
     * Returns if content of editor is changed.
     * 
     * @return <code>true</code> if text of editor is changed, otherwise false.
     */
    public boolean isChanged() {
        return changed;
    }

    /**
     * Sets if the text of editor is changed.
     * 
     * @param changed the changed to set
     */
    public void setChanged(boolean changed) {
        this.changed = changed;
    }

    /**
     * Returns if editor is started.
     * 
     * @return the editorStarted
     */
    public boolean isEditorStarted() {
        return editorStarted;
    }

    /**
     * Returns the original content, which initialize the editor.
     * 
     * @return the content
     */
    public String getContent() {
        return content;
    }

    /**
     * Sets the original content, which initialize the editor.<br>
     * If editor is already started, sets the content to editor text.
     * 
     * @param content the content to set
     */
    public void setContent(String content) {
        this.content = content;
        // if editor is already started, sets TEXT
        if (editorStarted) {
            editor.setText(content);
        }
    }

    /**
     * Returns editor instance.
     * 
     * @return the editor
     */
    public Editor getEditor() {
        return editor;
    }

    /**
     * Returns if editor is readOnly.
     * @return the readOnly
     */
    public boolean isReadOnly() {
        return readOnly;
    }

    /**
     * @param readOnly the readOnly to set
     */
    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
        editor.setReadOnly(readOnly);
    }

    /**
     * Starts editor (if not already started).
     * Furthermore adds menu item on menu bar
     */
    public void startEditor() {
        if (!editorStarted) {
            // start the first editor and set its theme and mode
            // must be called before calling setTheme/setMode/etc.
            editor.start();

            editor.setTheme(Theme.JEM);
            // delegates to set editor attributes
            setEditorAttributes(editor);

            // sets text, remove print margin and flag 
            // to check if editor is started
            editor.setShowPrintMargin(false);
            editor.setText(content);
            editorStarted = true;

            // adds change listener
            editor.addOnChangeHandler(new EditorChangeHandler() {

                @Override
                public void invokeAceCallback(JavaScriptObject obj) {
                    // if content not null, checks if content is equals to text
                    if (getContent() != null) {
                        changed = !getContent().equalsIgnoreCase(getEditor().getText());
                    } else {
                        // if there is not content, is considered NOT changed!
                        changed = false;
                    }
                    // fires the event
                    onChange(changed);
                }
            });

            // gets the user preferences for editor 
            String pref = CurrentUser.getInstance().getStringPreference(PreferencesKeys.JOB_EDIT_FONTSIZE);
            // default is SMALL
            if (pref == null) {
                pref = FontSize.SMALL.getCssValue();
            }

            // Font size item
            MenuBar fontSizeMenu = new MenuBar(true);
            small = createMenuItem(FontSize.SMALL, pref);
            medium = createMenuItem(FontSize.MEDIUM, pref);
            large = createMenuItem(FontSize.LARGE, pref);
            extraLarge = createMenuItem(FontSize.EXTRA_LARGE, pref);

            fontSizeMenu.addItem(small);
            fontSizeMenu.addItem(medium);
            fontSizeMenu.addItem(large);
            fontSizeMenu.addItem(extraLarge);

            // if content is null, no ctions available
            if (content == null) {
                small.setEnabled(false);
                medium.setEnabled(false);
                large.setEnabled(false);
                extraLarge.setEnabled(false);
            }

            // load images and creates menu item
            Image imgFontSize = new Image(Images.INSTANCE.editFontSize());
            imgFontSize.getElement().getStyle().setVerticalAlign(VerticalAlign.MIDDLE);
            MenuItem fontSizeMenuItem = new MenuItem(imgFontSize + "  Size", true, fontSizeMenu);
            // sets font weight always to normal (no bold as GWT uses as default)
            fontSizeMenuItem.getElement().getStyle().setFontWeight(FontWeight.NORMAL);

            menu.addItem(fontSizeMenuItem);
            // calls here specific menu bar customization
            setMenuItems(menu);

            // adds a font size event handler so is aware when a editor changes font size
            eventRegistration = EventBus.INSTANCE.addHandler(FontSizeEvent.TYPE,
                    new SyntaxHighlighterFontSizeEventHandler());

        } else {
            // sets attributes 
            setEditorAttributes(editor);
            editor.setFontSize(currentFontSize.getCssValue());
        }
    }

    private class SyntaxHighlighterFontSizeEventHandler implements FontSizeEventHandler {
        @Override
        public void onChange(FontSizeEvent event) {
            // called whene editor is started
            if (isEditorStarted()) {
                FontSize fontsize = event.getFontSize();
                // saves font size
                currentFontSize = fontsize;
                // sets font size on editor
                // PAY attention that when editor is in a popup, if popup is not showing, 
                // the element of editor is null.
                editor.setFontSize(fontsize.getCssValue());
                // Enables the previous menu item, removing style
                selectedFontItem.setEnabled(true);
                selectedFontItem.removeStyleName(Styles.INSTANCE.common().editMenuItemDisabled());

                // looks for menu item of new font size
                MenuItem item = null;
                if (fontsize.getName().equals(FontSize.SMALL.getName())) {
                    item = small;
                } else if (fontsize.getName().equals(FontSize.MEDIUM.getName())) {
                    item = medium;
                } else if (fontsize.getName().equals(FontSize.LARGE.getName())) {
                    item = large;
                } else if (fontsize.getName().equals(FontSize.EXTRA_LARGE.getName())) {
                    item = extraLarge;
                } else {
                    item = medium;
                }
                // Disables menu item and add disabled style
                item.setEnabled(false);
                item.addStyleName(Styles.INSTANCE.common().editMenuItemDisabled());
                selectedFontItem = item;
            }
        }
    }

    /**
     * Method to set specific attributes on editor 
     * 
     * @param editor editor to change
     */
    public abstract void setEditorAttributes(Editor editor);

    /**
     * Method to add and change menubar of editor
     * @param menu menu to change
     * @param jclNotAvailable if JCL non available 
     */
    public abstract void setMenuItems(MenuBar menu);

    private MenuItem createMenuItem(final FontSize fontsize, String preference) {
        SafeHtmlBuilder builder = new SafeHtmlBuilder();
        builder.appendHtmlConstant(
                "<div style='font-size: " + fontsize.getCssValue() + ";'>" + fontsize.getName() + "</div>");
        final MenuItem item = new MenuItem(builder.toSafeHtml());
        item.setScheduledCommand(new Command() {
            @Override
            public void execute() {
                // sets preferences
                CurrentUser.getInstance().setStringPreference(PreferencesKeys.JOB_EDIT_FONTSIZE,
                        fontsize.getCssValue());
                // fires new event
                FontSizeEvent event = new FontSizeEvent(fontsize);
                EventBus.INSTANCE.fireEvent(event);
            }
        });
        if (preference.equalsIgnoreCase(fontsize.getCssValue())) {
            selectedFontItem = item;
            item.setEnabled(false);
            item.addStyleName(Styles.INSTANCE.common().editMenuItemDisabled());
            editor.setFontSize(fontsize.getCssValue());
            currentFontSize = fontsize;
        }
        return item;
    }

    /**
     * Destroy EDITOR, when inspector is hidden
     */
    public void destroyEditor() {
        if (editorStarted) {
            editor.destroy();
            if (eventRegistration != null) {
                eventRegistration.removeHandler();
            }
        }
    }

    /**
     * Called by editor listener when the text of editor is changed
     * @param changed <code>true</code> if text is changed
     */
    public void onChange(boolean changed) {
        // NOP
    }

    /**
     * @see org.pepstock.jem.gwt.client.ResizeCapable#onResize(int, int)
     */
    @Override
    public void onResize(int availableWidth, int availableHeight) {
        // MenuBar has got borders
        menu.setWidth(Sizes.toString(availableWidth));
        editor.setWidth(Sizes.toString(availableWidth));
        editor.setHeight(Sizes.toString(availableHeight - Sizes.TABBAR_HEIGHT_PX - Sizes.MAIN_TAB_PANEL_BORDER));
        if (isEditorStarted()) {
            editor.onResize();
        }
    }
}