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