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.components.codemirror; 029 030import org.opencms.i18n.CmsMessages; 031import org.opencms.json.JSONObject; 032import org.opencms.ui.components.Messages; 033import org.opencms.workplace.CmsWorkplace; 034 035import java.lang.reflect.Method; 036import java.util.Arrays; 037import java.util.HashSet; 038import java.util.Set; 039 040import com.vaadin.annotations.JavaScript; 041import com.vaadin.event.FieldEvents; 042import com.vaadin.shared.ui.JavaScriptComponentState; 043import com.vaadin.ui.AbstractJavaScriptComponent; 044import com.vaadin.ui.Button; 045import com.vaadin.ui.Component; 046import com.vaadin.ui.JavaScriptFunction; 047import com.vaadin.ui.UI; 048import com.vaadin.v7.data.Property; 049 050import elemental.json.JsonArray; 051 052/** 053 * Code mirror input component.<p> 054 */ 055@JavaScript({"codemirror-connector.js"}) 056public class CmsCodeMirror extends AbstractJavaScriptComponent 057implements Property<String>, Property.ValueChangeNotifier { 058 059 /** The available editor languages. */ 060 public enum CodeMirrorLanguage { 061 /** CSS. */ 062 CSS("css", new String[] {"css"}), 063 /** HTML. */ 064 HTML("text/html", new String[] {"html", "htm", "xhtml"}), 065 /** JAVA. */ 066 JAVA("text/x-java", new String[] {"java"}), 067 /** JavaScript. */ 068 JAVASCRIPT("javascript", new String[] {"js"}), 069 /** JSP. */ 070 JSP("application/x-jsp", new String[] {"jsp"}), 071 /** XML. */ 072 XML("application/xml", new String[] {"xml", "xsd"}); 073 074 /** The language name. */ 075 private final String m_languageName; 076 077 /** The supported file types. */ 078 private Set<String> m_supportedFileTypes; 079 080 /** 081 * Constructor.<p> 082 * 083 * @param languageName the language name 084 * @param fileTypes the file types suported by this language 085 */ 086 private CodeMirrorLanguage(String languageName, String[] fileTypes) { 087 088 m_languageName = languageName; 089 m_supportedFileTypes = new HashSet<String>(Arrays.asList(fileTypes)); 090 } 091 092 /** 093 * Returns the language name.<p> 094 * 095 * @return the language name 096 */ 097 public String getLanguageName() { 098 099 return m_languageName; 100 } 101 102 /** 103 * Returns whether the given file ending is a supported file type.<p> 104 * 105 * @param fileNameSuffix the file name suffix 106 * 107 * @return <code>true</code> in case the file type is supported 108 */ 109 public boolean isSupportedFileType(String fileNameSuffix) { 110 111 return m_supportedFileTypes.contains(fileNameSuffix); 112 } 113 114 /** 115 * @see java.lang.Enum#toString() 116 */ 117 @Override 118 public String toString() { 119 120 return m_languageName; 121 } 122 } 123 124 /** 125 * The editor state.<p> 126 */ 127 public static class CodeMirrorState extends JavaScriptComponentState { 128 129 /** The serial version id. */ 130 private static final long serialVersionUID = 1L; 131 132 /** The close brackets flag. */ 133 public boolean m_closeBrackets = true; 134 135 /** The content value. */ 136 public String m_contentValue = "//please start to code"; 137 138 /** The required CSS stylesheet URIs. */ 139 public String[] m_cssURIs; 140 141 /** The search and replace enabled flag. */ 142 public boolean m_enableSearchReplace; 143 144 /** The undo redo enabled flag. */ 145 public boolean m_enableUndoRedo; 146 147 /** The font size. */ 148 public String m_fontSize = "14px"; 149 150 /** The height. */ 151 public String m_height = "600"; 152 153 /** The highlighting flag. */ 154 public boolean m_highlighting = true; 155 156 /** The editor instance id. */ 157 public long m_id; 158 159 /** The line wrapping flag. */ 160 public boolean m_lineWrapping = true; 161 162 /** The language mode. */ 163 public String m_mode = CodeMirrorLanguage.JAVASCRIPT.toString(); 164 165 /** The required JavaScript resource URIs. */ 166 public String[] m_scriptURIs; 167 168 /** The short cut descriptions HTML. */ 169 public String m_shortcutsMessage; 170 171 /** The tab visibility flag. */ 172 public boolean m_tabsVisible = true; 173 174 /** The theme. */ 175 public String m_theme = CodeMirrorTheme.ECLIPSE.toString(); 176 177 /** The width. */ 178 public String m_width = "600"; 179 180 /** The code mirror localization. */ 181 public String m_messages; 182 } 183 184 /** The available editor themes. */ 185 public enum CodeMirrorTheme { 186 /** Theme. */ 187 AMBIANCE("ambiance"), 188 /** Theme. */ 189 BASE16_DARK("base16-dark"), 190 /** Theme. */ 191 BASE16_LIGHT("base16-light"), 192 /** Theme. */ 193 BLACKBOARD("blackboard"), 194 /** Theme. */ 195 COBALT("cobalt"), 196 /** Theme. */ 197 DAY_3024("3024-day"), 198 /** Theme. */ 199 DEFAULT("default"), 200 /** Theme. */ 201 ECLIPSE("eclipse"), 202 /** Theme. */ 203 ELEGANT("elegant"), 204 /** Theme. */ 205 ERLANG_DARK("erlang-dark"), 206 /** Theme. */ 207 ERLANG_LIGHT("erlang-light"), 208 /** Theme. */ 209 LESSER_DARK("lesser-dark"), 210 /** Theme. */ 211 MBO("mbo"), 212 /** Theme. */ 213 MDN_LIKE("mdn-like"), 214 /** Theme. */ 215 MIDNIGHT("midnight"), 216 /** Theme. */ 217 MONOKAI("monokai"), 218 /** Theme. */ 219 NEAT("neat"), 220 /** Theme. */ 221 NIGHT("night"), 222 /** Theme. */ 223 NIGHT_3024("3024-night"), 224 /** Theme. */ 225 PARAISO_DARK("paraiso-dark"), 226 /** Theme. */ 227 PARAISO_LIGHT("paraiso-light"), 228 /** Theme. */ 229 PASTEL_ON_DARK("paster-on-dark"), 230 /** Theme. */ 231 RUBYBLUE("rubyblue"), 232 /** Theme. */ 233 SOLARIZED_DARK("solarized dark"), 234 /** Theme. */ 235 SOLARIZED_LIGHT("solarized light"), 236 /** Theme. */ 237 THE_MATRIX("the-matrix"), 238 /** Theme. */ 239 TOMORROW_NIGHT_EIGHTIES("tomorrow-night-eighties"), 240 /** Theme. */ 241 TWILIGHT("twilight"), 242 /** Theme. */ 243 VIBRANT_INK("vibrant-ink"), 244 /** Theme. */ 245 XQ_DARK("xq-dark"), 246 /** Theme. */ 247 XQ_LIGHT("xq-light"); 248 249 /** The theme name. */ 250 private final String m_themeName; 251 252 /** 253 * Constructor.<p> 254 * 255 * @param themeName the theme name 256 */ 257 private CodeMirrorTheme(String themeName) { 258 259 this.m_themeName = themeName; 260 } 261 262 /** 263 * Returns the theme name.<p> 264 * 265 * @return the theme name 266 */ 267 public String getThemeName() { 268 269 return m_themeName; 270 } 271 272 /** 273 * @see java.lang.Enum#toString() 274 */ 275 @Override 276 public String toString() { 277 278 return m_themeName; 279 } 280 281 } 282 283 /** 284 * The code mirror change event.<p> 285 */ 286 public static class ValueChangeEvent extends Component.Event implements Property.ValueChangeEvent { 287 288 /** The serial version id. */ 289 private static final long serialVersionUID = 1L; 290 291 /** 292 * Constructs a new event object with the specified source field object. 293 * 294 * @param eventSource the field that caused the event. 295 */ 296 public ValueChangeEvent(CmsCodeMirror eventSource) { 297 298 super(eventSource); 299 } 300 301 /** 302 * Gets the Property which triggered the event. 303 * 304 * @return the Source Property of the event. 305 */ 306 @Override 307 public Property getProperty() { 308 309 return (Property<?>)getSource(); 310 } 311 } 312 313 /** The blur method. */ 314 private static final Method BLUR_METHOD; 315 316 /** The required CSS stylesheet URIs. */ 317 private static String[] CSS_URIS; 318 319 /** The HTML id prefix. */ 320 private static final String HTML_ID_PREFIX = "cm-addon-"; 321 322 /** The required JavaScript resource URIs. */ 323 private static String[] JAVASCRIPT_URIS; 324 325 /** The code mirror component count, used as HTML ids. */ 326 private static long m_componentCount; 327 328 /** The serial version id. */ 329 private static final long serialVersionUID = -4921119175861329688L; 330 331 /** Them value change method. */ 332 private static final Method VALUE_CHANGE_METHOD; 333 334 static { 335 try { 336 VALUE_CHANGE_METHOD = Property.ValueChangeListener.class.getDeclaredMethod( 337 "valueChange", 338 new Class[] {Property.ValueChangeEvent.class}); 339 } catch (final java.lang.NoSuchMethodException e) { 340 // This should never happen 341 throw new java.lang.RuntimeException("Internal error finding methods in ValueChangeListener"); 342 } 343 344 try { 345 BLUR_METHOD = FieldEvents.BlurListener.class.getDeclaredMethod( 346 "blur", 347 new Class[] {FieldEvents.BlurEvent.class}); 348 } catch (final java.lang.NoSuchMethodException e) { 349 // This should never happen 350 throw new java.lang.RuntimeException("Internal error finding methods in ValueChangeListener"); 351 } 352 } 353 354 /** The current content value. */ 355 private String m_codeValue; 356 357 /** The component id. */ 358 private final long m_componentId; 359 360 /** 361 * Constructor.<p> 362 */ 363 public CmsCodeMirror() { 364 365 m_componentId = m_componentCount; 366 m_componentCount++; 367 m_codeValue = ""; 368 getState().m_id = m_componentId; 369 getState().m_contentValue = m_codeValue; 370 CmsMessages messages = Messages.get().getBundle(UI.getCurrent().getLocale()); 371 getState().m_shortcutsMessage = getShortcutMessages(messages); 372 getState().m_messages = getLocalizationMessages(messages); 373 374 if (CSS_URIS == null) { 375 CSS_URIS = new String[] { 376 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/lib/codemirror.css"), 377 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/theme/eclipse.css"), 378 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/dialog/dialog.css"), 379 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/hint/show-hint.css")}; 380 } 381 getState().m_cssURIs = CSS_URIS; 382 if (JAVASCRIPT_URIS == null) { 383 JAVASCRIPT_URIS = new String[] { 384 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/lib/codemirror.js"), 385 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/dialog/dialog.js"), 386 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/search/searchcursor.js"), 387 CmsWorkplace.getStaticResourceUri("/editors/codemirror/js/search.js"), 388 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/edit/closebrackets.js"), 389 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/edit/closetag.js"), 390 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/edit/matchbrackets.js"), 391 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/hint/show-hint.js"), 392 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/hint/html-hint.js"), 393 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/hint/javascript-hint.js"), 394 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/hint/xml-hint.js"), 395 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/fold/foldcode.js"), 396 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/fold/brace-fold.js"), 397 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/fold/xml-fold.js"), 398 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/comment/comment.js"), 399 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/addon/selection/active-line.js"), 400 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/mode/css/css.js"), 401 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/mode/xml/xml.js"), 402 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/mode/clike/clike.js"), 403 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/mode/javascript/javascript.js"), 404 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/mode/css/css.js"), 405 CmsWorkplace.getStaticResourceUri("/editors/codemirror/dist/mode/htmlmixed/htmlmixed.js"), 406 CmsWorkplace.getStaticResourceUri("/editors/codemirror/js/htmlembedded_modified.js")}; 407 } 408 getState().m_scriptURIs = JAVASCRIPT_URIS; 409 410 addFunction("onBlur", new JavaScriptFunction() { 411 412 private static final long serialVersionUID = 1L; 413 414 @Override 415 public void call(JsonArray arguments) { 416 417 onBlur(arguments.getString(0)); 418 } 419 }); 420 addFunction("onChange", new JavaScriptFunction() { 421 422 private static final long serialVersionUID = 1L; 423 424 @Override 425 public void call(JsonArray arguments) { 426 427 onChange(arguments.getString(0)); 428 } 429 }); 430 addStyleName("o-codemirror"); 431 } 432 433 /** 434 * Adds a blur listener.<p> 435 * 436 * @param listener the blur listener 437 */ 438 public void addBlurListener(FieldEvents.BlurListener listener) { 439 440 addListener(FieldEvents.BlurEvent.class, listener, BLUR_METHOD); 441 markAsDirty(); 442 } 443 444 /** 445 * @see com.vaadin.v7.data.Property.ValueChangeNotifier#addListener(com.vaadin.v7.data.Property.ValueChangeListener) 446 * @deprecated use {@link #addValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener)} 447 */ 448 @Deprecated 449 public void addListener(com.vaadin.v7.data.Property.ValueChangeListener listener) { 450 451 addValueChangeListener(listener); 452 } 453 454 /** 455 * @see com.vaadin.v7.data.Property.ValueChangeNotifier#addValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener) 456 */ 457 public void addValueChangeListener(Property.ValueChangeListener listener) { 458 459 addListener(Property.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); 460 // ensure "automatic immediate handling" works 461 markAsDirty(); 462 } 463 464 /** 465 * Returns the font size.<p> 466 * 467 * @return the font size 468 */ 469 public String getFontSize() { 470 471 return getState().m_fontSize; 472 } 473 474 /** 475 * @see com.vaadin.v7.data.Property#getType() 476 */ 477 public Class<? extends String> getType() { 478 479 return String.class; 480 } 481 482 /** 483 * Returns the current editor content value.<p> 484 * 485 * @return the editor content value 486 */ 487 public String getValue() { 488 489 return m_codeValue; 490 } 491 492 /** 493 * Returns whether auto close brackets is active.<p> 494 * 495 * @return <code>true</code> if auto close brackets is active 496 */ 497 public boolean isCloseBrackets() { 498 499 return getState().m_closeBrackets; 500 } 501 502 /** 503 * Returns whether highlighting is active.<p> 504 * 505 * @return <code>true</code> if highlighting is active 506 */ 507 public boolean isHighlighting() { 508 509 return getState().m_highlighting; 510 } 511 512 /** 513 * Returns whether line wrapping is active.<p> 514 * 515 * @return <code>true</code> if line wrapping is active 516 */ 517 public boolean isLineWrapping() { 518 519 return getState().m_lineWrapping; 520 } 521 522 /** 523 * @see com.vaadin.ui.AbstractComponent#isReadOnly() 524 */ 525 @Override 526 public boolean isReadOnly() { 527 528 return super.isReadOnly(); 529 } 530 531 /** 532 * Returns whether tabs are visible.<p> 533 * 534 * @return <code>true</code> if tabs are visible 535 */ 536 public boolean isTabsVisible() { 537 538 return getState().m_tabsVisible; 539 } 540 541 /** 542 * Registers the given buttons as the search and replace buttons.<p> 543 * 544 * @param search the search button 545 * @param replace the replace button 546 */ 547 public void registerSearchReplace(Button search, Button replace) { 548 549 if (getState().m_enableSearchReplace) { 550 throw new RuntimeException("Search/replace already registered."); 551 } 552 search.setId(HTML_ID_PREFIX + m_componentId + "-search"); 553 replace.setId(HTML_ID_PREFIX + m_componentId + "-replace"); 554 getState().m_enableSearchReplace = true; 555 markAsDirty(); 556 } 557 558 /** 559 * Registers the given buttons as undo redo buttons.<p> 560 * 561 * @param undo the undo button 562 * @param redo the redo button 563 */ 564 public void registerUndoRedo(Button undo, Button redo) { 565 566 if (getState().m_enableUndoRedo) { 567 throw new RuntimeException("Undo/redo already registered."); 568 } 569 undo.setId(HTML_ID_PREFIX + m_componentId + "-undo"); 570 redo.setId(HTML_ID_PREFIX + m_componentId + "-redo"); 571 getState().m_enableUndoRedo = true; 572 markAsDirty(); 573 } 574 575 /** 576 * Removes the given blur listener.<p> 577 * 578 * @param listener the listener to remove 579 */ 580 public void removeBlurListener(FieldEvents.BlurNotifier listener) { 581 582 removeListener(FieldEvents.BlurEvent.class, listener, BLUR_METHOD); 583 // ensure "automatic immediate handling" works 584 markAsDirty(); 585 } 586 587 /** 588 * @see com.vaadin.v7.data.Property.ValueChangeNotifier#removeListener(com.vaadin.v7.data.Property.ValueChangeListener) 589 * @deprecated use {@link #removeValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener)} 590 */ 591 @Deprecated 592 public void removeListener(com.vaadin.v7.data.Property.ValueChangeListener listener) { 593 594 removeValueChangeListener(listener); 595 } 596 597 /** 598 * @see com.vaadin.v7.data.Property.ValueChangeNotifier#removeValueChangeListener(com.vaadin.v7.data.Property.ValueChangeListener) 599 */ 600 public void removeValueChangeListener(Property.ValueChangeListener listener) { 601 602 removeListener(Property.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); 603 markAsDirty(); 604 } 605 606 /** 607 * Sets the auto close brackets feature enabled.<p> 608 * 609 * @param closeBrackets <code>true</code> to auto close brackets 610 */ 611 public void setCloseBrackets(boolean closeBrackets) { 612 613 getState().m_closeBrackets = closeBrackets; 614 markAsDirty(); 615 } 616 617 /** 618 * Sets the editor font size.<p> 619 * 620 * @param fontSize the editor font size 621 */ 622 public void setFontSize(String fontSize) { 623 624 getState().m_fontSize = fontSize; 625 markAsDirty(); 626 } 627 628 /** 629 * @see com.vaadin.ui.AbstractComponent#setHeight(float, com.vaadin.server.Sizeable.Unit) 630 */ 631 @Override 632 public void setHeight(float height, Unit unit) { 633 634 super.setHeight(height, unit); 635 getState().m_height = height + unit.getSymbol(); 636 markAsDirty(); 637 } 638 639 /** 640 * @see com.vaadin.ui.AbstractComponent#setHeight(java.lang.String) 641 */ 642 @Override 643 public void setHeight(String height) { 644 645 super.setHeight(height); 646 getState().m_height = height; 647 markAsDirty(); 648 } 649 650 /** 651 * Sets the language highlighting enabled.<p> 652 * 653 * @param highlighting <code>true</code> to highlight 654 */ 655 public void setHighlighting(boolean highlighting) { 656 657 getState().m_highlighting = highlighting; 658 markAsDirty(); 659 } 660 661 /** 662 * Sets the editor language.<p> 663 * 664 * @param codeMirrorLanguage the editor language 665 */ 666 public void setLanguage(CodeMirrorLanguage codeMirrorLanguage) { 667 668 getState().m_mode = codeMirrorLanguage.getLanguageName(); 669 markAsDirty(); 670 } 671 672 /** 673 * Sets line wrapping enabled.<p> 674 * 675 * @param lineWrapping <code>true</code> to wrap lines 676 */ 677 public void setLineWrapping(boolean lineWrapping) { 678 679 getState().m_lineWrapping = lineWrapping; 680 markAsDirty(); 681 } 682 683 /** 684 * @see com.vaadin.ui.AbstractComponent#setReadOnly(boolean) 685 */ 686 @Override 687 public void setReadOnly(boolean readOnly) { 688 689 super.setReadOnly(readOnly); 690 } 691 692 /** 693 * Sets tab characters visible.<p> 694 * 695 * @param tabsVisible <code>true</code> to show tab characters 696 */ 697 public void setTabsVisible(boolean tabsVisible) { 698 699 getState().m_tabsVisible = tabsVisible; 700 markAsDirty(); 701 } 702 703 /** 704 * Sets the editor theme.<p> 705 * 706 * @param codeMirrorTheme the editor theme 707 */ 708 public void setTheme(CodeMirrorTheme codeMirrorTheme) { 709 710 // getState().m_id = m_componentId; 711 getState().m_theme = codeMirrorTheme.getThemeName(); 712 markAsDirty(); 713 } 714 715 /** 716 * Sets the editor content value.<p> 717 * 718 * @param value the content value 719 */ 720 public void setValue(String value) { 721 722 m_codeValue = value; 723 724 getState().m_contentValue = value; 725 markAsDirty(); 726 } 727 728 /** 729 * @see com.vaadin.ui.AbstractComponent#setWidth(float, com.vaadin.server.Sizeable.Unit) 730 */ 731 @Override 732 public void setWidth(float width, Unit unit) { 733 734 super.setWidth(width, unit); 735 getState().m_width = width + unit.getSymbol(); 736 markAsDirty(); 737 } 738 739 /** 740 * @see com.vaadin.ui.AbstractComponent#setWidth(java.lang.String) 741 */ 742 @Override 743 public void setWidth(String width) { 744 745 super.setWidth(width); 746 getState().m_width = width; 747 markAsDirty(); 748 } 749 750 /** 751 * @see com.vaadin.ui.AbstractJavaScriptComponent#getState() 752 */ 753 @Override 754 protected CodeMirrorState getState() { 755 756 return (CodeMirrorState)super.getState(); 757 } 758 759 /** 760 * Called on blur.<p> 761 * 762 * @param value the content value 763 */ 764 void onBlur(String value) { 765 766 m_codeValue = value; 767 fireEvent(new FieldEvents.BlurEvent(CmsCodeMirror.this)); 768 } 769 770 /** 771 * Called on blur.<p> 772 * 773 * @param value the content value 774 */ 775 void onChange(String value) { 776 777 boolean changed = !m_codeValue.equals(value); 778 m_codeValue = value; 779 if (changed) { 780 fireEvent(new ValueChangeEvent(this)); 781 } 782 } 783 784 /** 785 * Returns the code mirror localization JSON.<p> 786 * 787 * @param messages the message bundle to use 788 * 789 * @return the localization 790 */ 791 private String getLocalizationMessages(CmsMessages messages) { 792 793 JSONObject result = new JSONObject(); 794 try { 795 result.put("search", messages.key(Messages.GUI_CODEMIRROR_LANG_SEARCH_0)); 796 result.put("hint", messages.key(Messages.GUI_CODEMIRROR_LANG_HINT_0)); 797 result.put("replace", messages.key(Messages.GUI_CODEMIRROR_LANG_REPLACE_0)); 798 result.put("replacewith", messages.key(Messages.GUI_CODEMIRROR_LANG_REPLACE_WITH_0)); 799 result.put("replaceconfirm", messages.key(Messages.GUI_CODEMIRROR_LANG_REPLACE_CONFIRM_0)); 800 result.put("replaceyes", messages.key(Messages.GUI_CODEMIRROR_LANG_REPLACE_YES_0)); 801 result.put("replaceno", messages.key(Messages.GUI_CODEMIRROR_LANG_RELACE_NO_0)); 802 result.put("replacestop", messages.key(Messages.GUI_CODEMIRROR_LANG_REPLACE_STOP_0)); 803 804 result.put("fontsize", messages.key(Messages.GUI_CODEMIRROR_LANG_FONT_SIZE_0)); 805 } catch (org.opencms.json.JSONException e) { 806 // should never happen 807 } 808 return result.toString(); 809 } 810 811 /** 812 * Returns the localized short cut messages HTML.<p> 813 * 814 * @param messages the message bundle to use 815 * 816 * @return the HTML 817 */ 818 private String getShortcutMessages(CmsMessages messages) { 819 820 StringBuffer buffer = new StringBuffer(); 821 buffer.append("<span class=\"col1\"><b>").append(messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_SEARCH_0)); 822 buffer.append("</b> ").append(messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_SEARCH_HELP_0)); 823 buffer.append(" </span><span class=\"col2\"><b>").append( 824 messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_FIND_NEXT_0)); 825 buffer.append("</b> ").append(messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_FIND_NEXT_HELP_0)); 826 buffer.append(" </span><span class=\"col3\"><b>").append( 827 messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_FIND_PREVIOUS_0)); 828 buffer.append("</b> ").append(messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_FIND_PREVIOUS_HELP_0)); 829 buffer.append(" </span><span class=\"col1\"><b>").append( 830 messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_REPLACE_0)); 831 buffer.append("</b> ").append(messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_REPLACE_HELP_0)); 832 buffer.append(" </span><span class=\"col2\"><b>").append( 833 messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_REPLACE_ALL_0)); 834 buffer.append("</b> ").append(messages.key(Messages.GUI_CODEMIRROR_SHORTCUT_REPLACE_ALL_HELP_0)).append( 835 "</span>"); 836 return buffer.toString(); 837 } 838}