org.opencms.ui.editors.CmsSourceEditor Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.ui.editors;
import org.opencms.file.CmsResource;
import org.opencms.file.types.CmsResourceTypeBinary;
import org.opencms.file.types.CmsResourceTypeImage;
import org.opencms.file.types.CmsResourceTypeJsp;
import org.opencms.file.types.CmsResourceTypeXmlContent;
import org.opencms.file.types.CmsResourceTypeXmlPage;
import org.opencms.file.types.I_CmsResourceType;
import org.opencms.i18n.CmsMessages;
import org.opencms.json.JSONException;
import org.opencms.json.JSONObject;
import org.opencms.lock.CmsLockUtil.LockedFile;
import org.opencms.main.CmsException;
import org.opencms.main.OpenCms;
import org.opencms.ui.A_CmsUI;
import org.opencms.ui.CmsVaadinUtils;
import org.opencms.ui.FontOpenCms;
import org.opencms.ui.apps.CmsAppWorkplaceUi;
import org.opencms.ui.apps.CmsEditor;
import org.opencms.ui.apps.I_CmsAppSettings;
import org.opencms.ui.apps.I_CmsAppUIContext;
import org.opencms.ui.apps.I_CmsHasShortcutActions;
import org.opencms.ui.components.CmsConfirmationDialog;
import org.opencms.ui.components.CmsErrorDialog;
import org.opencms.ui.components.CmsToolBar;
import org.opencms.ui.components.I_CmsWindowCloseListener;
import org.opencms.ui.components.OpenCmsTheme;
import org.opencms.ui.components.codemirror.CmsCodeMirror;
import org.opencms.ui.components.codemirror.CmsCodeMirror.CodeMirrorLanguage;
import java.util.HashMap;
import java.util.Map;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.Action;
import com.vaadin.event.ShortcutAction;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.UI;
/**
* The plain text editor.
*/
public class CmsSourceEditor
implements I_CmsEditor, I_CmsWindowCloseListener, ViewChangeListener, I_CmsHasShortcutActions {
/**
* Stores the editor settings.
*/
public static class EditorSettings implements I_CmsAppSettings {
/** JSON key constant. */
private static final String BRACKETS = "brackets";
/** JSON key constant. */
private static final String FONTSIZE = "fontsize";
/** JSON key constant. */
private static final String HIGHLIGHTING = "highlighting";
/** JSON key constant. */
private static final String TABS = "tabs";
/** JSON key constant. */
private static final String WRAPPING = "wrapping";
/** The auto close brackets flag. */
boolean m_closeBrackets = true;
/** The font size. */
String m_fontSize = "16px";
/** The highlighting flag. */
boolean m_highlighting = true;
/** The line wrapping flag. */
boolean m_lineWrapping = false;
/** The tab visibility flag. */
boolean m_tabsVisible = true;
/**
* @see org.opencms.ui.apps.I_CmsAppSettings#getSettingsString()
*/
public String getSettingsString() {
JSONObject json = new JSONObject();
try {
json.put(BRACKETS, m_closeBrackets);
json.put(HIGHLIGHTING, m_highlighting);
json.put(WRAPPING, m_lineWrapping);
json.put(FONTSIZE, m_fontSize);
json.put(TABS, m_tabsVisible);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return json.toString();
}
/**
* @see org.opencms.ui.apps.I_CmsAppSettings#restoreSettings(java.lang.String)
*/
public void restoreSettings(String storedSettings) {
try {
JSONObject json = new JSONObject(storedSettings);
if (json.has(BRACKETS)) {
m_closeBrackets = json.getBoolean(BRACKETS);
}
if (json.has(HIGHLIGHTING)) {
m_highlighting = json.getBoolean(HIGHLIGHTING);
}
if (json.has(WRAPPING)) {
m_lineWrapping = json.getBoolean(WRAPPING);
}
if (json.has(TABS)) {
m_tabsVisible = json.getBoolean(TABS);
}
if (json.has(FONTSIZE)) {
m_fontSize = json.getString(FONTSIZE);
}
} catch (JSONException e) {
// LOG.error("Failed to restore file explorer settings from '" + storedSettings + "'", e);
}
}
}
/** Exit shortcut. */
private static final Action ACTION_EXIT = new ShortcutAction(
"Ctrl+Shift+X",
ShortcutAction.KeyCode.X,
new int[] {ShortcutAction.ModifierKey.CTRL, ShortcutAction.ModifierKey.SHIFT});
/** Save shortcut. */
private static final Action ACTION_SAVE = new ShortcutAction(
"Ctrl+S",
ShortcutAction.KeyCode.S,
new int[] {ShortcutAction.ModifierKey.CTRL});
/** Save & Exit shortcut. */
private static final Action ACTION_SAVE_AND_EXIT = new ShortcutAction(
"Ctrl+Shift+S",
ShortcutAction.KeyCode.S,
new int[] {ShortcutAction.ModifierKey.CTRL, ShortcutAction.ModifierKey.SHIFT});
/** The available font sizes. */
private static final String[] FONT_SIZES = new String[] {"8px", "10px", "12px", "14px", "16px", "18px", "20px"};
/** The serial version id. */
private static final long serialVersionUID = 726920483145397926L;
/** The editor back link. */
String m_backLink;
/** The code mirror instance. */
CmsCodeMirror m_codeMirror;
/** The bundle editor shortcuts. */
Map m_shortcutActions;
/** The content changed flag. */
private boolean m_changed;
/** The cleared flag. */
private boolean m_cleared;
/** The exit button. */
private Button m_exit;
/** The current file. */
private LockedFile m_file;
/** The save button. */
private Button m_save;
/** The save and exit button. */
private Button m_saveAndExit;
/**
* Constructor.
*/
public CmsSourceEditor() {
m_shortcutActions = new HashMap();
m_shortcutActions.put(ACTION_SAVE, new Runnable() {
public void run() {
save();
}
});
m_shortcutActions.put(ACTION_SAVE_AND_EXIT, new Runnable() {
public void run() {
saveAndExit();
}
});
m_shortcutActions.put(ACTION_EXIT, new Runnable() {
public void run() {
exit();
}
});
}
/**
* @see com.vaadin.navigator.ViewChangeListener#afterViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
*/
public void afterViewChange(ViewChangeEvent event) {
// nothing to do
}
/**
* @see com.vaadin.navigator.ViewChangeListener#beforeViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
*/
public boolean beforeViewChange(final ViewChangeEvent event) {
if (m_changed) {
CmsConfirmationDialog.show(
CmsVaadinUtils.getMessageText(org.opencms.ui.apps.Messages.GUI_EDITOR_CLOSE_CAPTION_0),
CmsVaadinUtils.getMessageText(org.opencms.ui.apps.Messages.GUI_EDITOR_CLOSE_TEXT_0),
new Runnable() {
public void run() {
clear();
event.getNavigator().navigateTo(event.getViewName());
}
});
return false;
}
if (!m_cleared) {
clear();
}
return true;
}
/**
* Returns the syntax highlighting type for the currently edited resource.
*
* @param resource the resource to edit
*
* @return the syntax highlighting type
*/
public CodeMirrorLanguage getHighlightMode(CmsResource resource) {
if (resource != null) {
// determine resource type
int type = resource.getTypeId();
if (CmsResourceTypeJsp.isJspTypeId(type)) {
// JSP file
return CodeMirrorLanguage.JSP;
}
if (CmsResourceTypeXmlContent.isXmlContent(resource) || CmsResourceTypeXmlPage.isXmlPage(resource)) {
// XML content file or XML page file
return CodeMirrorLanguage.XML;
}
// all other files will be matched according to their suffix
int dotIndex = resource.getName().lastIndexOf('.');
if (dotIndex != -1) {
String suffix = resource.getName().substring(dotIndex + 1).toLowerCase();
for (CodeMirrorLanguage lang : CodeMirrorLanguage.values()) {
if (lang.isSupportedFileType(suffix)) {
return lang;
}
}
}
}
// return HTML type as default
return CodeMirrorLanguage.HTML;
}
/**
* @see org.opencms.ui.editors.I_CmsEditor#getPriority()
*/
public int getPriority() {
return 10;
}
/**
* @see org.opencms.ui.apps.I_CmsHasShortcutActions#getShortcutActions()
*/
public Map getShortcutActions() {
return m_shortcutActions;
}
/**
* @see org.opencms.ui.editors.I_CmsEditor#initUI(org.opencms.ui.apps.I_CmsAppUIContext, org.opencms.file.CmsResource, java.lang.String)
*/
public void initUI(I_CmsAppUIContext context, CmsResource resource, String backLink) {
CmsMessages messages = Messages.get().getBundle(UI.getCurrent().getLocale());
context.showInfoArea(false);
context.setAppTitle(messages.key(Messages.GUI_SOURCE_EDITOR_TITLE_0));
CmsAppWorkplaceUi.setWindowTitle(
CmsVaadinUtils.getMessageText(
org.opencms.ui.apps.Messages.GUI_CONTENT_EDITOR_TITLE_2,
resource.getName(),
CmsResource.getParentFolder(A_CmsUI.getCmsObject().getSitePath(resource))));
m_backLink = backLink;
m_codeMirror = new CmsCodeMirror();
m_codeMirror.setSizeFull();
context.setAppContent(m_codeMirror);
context.enableDefaultToolbarButtons(false);
m_saveAndExit = CmsToolBar.createButton(
FontOpenCms.SAVE_EXIT,
messages.key(Messages.GUI_BUTTON_SAVE_AND_EXIT_0),
true);
m_saveAndExit.addClickListener(new ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
saveAndExit();
}
});
m_saveAndExit.setEnabled(false);
context.addToolbarButton(m_saveAndExit);
m_save = CmsToolBar.createButton(FontOpenCms.SAVE, messages.key(Messages.GUI_BUTTON_SAVE_0), true);
m_save.addClickListener(new ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
save();
}
});
m_save.setEnabled(false);
context.addToolbarButton(m_save);
Button undo = CmsToolBar.createButton(FontOpenCms.UNDO, messages.key(Messages.GUI_BUTTON_UNDO_0), true);
context.addToolbarButton(undo);
Button redo = CmsToolBar.createButton(FontOpenCms.REDO, messages.key(Messages.GUI_BUTTON_REDO_0), true);
context.addToolbarButton(redo);
m_codeMirror.registerUndoRedo(undo, redo);
Button search = CmsToolBar.createButton(FontOpenCms.SEARCH, messages.key(Messages.GUI_BUTTON_SEARCH_0), true);
context.addToolbarButton(search);
Button replace = CmsToolBar.createButton(
FontOpenCms.SEARCH_REPLACE,
messages.key(Messages.GUI_BUTTON_REPLACE_0),
true);
context.addToolbarButton(replace);
m_codeMirror.registerSearchReplace(search, replace);
EditorSettings settings;
try {
settings = OpenCms.getWorkplaceAppManager().getAppSettings(A_CmsUI.getCmsObject(), EditorSettings.class);
} catch (Exception e) {
settings = new EditorSettings();
}
final Button toggleHighlight = CmsToolBar.createButton(
FontOpenCms.HIGHLIGHT,
messages.key(Messages.GUI_BUTTON_TOGGLE_HIGHLIGHTING_0));
toggleHighlight.addClickListener(new ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
Button b = event.getButton();
boolean pressed = b.getStyleName().contains(OpenCmsTheme.BUTTON_PRESSED);
if (pressed) {
b.removeStyleName(OpenCmsTheme.BUTTON_PRESSED);
} else {
b.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
}
m_codeMirror.setHighlighting(!pressed);
}
});
if (settings.m_highlighting) {
m_codeMirror.setHighlighting(true);
toggleHighlight.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
} else {
m_codeMirror.setHighlighting(false);
}
context.addToolbarButtonRight(toggleHighlight);
final Button toggleLineWrap = CmsToolBar.createButton(
FontOpenCms.WRAP_LINES,
messages.key(Messages.GUI_BUTTON_TOGGLE_LINE_WRAPPING_0));
toggleLineWrap.addClickListener(new ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
Button b = event.getButton();
boolean pressed = b.getStyleName().contains(OpenCmsTheme.BUTTON_PRESSED);
if (pressed) {
b.removeStyleName(OpenCmsTheme.BUTTON_PRESSED);
} else {
b.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
}
m_codeMirror.setLineWrapping(!pressed);
}
});
if (settings.m_lineWrapping) {
m_codeMirror.setLineWrapping(true);
toggleLineWrap.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
} else {
m_codeMirror.setLineWrapping(false);
}
context.addToolbarButtonRight(toggleLineWrap);
final Button toggleBrackets = CmsToolBar.createButton(
FontOpenCms.BRACKETS,
messages.key(Messages.GUI_BUTTON_TOBBLE_BRACKET_AUTOCLOSE_0));
toggleBrackets.addClickListener(new ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
Button b = event.getButton();
boolean pressed = b.getStyleName().contains(OpenCmsTheme.BUTTON_PRESSED);
if (pressed) {
b.removeStyleName(OpenCmsTheme.BUTTON_PRESSED);
} else {
b.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
}
m_codeMirror.setCloseBrackets(!pressed);
}
});
if (settings.m_closeBrackets) {
m_codeMirror.setCloseBrackets(true);
toggleBrackets.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
} else {
m_codeMirror.setCloseBrackets(false);
}
context.addToolbarButtonRight(toggleBrackets);
final Button toggleTabs = CmsToolBar.createButton(
FontOpenCms.INVISIBLE_CHARS,
messages.key(Messages.GUI_BUTTON_TOGGLE_TAB_VISIBILITY_0));
toggleTabs.addClickListener(new ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
Button b = event.getButton();
boolean pressed = b.getStyleName().contains(OpenCmsTheme.BUTTON_PRESSED);
if (pressed) {
b.removeStyleName(OpenCmsTheme.BUTTON_PRESSED);
} else {
b.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
}
m_codeMirror.setTabsVisible(!pressed);
}
});
if (settings.m_tabsVisible) {
m_codeMirror.setTabsVisible(true);
toggleTabs.addStyleName(OpenCmsTheme.BUTTON_PRESSED);
} else {
m_codeMirror.setTabsVisible(false);
}
context.addToolbarButtonRight(toggleTabs);
ComboBox modeSelect = new ComboBox();
modeSelect.setWidth("115px");
modeSelect.addStyleName(OpenCmsTheme.TOOLBAR_FIELD);
modeSelect.addStyleName(OpenCmsTheme.REQUIRED_BUTTON);
modeSelect.setNullSelectionAllowed(false);
modeSelect.setImmediate(true);
modeSelect.setNewItemsAllowed(false);
for (CodeMirrorLanguage lang : CodeMirrorLanguage.values()) {
modeSelect.addItem(lang);
modeSelect.setItemCaption(lang, lang.name());
}
CodeMirrorLanguage lang = getHighlightMode(resource);
modeSelect.setValue(lang);
m_codeMirror.setLanguage(lang);
modeSelect.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 1L;
public void valueChange(ValueChangeEvent event) {
m_codeMirror.setLanguage((CodeMirrorLanguage)event.getProperty().getValue());
}
});
context.addToolbarButtonRight(modeSelect);
ComboBox fontSizeSelect = new ComboBox();
fontSizeSelect.setWidth("75px");
fontSizeSelect.addStyleName(OpenCmsTheme.TOOLBAR_FIELD);
fontSizeSelect.addStyleName(OpenCmsTheme.REQUIRED_BUTTON);
fontSizeSelect.setNullSelectionAllowed(false);
fontSizeSelect.setImmediate(true);
fontSizeSelect.setNewItemsAllowed(false);
for (int i = 0; i < FONT_SIZES.length; i++) {
fontSizeSelect.addItem(FONT_SIZES[i]);
}
fontSizeSelect.setValue(settings.m_fontSize);
fontSizeSelect.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 1L;
public void valueChange(ValueChangeEvent event) {
m_codeMirror.setFontSize((String)event.getProperty().getValue());
}
});
context.addToolbarButtonRight(fontSizeSelect);
m_codeMirror.setFontSize(settings.m_fontSize);
m_exit = CmsToolBar.createButton(FontOpenCms.EXIT, messages.key(Messages.GUI_BUTTON_CANCEL_0), true);
m_exit.addClickListener(new ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
exit();
}
});
context.addToolbarButtonRight(m_exit);
try {
m_file = LockedFile.lockResource(A_CmsUI.getCmsObject(), resource);
String content = new String(m_file.getFile().getContents(), m_file.getEncoding());
m_codeMirror.setValue(content);
} catch (Exception e) {
CmsErrorDialog.showErrorDialog(e);
}
m_codeMirror.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 1L;
public void valueChange(ValueChangeEvent event) {
onChange((String)event.getProperty().getValue());
}
});
}
/**
* @see org.opencms.ui.editors.I_CmsEditor#matchesResource(org.opencms.file.CmsResource, boolean)
*/
public boolean matchesResource(CmsResource resource, boolean plainText) {
I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(resource);
return !((type instanceof CmsResourceTypeBinary) || (type instanceof CmsResourceTypeImage));
}
/**
* @see org.opencms.ui.editors.I_CmsEditor#newInstance()
*/
public I_CmsEditor newInstance() {
return new CmsSourceEditor();
}
/**
* @see org.opencms.ui.components.I_CmsWindowCloseListener#onWindowClose()
*/
public void onWindowClose() {
clear();
}
/**
* Unlocks the edited file before leaving the editor.
*/
void clear() {
m_cleared = true;
m_changed = false;
try {
m_file.unlock();
} catch (CmsException e) {
// ignore
}
OpenCms.getWorkplaceAppManager().storeAppSettings(
A_CmsUI.getCmsObject(),
EditorSettings.class,
getCurrentSettings());
}
/**
* Exits the editor without saving.
* Will ask to confirm exit on changed contents.
*/
void exit() {
if (m_changed) {
CmsConfirmationDialog.show(
CmsVaadinUtils.getMessageText(org.opencms.ui.apps.Messages.GUI_EDITOR_CLOSE_CAPTION_0),
CmsVaadinUtils.getMessageText(org.opencms.ui.apps.Messages.GUI_EDITOR_CLOSE_TEXT_0),
new Runnable() {
public void run() {
exitInternal();
}
});
} else {
exitInternal();
}
}
/**
* Exits the editor without saving.
*/
void exitInternal() {
clear();
CmsEditor.openBackLink(m_backLink);
}
/**
* Called on content change.
*
* @param value the changed content value
*/
void onChange(String value) {
m_changed = true;
m_save.setEnabled(true);
m_saveAndExit.setEnabled(true);
}
/**
* Saves the current editor content.
*/
void save() {
try {
byte[] content = m_codeMirror.getValue().getBytes(m_file.getEncoding());
m_file.getFile().setContents(content);
A_CmsUI.getCmsObject().writeFile(m_file.getFile());
m_changed = false;
m_save.setEnabled(false);
m_saveAndExit.setEnabled(false);
} catch (Exception e) {
CmsErrorDialog.showErrorDialog(e);
}
}
/**
* Saves the current editor content and leaves the editor.
*/
void saveAndExit() {
save();
exit();
}
/**
* Returns the current editor settings.
*
* @return the current editor settings
*/
private EditorSettings getCurrentSettings() {
EditorSettings result = new EditorSettings();
result.m_closeBrackets = m_codeMirror.isCloseBrackets();
result.m_lineWrapping = m_codeMirror.isLineWrapping();
result.m_highlighting = m_codeMirror.isHighlighting();
result.m_tabsVisible = m_codeMirror.isTabsVisible();
result.m_fontSize = m_codeMirror.getFontSize();
return result;
}
}