001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.acacia.client; 029 030import org.opencms.acacia.client.css.I_CmsWidgetsLayoutBundle; 031import org.opencms.acacia.client.entity.CmsEntityBackend; 032import org.opencms.acacia.client.entity.I_CmsEntityBackend; 033import org.opencms.acacia.client.ui.CmsInlineEditOverlay; 034import org.opencms.acacia.client.widgets.CmsFormWidgetWrapper; 035import org.opencms.acacia.client.widgets.CmsStringWidget; 036import org.opencms.acacia.client.widgets.CmsTinyMCEWidget; 037import org.opencms.acacia.client.widgets.I_CmsEditWidget; 038import org.opencms.acacia.client.widgets.I_CmsFormEditWidget; 039import org.opencms.acacia.client.widgets.complex.CmsDataViewWidgetRenderer; 040import org.opencms.acacia.shared.CmsContentDefinition; 041import org.opencms.acacia.shared.CmsEntity; 042import org.opencms.acacia.shared.CmsEntityHtml; 043import org.opencms.acacia.shared.CmsTabInfo; 044import org.opencms.acacia.shared.CmsType; 045import org.opencms.acacia.shared.CmsValidationResult; 046import org.opencms.acacia.shared.rpc.I_CmsContentServiceAsync; 047import org.opencms.gwt.client.ui.CmsTabbedPanel; 048import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle; 049 050import java.util.ArrayList; 051import java.util.List; 052import java.util.Set; 053 054import com.google.gwt.dom.client.Element; 055import com.google.gwt.event.dom.client.ClickHandler; 056import com.google.gwt.event.logical.shared.ResizeEvent; 057import com.google.gwt.event.logical.shared.ResizeHandler; 058import com.google.gwt.event.logical.shared.ValueChangeHandler; 059import com.google.gwt.event.shared.HandlerRegistration; 060import com.google.gwt.i18n.client.Dictionary; 061import com.google.gwt.user.client.Command; 062import com.google.gwt.user.client.Timer; 063import com.google.gwt.user.client.Window; 064import com.google.gwt.user.client.rpc.AsyncCallback; 065import com.google.gwt.user.client.ui.FlowPanel; 066import com.google.gwt.user.client.ui.Panel; 067 068/** 069 * The content editor base.<p> 070 */ 071public class CmsEditorBase implements I_CmsInlineHtmlUpdateHandler { 072 073 /** Message constant for key in the resource bundle. */ 074 public static final String GUI_CHOICE_ADD_CHOICE_1 = "GUI_CHOICE_ADD_CHOICE_1"; //Add choice {0} 075 076 /** Message constant for key in the resource bundle. */ 077 public static final String GUI_VIEW_ADD_1 = "GUI_VIEW_ADD_1"; //Add {0} 078 079 /** Message constant for key in the resource bundle. */ 080 public static final String GUI_VIEW_CLOSE_0 = "GUI_VIEW_CLOSE_0"; //Close 081 082 /** Message constant for key in the resource bundle. */ 083 public static final String GUI_VIEW_DELETE_1 = "GUI_VIEW_DELETE_1"; //Delete {0} 084 085 /** Message constant for key in the resource bundle. */ 086 public static final String GUI_VIEW_EDIT_1 = "GUI_VIEW_EDIT_1"; // Edit {0} 087 088 /** Message constant for key in the resource bundle. */ 089 public static final String GUI_VIEW_MOVE_1 = "GUI_VIEW_MOVE_1"; //Move {0} 090 091 /** Message constant for key in the resource bundle. */ 092 public static final String GUI_VIEW_MOVE_DOWN_0 = "GUI_VIEW_MOVE_DOWN_0"; //Move down 093 094 /** Message constant for key in the resource bundle. */ 095 public static final String GUI_VIEW_MOVE_UP_0 = "GUI_VIEW_MOVE_UP_0"; //Move up 096 097 /** The inline edit focus marker. */ 098 private static final String INLINE_EDIT_FOCUS_MARKER = "shouldFocusOnInlineEdit"; 099 100 /** The localized dictionary. */ 101 private static Dictionary m_dictionary; 102 103 /** The entity back-end instance. */ 104 protected I_CmsEntityBackend m_entityBackend; 105 106 /** The id of the edited entity. */ 107 protected String m_entityId; 108 109 /** The in-line edit overlay hiding other content. */ 110 private CmsInlineEditOverlay m_editOverlay; 111 112 /** The edited entity. */ 113 private CmsEntity m_entity; 114 115 /** The form panel. */ 116 private FlowPanel m_formPanel; 117 118 /** The tab panel if tabs are used. */ 119 private CmsTabbedPanel<?> m_formTabs; 120 121 /** The window resize handler registration. */ 122 private HandlerRegistration m_resizeHandlerRegistration; 123 124 /** The root attribute handler. */ 125 private CmsRootHandler m_rootHandler; 126 127 /** The content service instance. */ 128 private I_CmsContentServiceAsync m_service; 129 130 /** The tab infos. */ 131 private List<CmsTabInfo> m_tabInfos; 132 133 /** The validation handler. */ 134 private CmsValidationHandler m_validationHandler; 135 136 /** The widget service. */ 137 private I_CmsWidgetService m_widgetService; 138 139 /** 140 * Constructor.<p> 141 * 142 * @param service the content service 143 * @param widgetService the widget service to use 144 */ 145 public CmsEditorBase(I_CmsContentServiceAsync service, I_CmsWidgetService widgetService) { 146 147 I_CmsLayoutBundle.INSTANCE.generalCss().ensureInjected(); 148 I_CmsLayoutBundle.INSTANCE.buttonCss().ensureInjected(); 149 I_CmsLayoutBundle.INSTANCE.highlightCss().ensureInjected(); 150 I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().ensureInjected(); 151 I_CmsLayoutBundle.INSTANCE.dialogCss().ensureInjected(); 152 org.opencms.acacia.client.css.I_CmsLayoutBundle.INSTANCE.form().ensureInjected(); 153 org.opencms.acacia.client.css.I_CmsLayoutBundle.INSTANCE.attributeChoice().ensureInjected(); 154 I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().ensureInjected(); 155 I_CmsWidgetsLayoutBundle.INSTANCE.galleryWidgetsCss().ensureInjected(); 156 m_service = service; 157 m_entityBackend = CmsEntityBackend.getInstance(); 158 m_widgetService = widgetService; 159 I_CmsEntityRenderer renderer = new CmsRenderer(m_entityBackend, m_widgetService); 160 m_widgetService.setDefaultRenderer(renderer); 161 m_widgetService.addWidgetFactory("string", new I_CmsWidgetFactory() { 162 163 public I_CmsFormEditWidget createFormWidget(String configuration) { 164 165 return new CmsFormWidgetWrapper(new CmsStringWidget()); 166 } 167 168 public I_CmsEditWidget createInlineWidget(String configuration, Element element) { 169 170 return new CmsStringWidget(element); 171 } 172 }); 173 m_widgetService.addWidgetFactory("html", new I_CmsWidgetFactory() { 174 175 public I_CmsFormEditWidget createFormWidget(String configuration) { 176 177 return new CmsFormWidgetWrapper(new CmsTinyMCEWidget(null)); 178 } 179 180 public I_CmsEditWidget createInlineWidget(String configuration, Element element) { 181 182 return new CmsTinyMCEWidget(element, null); 183 } 184 }); 185 186 // we may want to explicitly use the default renderer for specific attributes. 187 m_widgetService.addRenderer(new CmsRenderer(CmsEntityBackend.getInstance(), getWidgetService())); 188 m_widgetService.addRenderer(new CmsNativeComplexWidgetRenderer()); 189 m_widgetService.addRenderer(new CmsDataViewWidgetRenderer()); 190 m_validationHandler = new CmsValidationHandler(); 191 m_validationHandler.setContentService(m_service); 192 } 193 194 /** 195 * Returns the formated message.<p> 196 * 197 * @param key the message key 198 * @param args the parameters to insert into the placeholders 199 * 200 * @return the formated message 201 */ 202 public static String getMessageForKey(String key, Object... args) { 203 204 String result = null; 205 if (hasDictionary()) { 206 result = m_dictionary.get(key); 207 if ((result != null) && (args != null) && (args.length > 0)) { 208 for (int i = 0; i < args.length; i++) { 209 result = result.replace("{" + i + "}", String.valueOf(args[i])); 210 } 211 } 212 } 213 if (result == null) { 214 result = ""; 215 } 216 return result; 217 } 218 219 /** 220 * Returns if the messages dictionary is set.<p> 221 * 222 * @return <code>true</code> if the messages dictionary is set 223 */ 224 public static boolean hasDictionary() { 225 226 return m_dictionary != null; 227 } 228 229 /** 230 * Marks the given element to receive focus once the inline editing is initialized.<p> 231 * 232 * @param element the element to mark 233 */ 234 public static void markForInlineFocus(Element element) { 235 236 element.setAttribute("rel", INLINE_EDIT_FOCUS_MARKER); 237 } 238 239 /** 240 * Sets the m_dictionary.<p> 241 * 242 * @param dictionary the m_dictionary to set 243 */ 244 public static void setDictionary(Dictionary dictionary) { 245 246 m_dictionary = dictionary; 247 } 248 249 /** 250 * Checks whether the given element is marked to receive focus once the inline editing is initialized.<p> 251 * 252 * @param element the element to check 253 * 254 * @return <code>true</code> if the given element is marked to receive focus once the inline editing is initialized 255 */ 256 public static boolean shouldFocusOnInlineEdit(Element element) { 257 258 return INLINE_EDIT_FOCUS_MARKER.equals(element.getAttribute("rel")); 259 } 260 261 /** 262 * Adds the value change handler to the entity with the given id.<p> 263 * 264 * @param entityId the entity id 265 * @param handler the change handler 266 */ 267 public void addEntityChangeHandler(String entityId, ValueChangeHandler<CmsEntity> handler) { 268 269 CmsEntity entity = m_entityBackend.getEntity(entityId); 270 if (entity != null) { 271 entity.addValueChangeHandler(handler); 272 } 273 } 274 275 /** 276 * Adds a validation change handler.<p> 277 * 278 * @param handler the validation change handler 279 * 280 * @return the handler registration 281 */ 282 public HandlerRegistration addValidationChangeHandler(ValueChangeHandler<CmsValidationContext> handler) { 283 284 return m_validationHandler.addValueChangeHandler(handler); 285 } 286 287 /** 288 * Destroys the form and related resources. Also clears all entities from the entity back-end<p> 289 * 290 * @param clearEntities <code>true</code> to also clear all entities 291 */ 292 public void destroyForm(boolean clearEntities) { 293 294 CmsValueFocusHandler.getInstance().destroy(); 295 if (clearEntities) { 296 m_entityBackend.clearEntities(); 297 } 298 } 299 300 /** 301 * Returns the currently edited entity.<p> 302 * 303 * @return the currently edited entity 304 */ 305 public CmsEntity getCurrentEntity() { 306 307 return m_entityBackend.getEntity(m_entityId); 308 } 309 310 /** 311 * Returns editor form tabs or null in case no tabs are used.<p> 312 * 313 * @return the editor form tabs 314 */ 315 public CmsTabbedPanel<?> getFormTabs() { 316 317 return m_formTabs; 318 } 319 320 /** 321 * Returns the content service instance.<p> 322 * 323 * @return the content service 324 */ 325 public I_CmsContentServiceAsync getService() { 326 327 return m_service; 328 } 329 330 /** 331 * Loads the content definition for the given entity and executes the callback on success.<p> 332 * 333 * @param entityId the entity id 334 * @param callback the callback 335 */ 336 public void loadContentDefinition(final String entityId, final Command callback) { 337 338 AsyncCallback<CmsContentDefinition> asyncCallback = new AsyncCallback<CmsContentDefinition>() { 339 340 public void onFailure(Throwable caught) { 341 342 onRpcError(caught); 343 } 344 345 public void onSuccess(CmsContentDefinition result) { 346 347 registerContentDefinition(result); 348 callback.execute(); 349 } 350 }; 351 getService().loadContentDefinition(entityId, asyncCallback); 352 } 353 354 /** 355 * Registers the types and entities of the given content definition.<p> 356 * 357 * @param definition the content definition 358 */ 359 public void registerContentDefinition(CmsContentDefinition definition) { 360 361 m_widgetService.addConfigurations(definition.getConfigurations()); 362 CmsType baseType = definition.getTypes().get(definition.getEntityTypeName()); 363 m_entityBackend.registerTypes(baseType, definition.getTypes()); 364 m_entityBackend.registerEntity(definition.getEntity()); 365 } 366 367 /** 368 * @see org.opencms.acacia.client.I_CmsInlineHtmlUpdateHandler#reinitWidgets(org.opencms.acacia.client.I_CmsInlineFormParent) 369 */ 370 public void reinitWidgets(I_CmsInlineFormParent formParent) { 371 372 renderInlineEntity(m_entityId, formParent); 373 } 374 375 /** 376 * Renders the entity form within the given context.<p> 377 * 378 * @param entityId the entity id 379 * @param tabInfos the tab informations 380 * @param context the context element 381 * @param scrollParent the scroll element to be used for automatic scrolling during drag and drop 382 383 */ 384 public void renderEntityForm(String entityId, List<CmsTabInfo> tabInfos, Panel context, Element scrollParent) { 385 386 CmsEntity entity = m_entityBackend.getEntity(entityId); 387 if (entity != null) { 388 boolean initUndo = (m_entity == null) || !entity.getId().equals(m_entity.getId()); 389 m_entity = entity; 390 CmsType type = m_entityBackend.getType(m_entity.getTypeName()); 391 m_formPanel = new FlowPanel(); 392 context.add(m_formPanel); 393 CmsAttributeHandler.setScrollElement(scrollParent); 394 CmsButtonBarHandler.INSTANCE.setWidgetService(m_widgetService); 395 if (m_rootHandler == null) { 396 m_rootHandler = new CmsRootHandler(); 397 } else { 398 m_rootHandler.clearHandlers(); 399 } 400 m_tabInfos = tabInfos; 401 m_formTabs = m_widgetService.getRendererForType( 402 type).renderForm(m_entity, m_tabInfos, m_formPanel, m_rootHandler, 0); 403 m_validationHandler.registerEntity(m_entity); 404 m_validationHandler.setRootHandler(m_rootHandler); 405 m_validationHandler.setFormTabPanel(m_formTabs); 406 if (initUndo) { 407 CmsUndoRedoHandler.getInstance().initialize(m_entity, this, m_rootHandler); 408 } 409 // trigger validation right away 410 m_validationHandler.validate(m_entity); 411 } 412 } 413 414 /** 415 * Renders the entity form within the given context.<p> 416 * 417 * @param entityId the entity id 418 * @param context the context element 419 * @param scrollParent the scroll element to be used for automatic scrolling during drag and drop 420 */ 421 public void renderEntityForm(String entityId, Panel context, Element scrollParent) { 422 423 CmsEntity entity = m_entityBackend.getEntity(entityId); 424 if (entity != null) { 425 boolean initUndo = (m_entity == null) || !entity.getId().equals(m_entity.getId()); 426 m_entity = entity; 427 CmsType type = m_entityBackend.getType(m_entity.getTypeName()); 428 m_formPanel = new FlowPanel(); 429 context.add(m_formPanel); 430 CmsAttributeHandler.setScrollElement(scrollParent); 431 CmsButtonBarHandler.INSTANCE.setWidgetService(m_widgetService); 432 if (m_rootHandler == null) { 433 m_rootHandler = new CmsRootHandler(); 434 } else { 435 m_rootHandler.clearHandlers(); 436 } 437 m_widgetService.getRendererForType(type).renderForm(m_entity, m_formPanel, m_rootHandler, 0); 438 m_formTabs = null; 439 m_tabInfos = null; 440 m_validationHandler.setContentService(m_service); 441 m_validationHandler.registerEntity(m_entity); 442 m_validationHandler.setRootHandler(m_rootHandler); 443 m_validationHandler.setFormTabPanel(null); 444 if (initUndo) { 445 CmsUndoRedoHandler.getInstance().initialize(m_entity, this, m_rootHandler); 446 } 447 } 448 } 449 450 /** 451 * Renders the entity form within the given context.<p> 452 * 453 * @param entityId the entity id 454 * @param formParent the form parent widget 455 */ 456 public void renderInlineEntity(String entityId, I_CmsInlineFormParent formParent) { 457 458 m_entity = m_entityBackend.getEntity(entityId); 459 if (m_entity != null) { 460 if (m_rootHandler == null) { 461 m_rootHandler = new CmsRootHandler(); 462 } else { 463 m_rootHandler.clearHandlers(); 464 } 465 m_validationHandler.setContentService(m_service); 466 m_validationHandler.registerEntity(m_entity); 467 m_validationHandler.setRootHandler(m_rootHandler); 468 CmsType type = m_entityBackend.getType(m_entity.getTypeName()); 469 CmsButtonBarHandler.INSTANCE.setWidgetService(m_widgetService); 470 m_widgetService.getRendererForType(type).renderInline(m_entity, formParent, this, m_rootHandler, 0); 471 CmsUndoRedoHandler.getInstance().initialize(m_entity, this, m_rootHandler); 472 } 473 } 474 475 /** 476 * Re-renders the form with the given entity data.<p> 477 * 478 * @param newContent the entity data 479 */ 480 public void rerenderForm(CmsEntity newContent) { 481 482 m_validationHandler.setPaused(true, m_entity); 483 m_entityBackend.changeEntityContentValues(m_entity, newContent); 484 CmsType type = m_entityBackend.getType(m_entity.getTypeName()); 485 if ((m_tabInfos != null) && !m_tabInfos.isEmpty()) { 486 int currentTab = m_formTabs.getSelectedIndex(); 487 m_formPanel.clear(); 488 m_rootHandler.clearHandlers(); 489 m_formTabs = m_widgetService.getRendererForType( 490 type).renderForm(m_entity, m_tabInfos, m_formPanel, m_rootHandler, 0); 491 m_formTabs.selectTab(currentTab); 492 } else { 493 m_formPanel.clear(); 494 m_rootHandler.clearHandlers(); 495 m_widgetService.getRendererForType(type).renderForm(m_entity, m_tabInfos, m_formPanel, m_rootHandler, 0); 496 } 497 m_validationHandler.setPaused(false, m_entity); 498 } 499 500 /** 501 * Saves the given entities.<p> 502 * 503 * @param entities the entities to save 504 * @param clearOnSuccess <code>true</code> to clear the entity back-end instance on success 505 * @param callback the call back command 506 */ 507 public void saveEntities(List<CmsEntity> entities, final boolean clearOnSuccess, final Command callback) { 508 509 AsyncCallback<CmsValidationResult> asyncCallback = new AsyncCallback<CmsValidationResult>() { 510 511 public void onFailure(Throwable caught) { 512 513 onRpcError(caught); 514 } 515 516 public void onSuccess(CmsValidationResult result) { 517 518 callback.execute(); 519 if ((result != null) && result.hasErrors()) { 520 // CmsValidationHandler.getInstance().displayErrors(null, result) 521 } 522 if (clearOnSuccess) { 523 destroyForm(true); 524 } 525 } 526 }; 527 getService().saveEntities(entities, asyncCallback); 528 } 529 530 /** 531 * Saves the given entity.<p> 532 * 533 * @param entityIds the entity ids 534 * @param clearOnSuccess <code>true</code> to clear all entities from entity back-end on success 535 * @param callback the callback executed on success 536 */ 537 public void saveEntities(Set<String> entityIds, boolean clearOnSuccess, Command callback) { 538 539 List<CmsEntity> entities = new ArrayList<CmsEntity>(); 540 for (String entityId : entityIds) { 541 CmsEntity entity = m_entityBackend.getEntity(entityId); 542 if (entity != null) { 543 entities.add(entity); 544 } 545 } 546 saveEntities(entities, clearOnSuccess, callback); 547 } 548 549 /** 550 * Saves the given entity.<p> 551 * 552 * @param entity the entity 553 * @param clearOnSuccess <code>true</code> to clear all entities from entity back-end on success 554 * @param callback the callback executed on success 555 */ 556 public void saveEntity(CmsEntity entity, final boolean clearOnSuccess, final Command callback) { 557 558 AsyncCallback<CmsValidationResult> asyncCallback = new AsyncCallback<CmsValidationResult>() { 559 560 public void onFailure(Throwable caught) { 561 562 onRpcError(caught); 563 } 564 565 public void onSuccess(CmsValidationResult result) { 566 567 callback.execute(); 568 if (clearOnSuccess) { 569 destroyForm(true); 570 } 571 } 572 }; 573 getService().saveEntity(entity, asyncCallback); 574 } 575 576 /** 577 * Saves the given entity.<p> 578 * 579 * @param entityId the entity id 580 * @param clearOnSuccess <code>true</code> to clear all entities from entity back-end on success 581 * @param callback the callback executed on success 582 */ 583 public void saveEntity(String entityId, boolean clearOnSuccess, Command callback) { 584 585 CmsEntity entity = m_entityBackend.getEntity(entityId); 586 saveEntity(entity, clearOnSuccess, callback); 587 } 588 589 /** 590 * Saves the given entity.<p> 591 * 592 * @param entityId the entity id 593 * @param callback the callback executed on success 594 */ 595 public void saveEntity(String entityId, Command callback) { 596 597 CmsEntity entity = m_entityBackend.getEntity(entityId); 598 saveEntity(entity, false, callback); 599 } 600 601 /** 602 * @see org.opencms.acacia.client.I_CmsInlineHtmlUpdateHandler#updateHtml(org.opencms.acacia.client.I_CmsInlineFormParent, com.google.gwt.user.client.Command) 603 */ 604 public void updateHtml(final I_CmsInlineFormParent formParent, final Command onSuccess) { 605 606 AsyncCallback<CmsEntityHtml> callback = new AsyncCallback<CmsEntityHtml>() { 607 608 public void onFailure(Throwable caught) { 609 610 onRpcError(caught); 611 } 612 613 public void onSuccess(CmsEntityHtml result) { 614 615 if (result.getHtmlContent() != null) { 616 formParent.replaceHtml(result.getHtmlContent()); 617 onSuccess.execute(); 618 } 619 } 620 }; 621 getService().updateEntityHtml(getCurrentEntity(), getContextUri(), getHtmlContextInfo(), callback); 622 } 623 624 /** 625 * Adds a click handler to the edit overlay.<p> 626 * 627 * @param handler the click handler 628 * 629 * @return the click handler registration 630 */ 631 protected HandlerRegistration addOverlayClickHandler(ClickHandler handler) { 632 633 return m_editOverlay.addClickHandler(handler); 634 } 635 636 /** 637 * Clears the editor.<p> 638 */ 639 protected void clearEditor() { 640 641 removeEditOverlays(); 642 CmsUndoRedoHandler.getInstance().clear(); 643 m_validationHandler.clear(); 644 m_entity = null; 645 m_entityId = null; 646 m_tabInfos = null; 647 m_rootHandler = null; 648 m_formPanel = null; 649 m_formTabs = null; 650 } 651 652 /** 653 * Returns the context URI.<p> 654 * Needed when updating the HTML due to content data changes.<p> 655 * 656 * Override to supply the required info.<p> 657 * 658 * @return the context URI 659 */ 660 protected String getContextUri() { 661 662 return ""; 663 } 664 665 /** 666 * Returns the in-line HTML context info.<p> 667 * Needed when updating the HTML due to content data changes.<p> 668 * 669 * Override to supply the required info.<p> 670 * 671 * @return the HTML context info 672 */ 673 protected String getHtmlContextInfo() { 674 675 return ""; 676 } 677 678 /** 679 * Returns the root attribute handler.<p> 680 * 681 * @return the root attribute handler 682 */ 683 protected CmsRootHandler getRootAttributeHandler() { 684 685 return m_rootHandler; 686 } 687 688 /** 689 * Returns the validation handler.<p> 690 * 691 * @return the validation handler 692 */ 693 protected CmsValidationHandler getValidationHandler() { 694 695 return m_validationHandler; 696 } 697 698 /** 699 * Returns the widget service.<p> 700 * 701 * @return the widget service 702 */ 703 protected I_CmsWidgetService getWidgetService() { 704 705 return m_widgetService; 706 } 707 708 /** 709 * Initializes the edit overlay to be positioned around the given element.<p> 710 * 711 * @param element the element 712 */ 713 protected void initEditOverlay(Element element) { 714 715 CmsInlineEditOverlay.removeAll(); 716 m_editOverlay = CmsInlineEditOverlay.addOverlayForElement(element); 717 if (m_resizeHandlerRegistration != null) { 718 m_resizeHandlerRegistration.removeHandler(); 719 } 720 // add a handler to ensure the edit overlays get adjusted to changed window size 721 m_resizeHandlerRegistration = Window.addResizeHandler(new ResizeHandler() { 722 723 private Timer m_resizeTimer; 724 725 public void onResize(ResizeEvent event) { 726 727 if (m_resizeTimer == null) { 728 m_resizeTimer = new Timer() { 729 730 @Override 731 public void run() { 732 733 handleResize(); 734 } 735 }; 736 m_resizeTimer.schedule(300); 737 } 738 } 739 740 /** 741 * Handles the window resize.<p> 742 */ 743 void handleResize() { 744 745 m_resizeTimer = null; 746 CmsInlineEditOverlay.updateCurrentOverlayPosition(); 747 } 748 }); 749 } 750 751 /** 752 * Handles RPC errors.<p> 753 * 754 * Override this for better error handling 755 * 756 * @param caught the error caught from the RPC 757 */ 758 protected void onRpcError(Throwable caught) { 759 760 // doing nothing 761 } 762 763 /** 764 * Removes the edit overlay from the DOM.<p> 765 */ 766 protected void removeEditOverlays() { 767 768 CmsInlineEditOverlay.removeAll(); 769 m_editOverlay = null; 770 if (m_resizeHandlerRegistration != null) { 771 m_resizeHandlerRegistration.removeHandler(); 772 m_resizeHandlerRegistration = null; 773 } 774 } 775 776 /** 777 * Updates the edit overlay position.<p> 778 */ 779 protected void updateOverlayPosition() { 780 781 if (m_editOverlay != null) { 782 m_editOverlay.updatePosition(); 783 } 784 } 785}