001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.editors; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.types.CmsResourceTypeBinary; 033import org.opencms.file.types.CmsResourceTypeImage; 034import org.opencms.file.types.CmsResourceTypeJsp; 035import org.opencms.file.types.CmsResourceTypeXmlContent; 036import org.opencms.file.types.CmsResourceTypeXmlPage; 037import org.opencms.file.types.I_CmsResourceType; 038import org.opencms.i18n.CmsMessages; 039import org.opencms.json.JSONException; 040import org.opencms.json.JSONObject; 041import org.opencms.lock.CmsLockUtil.LockedFile; 042import org.opencms.main.CmsRuntimeException; 043import org.opencms.main.OpenCms; 044import org.opencms.ui.A_CmsUI; 045import org.opencms.ui.CmsVaadinUtils; 046import org.opencms.ui.FontOpenCms; 047import org.opencms.ui.apps.CmsAppWorkplaceUi; 048import org.opencms.ui.apps.CmsEditor; 049import org.opencms.ui.apps.I_CmsAppSettings; 050import org.opencms.ui.apps.I_CmsAppUIContext; 051import org.opencms.ui.apps.I_CmsHasShortcutActions; 052import org.opencms.ui.components.CmsConfirmationDialog; 053import org.opencms.ui.components.CmsErrorDialog; 054import org.opencms.ui.components.CmsToolBar; 055import org.opencms.ui.components.I_CmsWindowCloseListener; 056import org.opencms.ui.components.OpenCmsTheme; 057import org.opencms.ui.components.codemirror.CmsCodeMirror; 058import org.opencms.ui.components.codemirror.CmsCodeMirror.CodeMirrorLanguage; 059import org.opencms.xml.content.CmsXmlContent; 060 061import java.util.HashMap; 062import java.util.Map; 063 064import com.vaadin.event.Action; 065import com.vaadin.event.ShortcutAction; 066import com.vaadin.navigator.ViewChangeListener; 067import com.vaadin.ui.Button; 068import com.vaadin.ui.Button.ClickEvent; 069import com.vaadin.ui.Button.ClickListener; 070import com.vaadin.ui.UI; 071import com.vaadin.v7.data.Property.ValueChangeEvent; 072import com.vaadin.v7.data.Property.ValueChangeListener; 073import com.vaadin.v7.ui.ComboBox; 074 075/** 076 * The plain text editor.<p> 077 */ 078@SuppressWarnings("deprecation") 079public class CmsSourceEditor 080implements I_CmsEditor, I_CmsWindowCloseListener, ViewChangeListener, I_CmsHasShortcutActions { 081 082 /** 083 * Stores the editor settings.<p> 084 */ 085 public static class EditorSettings implements I_CmsAppSettings { 086 087 /** JSON key constant. */ 088 private static final String BRACKETS = "brackets"; 089 /** JSON key constant. */ 090 private static final String FONTSIZE = "fontsize"; 091 /** JSON key constant. */ 092 private static final String HIGHLIGHTING = "highlighting"; 093 /** JSON key constant. */ 094 private static final String TABS = "tabs"; 095 /** JSON key constant. */ 096 private static final String WRAPPING = "wrapping"; 097 098 /** The auto close brackets flag. */ 099 boolean m_closeBrackets = true; 100 101 /** The font size. */ 102 String m_fontSize = "16px"; 103 104 /** The highlighting flag. */ 105 boolean m_highlighting = true; 106 107 /** The line wrapping flag. */ 108 boolean m_lineWrapping; 109 110 /** The tab visibility flag. */ 111 boolean m_tabsVisible = true; 112 113 /** 114 * Returns the font size. 115 * @return the font size. 116 */ 117 public String getFontSize() { 118 119 return m_fontSize; 120 } 121 122 /** 123 * @see org.opencms.ui.apps.I_CmsAppSettings#getSettingsString() 124 */ 125 public String getSettingsString() { 126 127 JSONObject json = new JSONObject(); 128 try { 129 json.put(BRACKETS, m_closeBrackets); 130 json.put(HIGHLIGHTING, m_highlighting); 131 json.put(WRAPPING, m_lineWrapping); 132 json.put(FONTSIZE, m_fontSize); 133 json.put(TABS, m_tabsVisible); 134 } catch (JSONException e) { 135 // TODO Auto-generated catch block 136 e.printStackTrace(); 137 } 138 139 return json.toString(); 140 } 141 142 /** 143 * Returns a flag, indicating if automatically closing brackets is activated. 144 * @return a flag, indicating if automatically closing brackets is activated. 145 */ 146 public boolean isCloseBracketsActive() { 147 148 return m_closeBrackets; 149 } 150 151 /** 152 * Returns a flag, indicating if highlighting is activated. 153 * @return a flag, indicating if highlighting is activated. 154 */ 155 public boolean isHighlightingActive() { 156 157 return m_highlighting; 158 } 159 160 /** 161 * Returns a flag, indicating if line wrapping is activated. 162 * @return a flag, indicating if line wrapping is activated. 163 */ 164 public boolean isLineWrappingActive() { 165 166 return m_lineWrapping; 167 } 168 169 /** 170 * Returns a flag, indicating if tabs should be visible. 171 * @return a flag, indicating if tabs should be visible. 172 */ 173 public boolean isTabsVisibleActive() { 174 175 return m_tabsVisible; 176 } 177 178 /** 179 * @see org.opencms.ui.apps.I_CmsAppSettings#restoreSettings(java.lang.String) 180 */ 181 public void restoreSettings(String storedSettings) { 182 183 try { 184 JSONObject json = new JSONObject(storedSettings); 185 if (json.has(BRACKETS)) { 186 m_closeBrackets = json.getBoolean(BRACKETS); 187 } 188 if (json.has(HIGHLIGHTING)) { 189 m_highlighting = json.getBoolean(HIGHLIGHTING); 190 } 191 if (json.has(WRAPPING)) { 192 m_lineWrapping = json.getBoolean(WRAPPING); 193 } 194 if (json.has(TABS)) { 195 m_tabsVisible = json.getBoolean(TABS); 196 } 197 if (json.has(FONTSIZE)) { 198 m_fontSize = json.getString(FONTSIZE); 199 } 200 201 } catch (JSONException e) { 202 // LOG.error("Failed to restore file explorer settings from '" + storedSettings + "'", e); 203 } 204 } 205 } 206 207 /** Exit shortcut. */ 208 private static final Action ACTION_EXIT = new ShortcutAction( 209 "Ctrl+Shift+X", 210 ShortcutAction.KeyCode.X, 211 new int[] {ShortcutAction.ModifierKey.CTRL, ShortcutAction.ModifierKey.SHIFT}); 212 213 /** Exit shortcut, (using Apple CMD as modifier). */ 214 private static final Action ACTION_EXIT_CMD = new ShortcutAction( 215 "CMD+Shift+X", 216 ShortcutAction.KeyCode.X, 217 new int[] {ShortcutAction.ModifierKey.META, ShortcutAction.ModifierKey.SHIFT}); 218 219 /** Save shortcut. */ 220 private static final Action ACTION_SAVE = new ShortcutAction( 221 "Ctrl+S", 222 ShortcutAction.KeyCode.S, 223 new int[] {ShortcutAction.ModifierKey.CTRL}); 224 225 /** Save & Exit shortcut. */ 226 private static final Action ACTION_SAVE_AND_EXIT = new ShortcutAction( 227 "Ctrl+Shift+S", 228 ShortcutAction.KeyCode.S, 229 new int[] {ShortcutAction.ModifierKey.CTRL, ShortcutAction.ModifierKey.SHIFT}); 230 231 /** Save & Exit shortcut, (using Apple CMD as modifier). */ 232 private static final Action ACTION_SAVE_AND_EXIT_CMD = new ShortcutAction( 233 "CMD+Shift+S", 234 ShortcutAction.KeyCode.S, 235 new int[] {ShortcutAction.ModifierKey.META, ShortcutAction.ModifierKey.SHIFT}); 236 237 /** Save shortcut, (using Apple CMD as modifier). */ 238 private static final Action ACTION_SAVE_CMD = new ShortcutAction( 239 "CMD+S", 240 ShortcutAction.KeyCode.S, 241 new int[] {ShortcutAction.ModifierKey.META}); 242 243 /** The available font sizes. */ 244 private static final String[] FONT_SIZES = new String[] {"8px", "10px", "12px", "14px", "16px", "18px", "20px"}; 245 246 /** The serial version id. */ 247 private static final long serialVersionUID = 726920483145397926L; 248 249 /** The editor back link. */ 250 String m_backLink; 251 252 /** The code mirror instance. */ 253 CmsCodeMirror m_codeMirror; 254 255 /** The bundle editor shortcuts. */ 256 Map<Action, Runnable> m_shortcutActions; 257 258 /** The content changed flag. */ 259 private boolean m_changed; 260 261 /** The cleared flag. */ 262 private boolean m_cleared; 263 264 /** The exit button. */ 265 private Button m_exit; 266 267 /** The current file. */ 268 private LockedFile m_file; 269 270 /** The save button. */ 271 private Button m_save; 272 273 /** The save and exit button. */ 274 private Button m_saveAndExit; 275 276 /** 277 * Constructor.<p> 278 */ 279 public CmsSourceEditor() { 280 281 m_shortcutActions = new HashMap<Action, Runnable>(); 282 Runnable save = new Runnable() { 283 284 public void run() { 285 286 save(); 287 } 288 }; 289 m_shortcutActions.put(ACTION_SAVE, save); 290 m_shortcutActions.put(ACTION_SAVE_CMD, save); 291 Runnable saveExit = new Runnable() { 292 293 public void run() { 294 295 saveAndExit(); 296 } 297 }; 298 m_shortcutActions.put(ACTION_SAVE_AND_EXIT, saveExit); 299 m_shortcutActions.put(ACTION_SAVE_AND_EXIT_CMD, saveExit); 300 Runnable exit = new Runnable() { 301 302 public void run() { 303 304 exit(); 305 } 306 }; 307 m_shortcutActions.put(ACTION_EXIT, exit); 308 m_shortcutActions.put(ACTION_EXIT_CMD, exit); 309 } 310 311 /** 312 * @see com.vaadin.navigator.ViewChangeListener#afterViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent) 313 */ 314 public void afterViewChange(ViewChangeEvent event) { 315 316 // nothing to do 317 } 318 319 /** 320 * @see com.vaadin.navigator.ViewChangeListener#beforeViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent) 321 */ 322 public boolean beforeViewChange(final ViewChangeEvent event) { 323 324 if (m_changed) { 325 CmsConfirmationDialog.show( 326 CmsVaadinUtils.getMessageText(org.opencms.ui.apps.Messages.GUI_EDITOR_CLOSE_CAPTION_0), 327 CmsVaadinUtils.getMessageText(org.opencms.ui.apps.Messages.GUI_EDITOR_CLOSE_TEXT_0), 328 new Runnable() { 329 330 public void run() { 331 332 clear(); 333 event.getNavigator().navigateTo(event.getViewName()); 334 } 335 }); 336 return false; 337 } 338 if (!m_cleared) { 339 clear(); 340 } 341 return true; 342 } 343 344 /** 345 * Returns the syntax highlighting type for the currently edited resource.<p> 346 * 347 * @param resource the resource to edit 348 * 349 * @return the syntax highlighting type 350 */ 351 public CodeMirrorLanguage getHighlightMode(CmsResource resource) { 352 353 if (resource != null) { 354 // determine resource type 355 int type = resource.getTypeId(); 356 if (CmsResourceTypeJsp.isJspTypeId(type)) { 357 // JSP file 358 return CodeMirrorLanguage.JSP; 359 } 360 if (CmsResourceTypeXmlContent.isXmlContent(resource) || CmsResourceTypeXmlPage.isXmlPage(resource)) { 361 // XML content file or XML page file 362 return CodeMirrorLanguage.XML; 363 } 364 // all other files will be matched according to their suffix 365 int dotIndex = resource.getName().lastIndexOf('.'); 366 if (dotIndex != -1) { 367 String suffix = resource.getName().substring(dotIndex + 1).toLowerCase(); 368 for (CodeMirrorLanguage lang : CodeMirrorLanguage.values()) { 369 if (lang.isSupportedFileType(suffix)) { 370 return lang; 371 } 372 } 373 } 374 } 375 // return HTML type as default 376 return CodeMirrorLanguage.HTML; 377 } 378 379 /** 380 * @see org.opencms.ui.editors.I_CmsEditor#getPriority() 381 */ 382 public int getPriority() { 383 384 return 10; 385 } 386 387 /** 388 * @see org.opencms.ui.apps.I_CmsHasShortcutActions#getShortcutActions() 389 */ 390 public Map<Action, Runnable> getShortcutActions() { 391 392 return m_shortcutActions; 393 } 394 395 /** 396 * @see org.opencms.ui.editors.I_CmsEditor#initUI(org.opencms.ui.apps.I_CmsAppUIContext, org.opencms.file.CmsResource, java.lang.String, java.util.Map) 397 */ 398 public void initUI(I_CmsAppUIContext context, CmsResource resource, String backLink, Map<String, String> params) { 399 400 CmsObject cms = A_CmsUI.getCmsObject(); 401 if (OpenCms.getADEManager().isEditorRestricted(cms, resource)) { 402 throw new CmsRuntimeException( 403 org.opencms.ade.contenteditor.Messages.get().container( 404 org.opencms.ade.contenteditor.Messages.ERR_EDITOR_RESTRICTED_0)); 405 } 406 CmsMessages messages = Messages.get().getBundle(UI.getCurrent().getLocale()); 407 context.showInfoArea(false); 408 context.setAppTitle(messages.key(Messages.GUI_SOURCE_EDITOR_TITLE_0)); 409 CmsAppWorkplaceUi.setWindowTitle( 410 CmsVaadinUtils.getMessageText( 411 org.opencms.ui.apps.Messages.GUI_CONTENT_EDITOR_TITLE_2, 412 resource.getName(), 413 CmsResource.getParentFolder(A_CmsUI.getCmsObject().getSitePath(resource)))); 414 m_backLink = backLink; 415 m_codeMirror = new CmsCodeMirror(); 416 m_codeMirror.setSizeFull(); 417 context.setAppContent(m_codeMirror); 418 context.enableDefaultToolbarButtons(false); 419 m_saveAndExit = CmsToolBar.createButton( 420 FontOpenCms.SAVE_EXIT, 421 messages.key(Messages.GUI_BUTTON_SAVE_AND_EXIT_0), 422 true); 423 m_saveAndExit.addClickListener(new ClickListener() { 424 425 private static final long serialVersionUID = 1L; 426 427 public void buttonClick(ClickEvent event) { 428 429 saveAndExit(); 430 } 431 432 }); 433 m_saveAndExit.setEnabled(false); 434 context.addToolbarButton(m_saveAndExit); 435 436 m_save = CmsToolBar.createButton(FontOpenCms.SAVE, messages.key(Messages.GUI_BUTTON_SAVE_0), true); 437 m_save.addClickListener(new ClickListener() { 438 439 private static final long serialVersionUID = 1L; 440 441 public void buttonClick(ClickEvent event) { 442 443 save(); 444 } 445 446 }); 447 m_save.setEnabled(false); 448 context.addToolbarButton(m_save); 449 450 Button undo = CmsToolBar.createButton(FontOpenCms.UNDO, messages.key(Messages.GUI_BUTTON_UNDO_0), true); 451 context.addToolbarButton(undo); 452 453 Button redo = CmsToolBar.createButton(FontOpenCms.REDO, messages.key(Messages.GUI_BUTTON_REDO_0), true); 454 context.addToolbarButton(redo); 455 456 m_codeMirror.registerUndoRedo(undo, redo); 457 458 Button search = CmsToolBar.createButton(FontOpenCms.SEARCH, messages.key(Messages.GUI_BUTTON_SEARCH_0), true); 459 context.addToolbarButton(search); 460 461 Button replace = CmsToolBar.createButton( 462 FontOpenCms.SEARCH_REPLACE, 463 messages.key(Messages.GUI_BUTTON_REPLACE_0), 464 true); 465 context.addToolbarButton(replace); 466 467 m_codeMirror.registerSearchReplace(search, replace); 468 469 EditorSettings settings; 470 try { 471 settings = OpenCms.getWorkplaceAppManager().getAppSettings(A_CmsUI.getCmsObject(), EditorSettings.class); 472 473 } catch (Exception e) { 474 settings = new EditorSettings(); 475 } 476 477 final Button toggleHighlight = CmsToolBar.createButton( 478 FontOpenCms.HIGHLIGHT, 479 messages.key(Messages.GUI_BUTTON_TOGGLE_HIGHLIGHTING_0)); 480 toggleHighlight.addClickListener(new ClickListener() { 481 482 private static final long serialVersionUID = 1L; 483 484 public void buttonClick(ClickEvent event) { 485 486 Button b = event.getButton(); 487 boolean pressed = b.getStyleName().contains(OpenCmsTheme.BUTTON_PRESSED); 488 if (pressed) { 489 b.removeStyleName(OpenCmsTheme.BUTTON_PRESSED); 490 } else { 491 b.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 492 } 493 m_codeMirror.setHighlighting(!pressed); 494 } 495 496 }); 497 if (settings.m_highlighting) { 498 m_codeMirror.setHighlighting(true); 499 toggleHighlight.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 500 } else { 501 m_codeMirror.setHighlighting(false); 502 } 503 context.addToolbarButtonRight(toggleHighlight); 504 505 final Button toggleLineWrap = CmsToolBar.createButton( 506 FontOpenCms.WRAP_LINES, 507 messages.key(Messages.GUI_BUTTON_TOGGLE_LINE_WRAPPING_0)); 508 toggleLineWrap.addClickListener(new ClickListener() { 509 510 private static final long serialVersionUID = 1L; 511 512 public void buttonClick(ClickEvent event) { 513 514 Button b = event.getButton(); 515 boolean pressed = b.getStyleName().contains(OpenCmsTheme.BUTTON_PRESSED); 516 if (pressed) { 517 b.removeStyleName(OpenCmsTheme.BUTTON_PRESSED); 518 } else { 519 b.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 520 } 521 m_codeMirror.setLineWrapping(!pressed); 522 } 523 524 }); 525 if (settings.m_lineWrapping) { 526 m_codeMirror.setLineWrapping(true); 527 toggleLineWrap.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 528 } else { 529 m_codeMirror.setLineWrapping(false); 530 } 531 context.addToolbarButtonRight(toggleLineWrap); 532 533 final Button toggleBrackets = CmsToolBar.createButton( 534 FontOpenCms.BRACKETS, 535 messages.key(Messages.GUI_BUTTON_TOBBLE_BRACKET_AUTOCLOSE_0)); 536 toggleBrackets.addClickListener(new ClickListener() { 537 538 private static final long serialVersionUID = 1L; 539 540 public void buttonClick(ClickEvent event) { 541 542 Button b = event.getButton(); 543 boolean pressed = b.getStyleName().contains(OpenCmsTheme.BUTTON_PRESSED); 544 if (pressed) { 545 b.removeStyleName(OpenCmsTheme.BUTTON_PRESSED); 546 } else { 547 b.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 548 } 549 m_codeMirror.setCloseBrackets(!pressed); 550 } 551 552 }); 553 if (settings.m_closeBrackets) { 554 m_codeMirror.setCloseBrackets(true); 555 toggleBrackets.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 556 } else { 557 m_codeMirror.setCloseBrackets(false); 558 } 559 context.addToolbarButtonRight(toggleBrackets); 560 561 final Button toggleTabs = CmsToolBar.createButton( 562 FontOpenCms.INVISIBLE_CHARS, 563 messages.key(Messages.GUI_BUTTON_TOGGLE_TAB_VISIBILITY_0)); 564 toggleTabs.addClickListener(new ClickListener() { 565 566 private static final long serialVersionUID = 1L; 567 568 public void buttonClick(ClickEvent event) { 569 570 Button b = event.getButton(); 571 boolean pressed = b.getStyleName().contains(OpenCmsTheme.BUTTON_PRESSED); 572 if (pressed) { 573 b.removeStyleName(OpenCmsTheme.BUTTON_PRESSED); 574 } else { 575 b.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 576 } 577 m_codeMirror.setTabsVisible(!pressed); 578 } 579 580 }); 581 if (settings.m_tabsVisible) { 582 m_codeMirror.setTabsVisible(true); 583 toggleTabs.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 584 } else { 585 m_codeMirror.setTabsVisible(false); 586 } 587 context.addToolbarButtonRight(toggleTabs); 588 589 ComboBox modeSelect = new ComboBox(); 590 modeSelect.setWidth("115px"); 591 modeSelect.addStyleName(OpenCmsTheme.TOOLBAR_FIELD); 592 modeSelect.addStyleName(OpenCmsTheme.REQUIRED_BUTTON); 593 modeSelect.setNullSelectionAllowed(false); 594 modeSelect.setImmediate(true); 595 modeSelect.setNewItemsAllowed(false); 596 for (CodeMirrorLanguage lang : CodeMirrorLanguage.values()) { 597 modeSelect.addItem(lang); 598 modeSelect.setItemCaption(lang, lang.name()); 599 } 600 CodeMirrorLanguage lang = getHighlightMode(resource); 601 modeSelect.setValue(lang); 602 m_codeMirror.setLanguage(lang); 603 modeSelect.addValueChangeListener(new ValueChangeListener() { 604 605 private static final long serialVersionUID = 1L; 606 607 public void valueChange(ValueChangeEvent event) { 608 609 m_codeMirror.setLanguage((CodeMirrorLanguage)event.getProperty().getValue()); 610 } 611 }); 612 context.addToolbarButtonRight(modeSelect); 613 614 ComboBox fontSizeSelect = new ComboBox(); 615 fontSizeSelect.setWidth("75px"); 616 fontSizeSelect.addStyleName(OpenCmsTheme.TOOLBAR_FIELD); 617 fontSizeSelect.addStyleName(OpenCmsTheme.REQUIRED_BUTTON); 618 fontSizeSelect.setNullSelectionAllowed(false); 619 fontSizeSelect.setImmediate(true); 620 fontSizeSelect.setNewItemsAllowed(false); 621 for (int i = 0; i < FONT_SIZES.length; i++) { 622 fontSizeSelect.addItem(FONT_SIZES[i]); 623 } 624 fontSizeSelect.setValue(settings.m_fontSize); 625 fontSizeSelect.addValueChangeListener(new ValueChangeListener() { 626 627 private static final long serialVersionUID = 1L; 628 629 public void valueChange(ValueChangeEvent event) { 630 631 m_codeMirror.setFontSize((String)event.getProperty().getValue()); 632 } 633 }); 634 context.addToolbarButtonRight(fontSizeSelect); 635 m_codeMirror.setFontSize(settings.m_fontSize); 636 637 m_exit = CmsToolBar.createButton(FontOpenCms.EXIT, messages.key(Messages.GUI_BUTTON_CANCEL_0), true); 638 m_exit.addClickListener(new ClickListener() { 639 640 private static final long serialVersionUID = 1L; 641 642 public void buttonClick(ClickEvent event) { 643 644 exit(); 645 } 646 647 }); 648 context.addToolbarButtonRight(m_exit); 649 650 try { 651 m_file = LockedFile.lockResource(A_CmsUI.getCmsObject(), resource); 652 String content = new String(m_file.getFile().getContents(), m_file.getEncoding()); 653 m_codeMirror.setValue(content); 654 } catch (Exception e) { 655 CmsErrorDialog.showErrorDialog(e); 656 } 657 m_codeMirror.addValueChangeListener(new ValueChangeListener() { 658 659 private static final long serialVersionUID = 1L; 660 661 public void valueChange(ValueChangeEvent event) { 662 663 onChange((String)event.getProperty().getValue()); 664 } 665 }); 666 } 667 668 /** 669 * @see org.opencms.ui.editors.I_CmsEditor#matchesResource(org.opencms.file.CmsObject, org.opencms.file.CmsResource, boolean) 670 */ 671 public boolean matchesResource(CmsObject cms, CmsResource resource, boolean plainText) { 672 673 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(resource); 674 return matchesType(type, plainText); 675 } 676 677 /** 678 * @see org.opencms.ui.editors.I_CmsEditor#matchesType(org.opencms.file.types.I_CmsResourceType, boolean) 679 */ 680 public boolean matchesType(I_CmsResourceType type, boolean plainText) { 681 682 return !((type instanceof CmsResourceTypeBinary) || (type instanceof CmsResourceTypeImage)); 683 } 684 685 /** 686 * @see org.opencms.ui.editors.I_CmsEditor#newInstance() 687 */ 688 public I_CmsEditor newInstance() { 689 690 return new CmsSourceEditor(); 691 } 692 693 /** 694 * @see org.opencms.ui.components.I_CmsWindowCloseListener#onWindowClose() 695 */ 696 public void onWindowClose() { 697 698 clear(); 699 } 700 701 /** 702 * Unlocks the edited file before leaving the editor.<p> 703 */ 704 void clear() { 705 706 m_cleared = true; 707 m_changed = false; 708 m_file.tryUnlock(); 709 OpenCms.getWorkplaceAppManager().storeAppSettings( 710 A_CmsUI.getCmsObject(), 711 EditorSettings.class, 712 getCurrentSettings()); 713 } 714 715 /** 716 * Exits the editor without saving.<p> 717 * Will ask to confirm exit on changed contents.<p> 718 */ 719 void exit() { 720 721 if (m_changed) { 722 CmsConfirmationDialog.show( 723 CmsVaadinUtils.getMessageText(org.opencms.ui.apps.Messages.GUI_EDITOR_CLOSE_CAPTION_0), 724 CmsVaadinUtils.getMessageText(org.opencms.ui.apps.Messages.GUI_EDITOR_CLOSE_TEXT_0), 725 new Runnable() { 726 727 public void run() { 728 729 exitInternal(); 730 } 731 }); 732 } else { 733 exitInternal(); 734 } 735 736 } 737 738 /** 739 * Exits the editor without saving.<p> 740 */ 741 void exitInternal() { 742 743 clear(); 744 CmsEditor.openBackLink(m_backLink); 745 } 746 747 /** 748 * Called on content change.<p> 749 * 750 * @param value the changed content value 751 */ 752 void onChange(String value) { 753 754 m_changed = true; 755 m_save.setEnabled(true); 756 m_saveAndExit.setEnabled(true); 757 } 758 759 /** 760 * Saves the current editor content.<p> 761 */ 762 void save() { 763 764 CmsObject cms = A_CmsUI.getCmsObject(); 765 try { 766 byte[] content = m_codeMirror.getValue().getBytes(m_file.getEncoding()); 767 m_file.getFile().setContents(content); 768 cms.getRequestContext().setAttribute(CmsXmlContent.AUTO_CORRECTION_ATTRIBUTE, Boolean.TRUE); 769 cms.writeFile(m_file.getFile()); 770 m_changed = false; 771 m_save.setEnabled(false); 772 m_saveAndExit.setEnabled(false); 773 } catch (Exception e) { 774 CmsErrorDialog.showErrorDialog(e); 775 } finally { 776 cms.getRequestContext().removeAttribute(CmsXmlContent.AUTO_CORRECTION_ATTRIBUTE); 777 } 778 } 779 780 /** 781 * Saves the current editor content and leaves the editor.<p> 782 */ 783 void saveAndExit() { 784 785 save(); 786 exit(); 787 } 788 789 /** 790 * Returns the current editor settings.<p> 791 * 792 * @return the current editor settings 793 */ 794 private EditorSettings getCurrentSettings() { 795 796 EditorSettings result = new EditorSettings(); 797 result.m_closeBrackets = m_codeMirror.isCloseBrackets(); 798 result.m_lineWrapping = m_codeMirror.isLineWrapping(); 799 result.m_highlighting = m_codeMirror.isHighlighting(); 800 result.m_tabsVisible = m_codeMirror.isTabsVisible(); 801 result.m_fontSize = m_codeMirror.getFontSize(); 802 return result; 803 } 804}