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