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.ade.galleries.client.ui; 029 030import org.opencms.ade.galleries.client.CmsGalleryConfigurationJSO; 031import org.opencms.ade.galleries.client.CmsGalleryController; 032import org.opencms.ade.galleries.client.I_CmsGalleryWidgetHandler; 033import org.opencms.ade.galleries.client.Messages; 034import org.opencms.ade.galleries.client.preview.CmsCroppingParamBean; 035import org.opencms.ade.galleries.client.ui.css.I_CmsLayoutBundle; 036import org.opencms.ade.galleries.shared.CmsGalleryActionInfo; 037import org.opencms.ade.galleries.shared.CmsResultItemBean; 038import org.opencms.ade.galleries.shared.I_CmsGalleryConfiguration; 039import org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService; 040import org.opencms.ade.galleries.shared.rpc.I_CmsGalleryServiceAsync; 041import org.opencms.ade.upload.client.I_CmsUploadContext; 042import org.opencms.ade.upload.client.ui.CmsDialogUploadButtonHandler; 043import org.opencms.file.CmsResource; 044import org.opencms.gwt.client.CmsCoreProvider; 045import org.opencms.gwt.client.CmsJsFunctions; 046import org.opencms.gwt.client.I_CmsHasInit; 047import org.opencms.gwt.client.rpc.CmsRpcAction; 048import org.opencms.gwt.client.ui.CmsListItemWidget; 049import org.opencms.gwt.client.ui.CmsPushButton; 050import org.opencms.gwt.client.ui.I_CmsAutoHider; 051import org.opencms.gwt.client.ui.I_CmsButton; 052import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle; 053import org.opencms.gwt.client.ui.I_CmsButton.Size; 054import org.opencms.gwt.client.ui.input.CmsSimpleTextBox; 055import org.opencms.gwt.client.ui.input.I_CmsFormWidget; 056import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry; 057import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory; 058import org.opencms.gwt.client.ui.input.upload.CmsFileInfo; 059import org.opencms.gwt.client.ui.input.upload.CmsUploadButton; 060import org.opencms.gwt.client.util.CmsDomUtil; 061import org.opencms.gwt.client.util.CmsEmbeddedDialogHandler; 062import org.opencms.gwt.shared.CmsGwtLog; 063import org.opencms.util.CmsStringUtil; 064import org.opencms.util.CmsUUID; 065 066import java.util.ArrayList; 067import java.util.HashMap; 068import java.util.List; 069import java.util.Map; 070 071import com.google.common.base.Optional; 072import com.google.common.base.Supplier; 073import com.google.gwt.core.client.GWT; 074import com.google.gwt.core.client.JavaScriptObject; 075import com.google.gwt.core.client.JsArray; 076import com.google.gwt.dom.client.DivElement; 077import com.google.gwt.dom.client.Element; 078import com.google.gwt.event.dom.client.BlurEvent; 079import com.google.gwt.event.dom.client.ClickEvent; 080import com.google.gwt.event.dom.client.ClickHandler; 081import com.google.gwt.event.dom.client.FocusEvent; 082import com.google.gwt.event.dom.client.FocusHandler; 083import com.google.gwt.event.dom.client.HasFocusHandlers; 084import com.google.gwt.event.logical.shared.CloseEvent; 085import com.google.gwt.event.logical.shared.CloseHandler; 086import com.google.gwt.event.logical.shared.HasResizeHandlers; 087import com.google.gwt.event.logical.shared.HasValueChangeHandlers; 088import com.google.gwt.event.logical.shared.OpenEvent; 089import com.google.gwt.event.logical.shared.OpenHandler; 090import com.google.gwt.event.logical.shared.ResizeEvent; 091import com.google.gwt.event.logical.shared.ResizeHandler; 092import com.google.gwt.event.logical.shared.ValueChangeEvent; 093import com.google.gwt.event.logical.shared.ValueChangeHandler; 094import com.google.gwt.event.shared.HandlerRegistration; 095import com.google.gwt.uibinder.client.UiBinder; 096import com.google.gwt.uibinder.client.UiField; 097import com.google.gwt.uibinder.client.UiHandler; 098import com.google.gwt.user.client.DOM; 099import com.google.gwt.user.client.Timer; 100import com.google.gwt.user.client.rpc.ServiceDefTarget; 101import com.google.gwt.user.client.ui.Composite; 102import com.google.gwt.user.client.ui.FlowPanel; 103import com.google.gwt.user.client.ui.HTMLPanel; 104import com.google.gwt.user.client.ui.IsWidget; 105import com.google.gwt.user.client.ui.Label; 106 107import elemental2.dom.HTMLImageElement; 108import jsinterop.base.Js; 109 110/** 111 * A widget for selecting a resource from an ADE gallery dialog.<p> 112 * 113 * @since 8.0.0 114 */ 115public class CmsGalleryField extends Composite 116implements I_CmsFormWidget, I_CmsHasInit, HasValueChangeHandlers<String>, HasResizeHandlers, HasFocusHandlers { 117 118 /** 119 * The UI Binder interface for this widget.<p> 120 */ 121 protected interface I_CmsGalleryFieldUiBinder extends UiBinder<HTMLPanel, CmsGalleryField> { 122 // binder interface 123 } 124 125 /** 126 * Handler to fire resize event on resource info widget open/close.<p> 127 */ 128 protected class OpenCloseHandler implements CloseHandler<CmsListItemWidget>, OpenHandler<CmsListItemWidget> { 129 130 /** 131 * @see com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt.event.logical.shared.CloseEvent) 132 */ 133 @Override 134 public void onClose(CloseEvent<CmsListItemWidget> event) { 135 136 fireResize(); 137 } 138 139 /** 140 * @see com.google.gwt.event.logical.shared.OpenHandler#onOpen(com.google.gwt.event.logical.shared.OpenEvent) 141 */ 142 @Override 143 public void onOpen(OpenEvent<CmsListItemWidget> event) { 144 145 fireResize(); 146 } 147 } 148 149 /** The widget type. */ 150 public static final String WIDGET_TYPE = "gallery"; 151 152 /** The ui binder for this widget. */ 153 private static I_CmsGalleryFieldUiBinder uibinder = GWT.create(I_CmsGalleryFieldUiBinder.class); 154 155 /** The gallery configuration. */ 156 protected I_CmsGalleryConfiguration m_configuration; 157 158 /** The scale parameters from popup. */ 159 protected CmsCroppingParamBean m_croppingParam; 160 161 /** The fading element. */ 162 @UiField 163 protected Label m_fader; 164 165 /** The DIV carrying the input field. */ 166 @UiField 167 protected DivElement m_fieldBox; 168 169 /** The image preview element. */ 170 @UiField 171 protected DivElement m_imagePreview; 172 173 /** The main panel. */ 174 protected HTMLPanel m_main; 175 176 /** The button to to open the selection. */ 177 @UiField 178 protected CmsPushButton m_opener; 179 180 /** The gallery pop-up. */ 181 protected CmsGalleryPopup m_popup; 182 183 /** The resource info panel. */ 184 @UiField 185 protected FlowPanel m_resourceInfoPanel; 186 187 /** Everything to the right of the preview image. */ 188 @UiField 189 protected HTMLPanel m_rightBlock; 190 191 /** The special upload button. */ 192 @UiField(provided = true) 193 protected CmsPushButton m_specialUploadButton; 194 195 /** The textbox containing the currently selected path. */ 196 @UiField 197 protected CmsSimpleTextBox m_textbox; 198 199 /** The upload button. */ 200 @UiField(provided = true) 201 protected CmsUploadButton m_uploadButton; 202 203 /** The upload drop zone. */ 204 protected Element m_uploadDropZone; 205 206 /** The upload target folder. */ 207 String m_uploadTarget; 208 209 /** Flag indicating uploads are allowed. */ 210 private boolean m_allowUploads; 211 212 /** The gallery service instance. */ 213 private I_CmsGalleryServiceAsync m_gallerySvc; 214 215 /** The has image flag. */ 216 private boolean m_hasImage; 217 218 /** The info timer instance. */ 219 private Timer m_infoTimer; 220 221 /** The previous field value. */ 222 private String m_previousValue; 223 224 /** The upload action. */ 225 private String m_uploadAction; 226 227 /** 228 * Constructs a new gallery widget.<p> 229 * 230 * @param configuration the gallery configuration 231 * @param allowUploads states if the upload button should be enabled for this widget 232 */ 233 public CmsGalleryField(I_CmsGalleryConfiguration configuration, boolean allowUploads) { 234 235 CmsDialogUploadButtonHandler buttonHandler = new CmsDialogUploadButtonHandler( 236 new Supplier<I_CmsUploadContext>() { 237 238 @Override 239 public I_CmsUploadContext get() { 240 241 return new I_CmsUploadContext() { 242 243 @Override 244 public void onUploadFinished(List<String> uploadedFiles) { 245 246 if ((uploadedFiles != null) && !uploadedFiles.isEmpty()) { 247 setValue(m_uploadTarget + uploadedFiles.iterator().next(), true); 248 } 249 } 250 251 }; 252 } 253 }); 254 buttonHandler.setIsTargetRootPath(false); 255 m_uploadButton = new CmsUploadButton(buttonHandler); 256 m_uploadButton.setText(null); 257 m_uploadButton.setTitle( 258 Messages.get().key(Messages.GUI_GALLERY_UPLOAD_TITLE_1, configuration.getUploadFolder())); 259 m_uploadButton.setButtonStyle(ButtonStyle.FONT_ICON, null); 260 m_uploadButton.setImageClass(I_CmsButton.UPLOAD); 261 m_uploadButton.setSize(Size.small); 262 m_uploadButton.removeStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll()); 263 m_uploadButton.getElement().setTabIndex(-1); 264 265 m_specialUploadButton = createSpecialUploadButton(); 266 267 m_main = uibinder.createAndBindUi(this); 268 initWidget(m_main); 269 m_allowUploads = allowUploads; 270 if (m_allowUploads) { 271 m_fieldBox.addClassName(I_CmsLayoutBundle.INSTANCE.galleryFieldCss().hasUpload()); 272 } 273 m_configuration = configuration; 274 I_CmsLayoutBundle.INSTANCE.galleryFieldCss().ensureInjected(); 275 m_opener.setButtonStyle(ButtonStyle.FONT_ICON, null); 276 m_opener.setImageClass(I_CmsButton.GALLERY); 277 m_opener.setSize(Size.small); 278 m_opener.setHideFromTabNav(true); 279 } 280 281 /** 282 * Initializes this class.<p> 283 */ 284 public static void initClass() { 285 286 // registers a factory for creating new instances of this widget 287 CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE, new I_CmsFormWidgetFactory() { 288 289 /** 290 * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional) 291 */ 292 @Override 293 public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) { 294 295 String config = widgetParams.get("configuration"); 296 if (CmsStringUtil.isEmptyOrWhitespaceOnly(config)) { 297 config = "{}"; 298 } 299 CmsGalleryConfigurationJSO conf = CmsGalleryConfigurationJSO.parseConfiguration(config); 300 CmsGalleryField galleryField = new CmsGalleryField(conf, false); 301 return galleryField; 302 } 303 }); 304 } 305 306 /** 307 * Adds a style name to the DIV carrying the input field.<p> 308 * 309 * @param styleName the style name to add 310 */ 311 public void addFieldStyleName(String styleName) { 312 313 m_fieldBox.addClassName(styleName); 314 } 315 316 /** 317 * @see com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com.google.gwt.event.dom.client.FocusHandler) 318 */ 319 @Override 320 public HandlerRegistration addFocusHandler(FocusHandler handler) { 321 322 return addDomHandler(handler, FocusEvent.getType()); 323 } 324 325 /** 326 * @see com.google.gwt.event.logical.shared.HasResizeHandlers#addResizeHandler(com.google.gwt.event.logical.shared.ResizeHandler) 327 */ 328 @Override 329 public HandlerRegistration addResizeHandler(ResizeHandler handler) { 330 331 return addHandler(handler, ResizeEvent.getType()); 332 } 333 334 /** 335 * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) 336 */ 337 @Override 338 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) { 339 340 return addHandler(handler, ValueChangeEvent.getType()); 341 } 342 343 /** 344 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getApparentValue() 345 */ 346 @Override 347 public String getApparentValue() { 348 349 return getFormValueAsString(); 350 } 351 352 /** 353 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFieldType() 354 */ 355 @Override 356 public FieldType getFieldType() { 357 358 return FieldType.STRING; 359 } 360 361 /** 362 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValue() 363 */ 364 @Override 365 public Object getFormValue() { 366 367 return getFormValueAsString(); 368 } 369 370 /** 371 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValueAsString() 372 */ 373 @Override 374 public String getFormValueAsString() { 375 376 return m_textbox.getValue(); 377 } 378 379 /** 380 * Returns the gallery popup.<p> 381 * 382 * @return the gallery popup 383 */ 384 public CmsGalleryPopup getPopup() { 385 386 return m_popup; 387 388 } 389 390 /** 391 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#isEnabled() 392 */ 393 @Override 394 public boolean isEnabled() { 395 396 return m_textbox.isEnabled(); 397 } 398 399 /** 400 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#reset() 401 */ 402 @Override 403 public void reset() { 404 405 setFormValueAsString(""); 406 } 407 408 /** 409 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setAutoHideParent(org.opencms.gwt.client.ui.I_CmsAutoHider) 410 */ 411 @Override 412 public void setAutoHideParent(I_CmsAutoHider autoHideParent) { 413 414 // do nothing 415 } 416 417 /** 418 * Sets the upload drop zone element.<p> 419 * 420 * @param dropZone the upload drop zone element 421 */ 422 public void setDropZoneElement(Element dropZone) { 423 424 if (m_allowUploads && (dropZone != null) && (m_uploadDropZone == null)) { 425 m_uploadDropZone = dropZone; 426 initUploadZone(m_uploadDropZone); 427 m_uploadDropZone.setTitle( 428 org.opencms.ade.upload.client.Messages.get().key( 429 org.opencms.ade.upload.client.Messages.GUI_UPLOAD_DRAG_AND_DROP_ENABLED_0)); 430 m_uploadDropZone.addClassName(I_CmsLayoutBundle.INSTANCE.galleryFieldCss().uploadDropZone()); 431 } 432 } 433 434 /** 435 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setEnabled(boolean) 436 */ 437 @Override 438 public void setEnabled(boolean enabled) { 439 440 m_textbox.setEnabled(enabled); 441 } 442 443 /** 444 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setErrorMessage(java.lang.String) 445 */ 446 @Override 447 public void setErrorMessage(String errorMessage) { 448 449 // do nothing 450 } 451 452 /** 453 * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setFormValueAsString(java.lang.String) 454 */ 455 @Override 456 public void setFormValueAsString(String value) { 457 458 setValue(value, false); 459 } 460 461 /** 462 * Sets the gallery opener button title.<p> 463 * 464 * @param openerTitle the gallery opener button title 465 */ 466 public void setGalleryOpenerTitle(String openerTitle) { 467 468 m_opener.setTitle(openerTitle); 469 } 470 471 /** 472 * Sets the has image flag.<p> 473 * 474 * @param hasImage the has image flag 475 **/ 476 public void setHasImage(boolean hasImage) { 477 478 m_hasImage = hasImage; 479 } 480 481 /** 482 * Sets the name of the input field.<p> 483 * 484 * @param name of the input field 485 * */ 486 public void setName(String name) { 487 488 m_textbox.setName(name); 489 490 } 491 492 /** 493 * Adds a widget to the main panel.<p> 494 * 495 * @param widget the widget to add 496 */ 497 protected void addToMain(IsWidget widget) { 498 499 m_rightBlock.add(widget); 500 } 501 502 /** 503 * Fires the value change event if the value has changed.<p> 504 * 505 * @param force <code>true</code> to force firing the event in any case 506 */ 507 protected void fireChange(boolean force) { 508 509 String value = getFormValueAsString(); 510 if (force || !value.equals(m_previousValue)) { 511 m_previousValue = value; 512 ValueChangeEvent.fire(this, value); 513 } 514 } 515 516 /** 517 * Fires the resize event for this widget.<p> 518 */ 519 protected void fireResize() { 520 521 ResizeEvent.fire(this, getElement().getOffsetWidth(), getElement().getOffsetHeight()); 522 } 523 524 /** 525 * Returns the currently set resource path.<p> 526 * 527 * @return the currently set resource path 528 */ 529 protected String getCurrentElement() { 530 531 return getFormValueAsString(); 532 } 533 534 /** 535 * Returns the gallery service instance.<p> 536 * 537 * @return the gallery service instance 538 */ 539 protected I_CmsGalleryServiceAsync getGalleryService() { 540 541 if (m_gallerySvc == null) { 542 m_gallerySvc = GWT.create(I_CmsGalleryService.class); 543 String serviceUrl = CmsCoreProvider.get().link("org.opencms.ade.galleries.CmsGalleryService.gwt"); 544 ((ServiceDefTarget)m_gallerySvc).setServiceEntryPoint(serviceUrl); 545 } 546 return m_gallerySvc; 547 } 548 549 /** 550 * Checks if drag/drop should be enabled. 551 * 552 * @return true if drag/drop should be enabled 553 */ 554 protected boolean isDndEnabled() { 555 556 return m_uploadAction == null; 557 } 558 559 /** 560 * Handles the focus event on the opener.<p> 561 * 562 * @param event the focus event 563 */ 564 @UiHandler("m_textbox") 565 protected void onFocusTextbox(FocusEvent event) { 566 567 CmsDomUtil.fireFocusEvent(this); 568 } 569 570 /** 571 * Internal method which opens the gallery dialog.<p> 572 */ 573 protected void openGalleryDialog() { 574 575 if (m_popup == null) { 576 m_popup = createPopup(); 577 m_popup.center(); 578 } else { 579 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getCurrentElement())) { 580 m_popup.searchElement(getCurrentElement()); 581 } else { 582 m_popup.center(); 583 } 584 } 585 } 586 587 /** 588 * Removes the given widget from the main panel.<p> 589 * 590 * @param widget the widget to remove 591 * 592 * @return <code>true</code> if the widget was a child of the main panel 593 */ 594 protected boolean removeFromMain(IsWidget widget) { 595 596 return m_main.remove(widget); 597 } 598 599 /** 600 * Sets the image preview.<p> 601 * 602 * @param realPath the actual image path 603 * @param imagePath the image path 604 */ 605 protected void setImagePreview(String realPath, String imagePath) { 606 607 if ((m_croppingParam == null) || !getFormValueAsString().contains(m_croppingParam.toString())) { 608 m_croppingParam = CmsCroppingParamBean.parseImagePath(getFormValueAsString()); 609 } 610 CmsCroppingParamBean restricted; 611 612 String highRes = null; 613 String normalRes = null; 614 if (m_croppingParam.getScaleParam(false).isEmpty()) { 615 highRes = imagePath + getScalingParams(true); 616 normalRes = imagePath + getScalingParams(false); 617 } else { 618 restricted = m_croppingParam.getRestrictedSizeParam(140, 165); 619 normalRes = imagePath + "?" + restricted.convertToScalingParam(false); 620 highRes = imagePath + "?" + restricted.convertToScalingParam(true); 621 } 622 Element image = DOM.createImg(); 623 image.setAttribute("src", normalRes); 624 { 625 HTMLImageElement img = Js.cast(image); 626 img.addEventListener("error", event -> CmsJsFunctions.INSTANCE.handleBrokenImage(img)); 627 if (highRes != null) { 628 img.srcset = highRes + " 2x"; 629 } 630 } 631 m_imagePreview.setInnerHTML(""); 632 m_imagePreview.appendChild(image); 633 } 634 635 /** 636 * Sets the widget value.<p> 637 * 638 * @param value the value to set 639 * @param fireEvent if the change event should be fired 640 */ 641 protected void setValue(String value, boolean fireEvent) { 642 643 m_textbox.setValue(value); 644 updateUploadTarget(CmsResource.getFolderPath(value)); 645 updateResourceInfo(value); 646 m_previousValue = value; 647 if (fireEvent) { 648 fireChange(true); 649 } 650 } 651 652 /** 653 * Sets the widget value. To be called from the gallery dialog.<p> 654 * 655 * @param resourcePath the selected resource path 656 * @param structureId the resource structure id 657 * @param croppingParameter the selected cropping 658 */ 659 protected void setValueFromGallery( 660 String resourcePath, 661 CmsUUID structureId, 662 CmsCroppingParamBean croppingParameter) { 663 664 m_croppingParam = croppingParameter; 665 String path = resourcePath; 666 // in case of an image check the cropping parameter 667 if ((m_croppingParam != null) && (m_croppingParam.isCropped() || m_croppingParam.isScaled())) { 668 path += "?" + m_croppingParam.toString(); 669 } 670 setValue(path, true); 671 m_popup.hide(); 672 } 673 674 /** 675 * Updates the upload target folder path.<p> 676 * 677 * @param uploadTarget the upload target folder 678 */ 679 protected void updateUploadTarget(String uploadTarget) { 680 681 m_uploadAction = null; 682 if (CmsStringUtil.isEmptyOrWhitespaceOnly(uploadTarget)) { 683 m_uploadTarget = m_configuration.getUploadFolder(); 684 } else { 685 m_uploadTarget = uploadTarget; 686 } 687 if (CmsStringUtil.isEmptyOrWhitespaceOnly(m_uploadTarget)) { 688 setSpecialUpload(false); 689 // disable the upload button as no target folder is available 690 m_uploadButton.disable( 691 org.opencms.ade.upload.client.Messages.get().key( 692 org.opencms.ade.upload.client.Messages.GUI_UPLOAD_BUTTON_NO_TARGET_0)); 693 } else { 694 CmsRpcAction<CmsGalleryActionInfo> action = new CmsRpcAction<CmsGalleryActionInfo>() { 695 696 @Override 697 public void execute() { 698 699 start(0, false); 700 CmsGalleryController.getGalleryService().getGalleryActionInfo(uploadTarget, this); 701 702 } 703 704 @SuppressWarnings("synthetic-access") 705 @Override 706 protected void onResponse(CmsGalleryActionInfo result) { 707 708 stop(false); 709 if ((result == null) || (result.getUploadAction() == null)) { 710 setSpecialUpload(false); 711 // make sure the upload button is available 712 m_uploadButton.enable(); 713 ((CmsDialogUploadButtonHandler)m_uploadButton.getButtonHandler()).setTargetFolder( 714 m_uploadTarget); 715 m_uploadButton.updateFileInput(); 716 m_uploadButton.setTitle( 717 Messages.get().key(Messages.GUI_GALLERY_UPLOAD_TITLE_1, m_uploadTarget)); 718 719 } else { 720 m_uploadAction = result.getUploadAction(); 721 setSpecialUpload(true); 722 } 723 } 724 }; 725 action.execute(); 726 727 } 728 } 729 730 /** 731 * Clears the info timer.<p> 732 */ 733 void clearInfoTimer() { 734 735 m_infoTimer = null; 736 } 737 738 /** 739 * Displays the resource info.<p> 740 * 741 * @param info the resource info 742 */ 743 void displayResourceInfo(CmsResultItemBean info) { 744 745 if (m_hasImage) { 746 setImagePreview(info.getPath(), info.getViewLink()); 747 m_resourceInfoPanel.add(new CmsImageInfo(info, info.getDimension())); 748 } else { 749 CmsListItemWidget widget = new CmsListItemWidget(info); 750 OpenCloseHandler handler = new OpenCloseHandler(); 751 widget.addCloseHandler(handler); 752 widget.addOpenHandler(handler); 753 m_resourceInfoPanel.add(widget); 754 int width = m_resourceInfoPanel.getOffsetWidth(); 755 if (width > 0) { 756 widget.truncate("STANDARD", width); 757 } 758 } 759 fireResize(); 760 } 761 762 /** 763 * On text box blur.<p> 764 * 765 * @param event the event 766 */ 767 @UiHandler("m_textbox") 768 void onBlur(BlurEvent event) { 769 770 setFaded((m_textbox.getValue().length() * 6.88) > m_textbox.getOffsetWidth()); 771 setTitle(m_textbox.getValue()); 772 } 773 774 /** 775 * Handles styling changes on drag out.<p> 776 */ 777 void onDragOut() { 778 779 m_uploadDropZone.removeClassName(I_CmsLayoutBundle.INSTANCE.galleryFieldCss().dropZoneHover()); 780 } 781 782 /** 783 * Handles styling changes on drag over.<p> 784 */ 785 void onDragOver() { 786 787 if (m_uploadTarget != null) { 788 m_uploadDropZone.addClassName(I_CmsLayoutBundle.INSTANCE.galleryFieldCss().dropZoneHover()); 789 } 790 } 791 792 /** 793 * On fader click.<p> 794 * 795 * @param event the event 796 */ 797 @UiHandler("m_fader") 798 void onFaiderClick(ClickEvent event) { 799 800 m_textbox.setFocus(true); 801 } 802 803 /** 804 * On opener click.<p> 805 * 806 * @param event the event 807 */ 808 @UiHandler("m_opener") 809 void onOpenerClick(ClickEvent event) { 810 811 m_opener.clearHoverState(); 812 openGalleryDialog(); 813 } 814 815 /** 816 * On text box change.<p> 817 * 818 * @param event the event 819 */ 820 @UiHandler("m_textbox") 821 void onTextBoxChange(ValueChangeEvent<String> event) { 822 823 fireChange(false); 824 if (m_infoTimer != null) { 825 m_infoTimer.cancel(); 826 m_infoTimer = null; 827 } 828 m_infoTimer = new Timer() { 829 830 @Override 831 public void run() { 832 833 updateResourceInfo(getFormValueAsString()); 834 clearInfoTimer(); 835 } 836 }; 837 m_infoTimer.schedule(300); 838 } 839 840 /** 841 * Toggles the fading element.<p> 842 * 843 * @param faded <code>true</code> to show the fading element.<p> 844 */ 845 void setFaded(boolean faded) { 846 847 m_fader.setVisible(faded); 848 } 849 850 /** 851 * Updates the resource info.<p> 852 * 853 * @param path the resource path 854 */ 855 void updateResourceInfo(final String path) { 856 857 m_resourceInfoPanel.clear(); 858 if (CmsStringUtil.isEmptyOrWhitespaceOnly(path)) { 859 m_resourceInfoPanel.setVisible(false); 860 if (m_hasImage) { 861 removeStyleName(I_CmsLayoutBundle.INSTANCE.galleryFieldCss().hasImage()); 862 m_imagePreview.setInnerHTML(""); 863 } 864 } else { 865 m_resourceInfoPanel.getElement().getStyle().clearDisplay(); 866 if (m_hasImage) { 867 addStyleName(I_CmsLayoutBundle.INSTANCE.galleryFieldCss().hasImage()); 868 } 869 CmsRpcAction<CmsResultItemBean> action = new CmsRpcAction<CmsResultItemBean>() { 870 871 @Override 872 public void execute() { 873 874 getGalleryService().getInfoForResource(path, m_configuration.getLocale(), this); 875 } 876 877 @Override 878 protected void onResponse(CmsResultItemBean result) { 879 880 displayResourceInfo(result); 881 } 882 }; 883 action.execute(); 884 } 885 fireResize(); 886 } 887 888 /** 889 * Creates the gallery pop-up.<p> 890 * 891 * @return the gallery pop-up 892 */ 893 private CmsGalleryPopup createPopup() { 894 895 I_CmsGalleryWidgetHandler handler = new I_CmsGalleryWidgetHandler() { 896 897 @Override 898 public void setWidgetValue( 899 String resourcePath, 900 CmsUUID structureId, 901 CmsCroppingParamBean croppingParameter) { 902 903 setValueFromGallery(resourcePath, structureId, croppingParameter); 904 } 905 }; 906 m_configuration.setCurrentElement(getCurrentElement()); 907 return new CmsGalleryPopup(handler, m_configuration); 908 } 909 910 /** 911 * Creates custom upload button for galleries which have an upload action configured. 912 * 913 * @return the special upload button 914 */ 915 private CmsPushButton createSpecialUploadButton() { 916 917 CmsPushButton uploadButton = new CmsPushButton(I_CmsButton.UPLOAD_SMALL); 918 uploadButton.setText(null); 919 //uploadButton.setTitle(Messages.get().key(Messages.GUI_GALLERY_UPLOAD_TITLE_1, gallery.getPath())); 920 uploadButton.setButtonStyle(ButtonStyle.FONT_ICON, null); 921 uploadButton.addClickHandler(new ClickHandler() { 922 923 @Override 924 public void onClick(ClickEvent event) { 925 926 CmsRpcAction<CmsUUID> action = new CmsRpcAction<CmsUUID>() { 927 928 @Override 929 public void execute() { 930 931 start(0, true); 932 CmsCoreProvider.getVfsService().getStructureId(m_uploadTarget, this); 933 } 934 935 @SuppressWarnings("synthetic-access") 936 @Override 937 protected void onResponse(CmsUUID result) { 938 939 stop(false); 940 if (result == null) { 941 return; 942 } 943 List<CmsUUID> resultIds = new ArrayList<>(); 944 resultIds.add(result); 945 Map<String, String> params = new HashMap<>(); 946 params.put("editor", "true"); 947 CmsEmbeddedDialogHandler.openDialog( 948 m_uploadAction, 949 resultIds, 950 params, 951 id -> updateValueFromId(id)); 952 } 953 954 }; 955 action.execute(); 956 } 957 }); 958 return uploadButton; 959 } 960 961 /** 962 * Gets the default scaling parameters for the preview. 963 * 964 * @param highRes true if we want the high-res version 965 * @param the scaling parameters 966 */ 967 private String getScalingParams(boolean highRes) { 968 969 970 if (highRes) { 971 return "?__scale=w:400,h:340,t:9,q:85"; 972 } else { 973 return "?__scale=w:200,h:170,t:9"; 974 } 975 } 976 977 /** 978 * Initializes the upload drop zone event handlers.<p> 979 * 980 * @param element the drop zone element 981 */ 982 private native void initUploadZone(JavaScriptObject element)/*-{ 983 // check for file api support 984 if ((typeof FileReader == 'function' || typeof FileReader == 'object') 985 && (typeof FormData == 'function' || typeof FormData == 'object')) { 986 var self = this; 987 988 function isDndEnabled() { 989 return self.@org.opencms.ade.galleries.client.ui.CmsGalleryField::isDndEnabled()(); 990 } 991 992 function dragover(event) { 993 event.stopPropagation(); 994 event.preventDefault(); 995 if (!isDndEnabled()) { 996 return; 997 } 998 self.@org.opencms.ade.galleries.client.ui.CmsGalleryField::onDragOver()(); 999 } 1000 1001 function dragleave(event) { 1002 event.stopPropagation(); 1003 event.preventDefault(); 1004 if (!isDndEnabled()) { 1005 return; 1006 } 1007 self.@org.opencms.ade.galleries.client.ui.CmsGalleryField::onDragOut()(); 1008 } 1009 1010 function drop(event) { 1011 event.preventDefault(); 1012 if (!isDndEnabled()) { 1013 return; 1014 } 1015 self.@org.opencms.ade.galleries.client.ui.CmsGalleryField::onDragOut()(); 1016 if (self.@org.opencms.ade.galleries.client.ui.CmsGalleryField::m_uploadTarget != null) { 1017 var dt = event.dataTransfer; 1018 var files = dt.files; 1019 self.@org.opencms.ade.galleries.client.ui.CmsGalleryField::openUploadWithFiles(Lcom/google/gwt/core/client/JavaScriptObject;)(files); 1020 } 1021 } 1022 1023 element.addEventListener("dragover", dragover, false); 1024 element.addEventListener("dragexit", dragleave, false); 1025 element.addEventListener("dragleave", dragleave, false); 1026 element.addEventListener("dragend", dragleave, false); 1027 element.addEventListener("drop", drop, false); 1028 } 1029 }-*/; 1030 1031 /** 1032 * Opens the upload dialog with the given file references to upload.<p> 1033 * 1034 * @param files the file references 1035 */ 1036 private void openUploadWithFiles(JavaScriptObject files) { 1037 1038 JsArray<CmsFileInfo> cmsFiles = files.cast(); 1039 List<CmsFileInfo> fileObjects = new ArrayList<CmsFileInfo>(); 1040 for (int i = 0; i < cmsFiles.length(); ++i) { 1041 fileObjects.add(cmsFiles.get(i)); 1042 } 1043 ((CmsDialogUploadButtonHandler)m_uploadButton.getButtonHandler()).openDialogWithFiles(fileObjects); 1044 } 1045 1046 /** 1047 * Enables the special upload button. 1048 * 1049 * @param specialUpload true if the special upload button should be enabled 1050 */ 1051 private void setSpecialUpload(boolean specialUpload) { 1052 1053 m_specialUploadButton.setVisible(specialUpload); 1054 m_uploadButton.setVisible(!specialUpload); 1055 1056 } 1057 1058 /** 1059 * Updates the value to the path for the given structure id. 1060 * 1061 * @param id a structure id 1062 */ 1063 private void updateValueFromId(CmsUUID id) { 1064 1065 CmsRpcAction<String> action = new CmsRpcAction<String>() { 1066 1067 @Override 1068 public void execute() { 1069 1070 start(0, false); 1071 CmsCoreProvider.getVfsService().getSitePath(id, this); 1072 1073 } 1074 1075 @Override 1076 protected void onResponse(String result) { 1077 1078 stop(false); 1079 m_textbox.setValue(result, true); 1080 1081 } 1082 }; 1083 action.execute(); 1084 1085 } 1086}