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.publish.client; 029 030import org.opencms.ade.publish.client.CmsPublishItemStatus.Signal; 031import org.opencms.ade.publish.shared.CmsProjectBean; 032import org.opencms.ade.publish.shared.CmsPublishGroup; 033import org.opencms.ade.publish.shared.CmsPublishGroupList; 034import org.opencms.ade.publish.shared.CmsPublishOptions; 035import org.opencms.ade.publish.shared.CmsPublishResource; 036import org.opencms.ade.publish.shared.CmsWorkflow; 037import org.opencms.ade.publish.shared.CmsWorkflowAction; 038import org.opencms.file.CmsResource; 039import org.opencms.gwt.client.ui.CmsAlertDialog; 040import org.opencms.gwt.client.ui.CmsPushButton; 041import org.opencms.gwt.client.ui.CmsScrollPanel; 042import org.opencms.gwt.client.ui.FontOpenCms; 043import org.opencms.gwt.client.ui.contenteditor.I_CmsContentEditorHandler; 044import org.opencms.gwt.client.ui.contextmenu.CmsContextMenuHandler; 045import org.opencms.gwt.client.ui.css.I_CmsConstantsBundle; 046import org.opencms.gwt.client.ui.input.CmsCheckBox; 047import org.opencms.gwt.client.ui.input.CmsSelectBox; 048import org.opencms.gwt.client.ui.input.CmsTriStateCheckBox; 049import org.opencms.gwt.client.ui.input.CmsTriStateCheckBox.State; 050import org.opencms.gwt.client.util.CmsDomUtil; 051import org.opencms.gwt.client.util.CmsMessages; 052import org.opencms.gwt.client.util.CmsScrollToBottomHandler; 053import org.opencms.util.CmsUUID; 054 055import java.util.ArrayList; 056import java.util.Collections; 057import java.util.HashSet; 058import java.util.LinkedHashMap; 059import java.util.List; 060import java.util.Map; 061import java.util.Set; 062 063import com.google.common.collect.Maps; 064import com.google.gwt.core.client.GWT; 065import com.google.gwt.core.client.Scheduler; 066import com.google.gwt.core.client.Scheduler.RepeatingCommand; 067import com.google.gwt.dom.client.Style; 068import com.google.gwt.dom.client.Style.Visibility; 069import com.google.gwt.event.dom.client.ClickEvent; 070import com.google.gwt.event.dom.client.ClickHandler; 071import com.google.gwt.event.logical.shared.ValueChangeEvent; 072import com.google.gwt.event.logical.shared.ValueChangeHandler; 073import com.google.gwt.uibinder.client.UiBinder; 074import com.google.gwt.uibinder.client.UiField; 075import com.google.gwt.uibinder.client.UiHandler; 076import com.google.gwt.user.client.ui.Composite; 077import com.google.gwt.user.client.ui.FlowPanel; 078import com.google.gwt.user.client.ui.HorizontalPanel; 079import com.google.gwt.user.client.ui.InlineLabel; 080import com.google.gwt.user.client.ui.Label; 081import com.google.gwt.user.client.ui.Panel; 082import com.google.gwt.user.client.ui.Widget; 083 084/** 085 * This is the main widget of the publish dialog.<p> 086 * 087 * It allows the user to choose which resources from the publish list should be published 088 * and/or removed from the publish list. 089 * 090 * @since 8.0.0 091 */ 092public class CmsPublishSelectPanel extends Composite 093implements I_CmsPublishSelectionChangeHandler, I_CmsPublishItemStatusUpdateHandler { 094 095 /** 096 * Data with which to update a check box. 097 */ 098 public static class CheckBoxUpdate { 099 100 /** The action (used for the tooltip). */ 101 private String m_action; 102 103 /** The new state. */ 104 private CmsTriStateCheckBox.State m_state; 105 106 /** The new text. */ 107 private String m_text; 108 109 /** 110 * Gets the action text.<P> 111 * 112 * @return the action text 113 */ 114 public String getAction() { 115 116 return m_action; 117 } 118 119 /** 120 * Gets the new state.<p> 121 * 122 * @return the new state 123 */ 124 public CmsTriStateCheckBox.State getState() { 125 126 return m_state; 127 } 128 129 /** 130 * Gets the new text.<p> 131 * 132 * @return the new text 133 */ 134 public String getText() { 135 136 return m_text; 137 } 138 139 /** 140 * Sets the action text.<p> 141 * 142 * @param action the action text 143 */ 144 public void setAction(String action) { 145 146 m_action = action; 147 } 148 149 /** 150 * Sets the new state.<p> 151 * 152 * @param state the new state 153 */ 154 public void setState(CmsTriStateCheckBox.State state) { 155 156 m_state = state; 157 } 158 159 /** 160 * Sets the new text.<p> 161 * 162 * @param text the new text 163 */ 164 public void setText(String text) { 165 166 m_text = text; 167 } 168 169 } 170 171 /** The UiBinder interface for this widget. */ 172 protected interface I_CmsPublishSelectPanelUiBinder extends UiBinder<Widget, CmsPublishSelectPanel> { 173 // empty 174 } 175 176 /** 177 * Command for adding more list items to the list of publish items.<p> 178 */ 179 protected class MoreItemsCommand implements RepeatingCommand { 180 181 /** The number of items left to add. */ 182 private int m_numItems; 183 184 /** 185 * Creates a new instance.<p> 186 * 187 * @param numItems the maximal number of items to add 188 */ 189 public MoreItemsCommand(int numItems) { 190 191 m_numItems = numItems; 192 } 193 194 /** 195 * @see com.google.gwt.core.client.Scheduler.RepeatingCommand#execute() 196 */ 197 public boolean execute() { 198 199 if (m_numItems == 0) { 200 finishLoading(); 201 return false; 202 } 203 boolean hasMore = addNextItem(); 204 if (!hasMore) { 205 finishLoading(); 206 return false; 207 } 208 m_numItems -= 1; 209 return true; 210 } 211 212 } 213 214 /** The CSS bundle used for this widget. */ 215 private static final I_CmsPublishCss CSS = I_CmsPublishLayoutBundle.INSTANCE.publishCss(); 216 217 /** 218 * When dynamically adding groups on scrolling, the number of groups should be calculated such that the total sum of resources 219 * in the groups is the smallest number greater or equal to this constant.<p> 220 */ 221 private static final int MIN_BATCH_SIZE = 20; 222 223 /** The scroll threshold for the list of problem resources. */ 224 private static final int SCROLL_THRESHOLD = 200; 225 226 /** The UiBinder instance used for this widget. */ 227 private static final I_CmsPublishSelectPanelUiBinder UI_BINDER = GWT.create(I_CmsPublishSelectPanelUiBinder.class); 228 229 /** The button for escaping from the publish dialog. */ 230 @UiField 231 protected CmsPushButton m_cancelButton; 232 233 /** Checkbox for including the contents of folders in the direct publish case. */ 234 @UiField 235 protected CmsCheckBox m_checkboxAddContents; 236 237 /** The checkbox for the "show problems only" mode. */ 238 @UiField 239 protected CmsCheckBox m_checkboxProblems; 240 241 /** The checkbox for including related resources. */ 242 @UiField 243 protected CmsCheckBox m_checkboxRelated; 244 245 /** The checkbox for including sibling resources. */ 246 @UiField 247 protected CmsCheckBox m_checkboxSiblings; 248 249 /** The panel containing the publish groups. */ 250 @UiField 251 protected Panel m_groupPanelContainer; 252 253 /** Flag to indicate whether new items are currently being added to the list. */ 254 protected boolean m_loading; 255 256 /** The data model for the publish dialog. */ 257 protected CmsPublishDataModel m_model; 258 259 /** The label which is displayed when there are no resources to publish. */ 260 @UiField 261 protected Label m_noResources; 262 263 /** The panel which shows a message telling the user the number of problems. */ 264 @UiField 265 protected Panel m_problemsPanel; 266 267 /** The project select box. */ 268 @UiField 269 protected CmsSelectBox m_projectSelector; 270 271 /** The publish dialog which contains this panel. */ 272 protected CmsPublishDialog m_publishDialog; 273 274 /** The scroll panel containing the group panel. */ 275 @UiField 276 protected CmsScrollPanel m_scrollPanel; 277 278 /** The global map of selection controllers for all groups. */ 279 protected Map<CmsUUID, CmsPublishItemSelectionController> m_selectionControllers = Maps.newHashMap(); 280 281 /** The label shown in front of the project selector. */ 282 @UiField 283 protected InlineLabel m_selectorLabel; 284 285 /** The panel containing the project selector. */ 286 @UiField 287 protected FlowPanel m_selectorPanel; 288 289 /** Label which is shown instead of the resource list when the resource list is too long. */ 290 @UiField 291 protected Label m_tooManyResources; 292 293 /** The top button bar. */ 294 @UiField 295 protected Panel m_topBar; 296 297 /** The workflow selector. */ 298 @UiField 299 protected CmsSelectBox m_workflowSelector; 300 301 /** The workflow selector label. */ 302 @UiField 303 protected InlineLabel m_workflowsLabel; 304 305 /** The action buttons. */ 306 private List<CmsPushButton> m_actionButtons; 307 308 /** The available actions. */ 309 private List<CmsWorkflowAction> m_actions; 310 311 /** The current group index used for scrolling. */ 312 private int m_currentGroupIndex; 313 314 /** The current group panel. */ 315 private CmsPublishGroupPanel m_currentGroupPanel; 316 /** The id of the virtual project used for 'direct publish'. */ 317 private CmsUUID m_directPublishId; 318 319 /** Indicates whether a previously selected project has been found. */ 320 private boolean m_foundOldProject; 321 322 /** The list of group panels for each publish list group. */ 323 private List<CmsPublishGroupPanel> m_groupPanels = new ArrayList<CmsPublishGroupPanel>(); 324 325 /** Flag indicating that the panel has been initialized. */ 326 private boolean m_initialized; 327 328 /** Checkbox for selecting/deselecting all items. */ 329 private CmsTriStateCheckBox m_selectAll; 330 331 /** Flag which indicates whether only resources with problems should be shown. */ 332 private boolean m_showProblemsOnly; 333 334 /** Indicates whether the resources are being shown (which is not done if the resource list is too long). */ 335 private boolean m_showResources = true; 336 337 /** 338 * Creates a new instance.<p> 339 * 340 * @param publishDialog the publish dialog to which this panel should belong 341 * @param projects a map of projects, where the keys are the project ids and the values are the names of the projects 342 * @param publishOptions the initial publish options 343 * @param workflows the available workflows 344 * @param selectedWorkflowId the selected workflow id 345 * @param scrollPanelHeight the available scroll panel height 346 */ 347 public CmsPublishSelectPanel( 348 CmsPublishDialog publishDialog, 349 List<CmsProjectBean> projects, 350 CmsPublishOptions publishOptions, 351 Map<String, CmsWorkflow> workflows, 352 String selectedWorkflowId, 353 int scrollPanelHeight) { 354 355 projects = new ArrayList<CmsProjectBean>(projects); 356 m_publishDialog = publishDialog; 357 m_actions = workflows.get(selectedWorkflowId).getActions(); 358 m_actionButtons = new ArrayList<CmsPushButton>(); 359 initWidget(UI_BINDER.createAndBindUi(this)); 360 String enableAddContentsStr = null; 361 boolean enableAddContents = false; 362 boolean addContent = false; 363 try { 364 enableAddContentsStr = publishOptions.getParameters().get(CmsPublishOptions.PARAM_ENABLE_INCLUDE_CONTENTS); 365 enableAddContents = (null != enableAddContentsStr) 366 && !(CmsPublishOptions.INCLUDE_CONTENTS_CHECKBOX_DISABLE.equals(enableAddContentsStr)); 367 addContent = Boolean.parseBoolean( 368 publishOptions.getParameters().get(CmsPublishOptions.PARAM_INCLUDE_CONTENTS)); 369 } catch (Exception e) { 370 // ignore; enableAddContents remains the default value 371 } 372 m_checkboxAddContents.setVisible(enableAddContents); 373 m_checkboxAddContents.setChecked(addContent); 374 if (enableAddContents) { 375 m_directPublishId = publishOptions.getProjectId(); 376 } 377 String addContentsText = Messages.get().key(Messages.GUI_CHECKBOX_ADD_CONTENT_0); 378 if (CmsPublishOptions.INCLUDE_CONTENTS_CHECKBOX_SINGULAR.equals(enableAddContentsStr)) { 379 addContentsText = Messages.get().key(Messages.GUI_CHECKBOX_ADD_CONTENT_SINGULAR_0); 380 } 381 m_checkboxAddContents.setText(addContentsText); 382 m_selectAll = new CmsTriStateCheckBox(""); 383 m_selectAll.getElement().getStyle().setMarginLeft(4, Style.Unit.PX); 384 m_selectAll.setNextStateAfterIntermediateState(State.on); 385 m_selectAll.addValueChangeHandler(new ValueChangeHandler<CmsTriStateCheckBox.State>() { 386 387 public void onValueChange(ValueChangeEvent<State> event) { 388 389 State state = event.getValue(); 390 if (state == State.on) { 391 m_model.signalAll(Signal.publish); 392 } else if (state == State.off) { 393 m_model.signalAll(Signal.unpublish); 394 } 395 } 396 }); 397 m_topBar.add(m_selectAll); 398 399 m_scrollPanel.getElement().getStyle().setPropertyPx(CmsDomUtil.Style.maxHeight.toString(), scrollPanelHeight); 400 m_checkboxProblems.setVisible(false); 401 CmsMessages messages = Messages.get(); 402 LinkedHashMap<String, String> workflowSelectorItems = new LinkedHashMap<String, String>(); 403 for (CmsWorkflow workflow : workflows.values()) { 404 workflowSelectorItems.put(workflow.getId(), workflow.getNiceName()); 405 } 406 LinkedHashMap<String, String> projectSelectItems = new LinkedHashMap<String, String>(); 407 Collections.<CmsProjectBean> sort(projects); 408 409 m_foundOldProject = false; 410 boolean selectedWorkflowProject = false; 411 for (CmsProjectBean project : projects) { 412 if (project.isWorkflowProject()) { 413 workflowSelectorItems.put(project.getId().toString(), project.getName()); 414 if (project.getId().equals(publishOptions.getProjectId())) { 415 selectedWorkflowProject = true; 416 } 417 } else { 418 projectSelectItems.put(project.getId().toString(), project.getName()); 419 // look if the project id from the last publish list is among the available projects. 420 // (this might not be the case if the project has been deleted in the meantime.) 421 if (project.getId().equals(publishOptions.getProjectId())) { 422 m_foundOldProject = true; 423 } 424 } 425 } 426 427 m_workflowSelector.setItems(workflowSelectorItems); 428 429 m_workflowSelector.addStyleName(CSS.selector()); 430 if (!(workflows.size() > 1)) { 431 m_workflowSelector.setEnabled(false); 432 } 433 434 m_workflowsLabel.setText(messages.key(Messages.GUI_PUBLISH_WORKFLOW_SELECT_0)); 435 436 m_projectSelector.setItems(projectSelectItems); 437 m_projectSelector.addStyleName(CSS.selector()); 438 if (!(null == publishOptions.getProjectId()) && m_foundOldProject) { 439 m_projectSelector.setFormValueAsString(publishOptions.getProjectId().toString()); 440 } 441 442 m_checkboxRelated.setChecked(publishOptions.isIncludeRelated()); 443 m_checkboxSiblings.setChecked(publishOptions.isIncludeSiblings()); 444 if (selectedWorkflowProject) { 445 m_projectSelector.setEnabled(false); 446 m_workflowSelector.setFormValueAsString(publishOptions.getProjectId().toString()); 447 } else { 448 m_workflowSelector.setFormValueAsString(selectedWorkflowId); 449 } 450 m_cancelButton.setText(messages.key(Messages.GUI_PUBLISH_DIALOG_CANCEL_BUTTON_0)); 451 m_cancelButton.setUseMinWidth(true); 452 m_noResources.setText(messages.key(Messages.GUI_PUBLISH_DIALOG_NO_RES_0)); 453 m_checkboxSiblings.setText(messages.key(Messages.GUI_PUBLISH_CHECKBOXES_SIBLINGS_0)); 454 m_checkboxRelated.setText(messages.key(Messages.GUI_PUBLISH_CHECKBOXES_REL_RES_0)); 455 m_checkboxProblems.setText(messages.key(Messages.GUI_PUBLISH_CHECKBOXES_PROBLEMS_0)); 456 m_selectorLabel.setText(messages.key(Messages.GUI_PUBLISH_TOP_PANEL_RIGHT_LABEL_0)); 457 addScrollHandler(); 458 m_initialized = true; 459 } 460 461 /** 462 * Formats a number of publish resources in a more user-friendly form.<p> 463 * 464 * @param resourceCount a number of resources 465 * 466 * @return the formatted number of resources 467 */ 468 public static String formatResourceCount(int resourceCount) { 469 470 return Messages.get().key(Messages.GUI_RESOURCE_COUNT_1, "" + resourceCount); 471 } 472 473 /** 474 * Updates the state of a check box used for selecting/deselecting items.<p> 475 * 476 * @param states the selection states of the items for the check box 477 * 478 * @return the data needed to update the check box 479 */ 480 public static CheckBoxUpdate updateCheckbox(CmsPublishItemStateSummary states) { 481 482 CheckBoxUpdate result = new CheckBoxUpdate(); 483 boolean hasPublish = states.getPublishCount() > 0; 484 boolean hasNormal = states.getNormalCount() > 0; 485 String actionSelectAll = Messages.get().key(Messages.GUI_CHECKBOX_SELECT_ALL_0); 486 String textDeselectAll = Messages.get().key(Messages.GUI_CHECKBOX_DESELECT_ALL_0); 487 String some = Messages.get().key( 488 Messages.GUI_CHECKBOX_SOME_2, 489 "" + states.getPublishCount(), 490 "" + (states.getPublishCount() + states.getNormalCount())); 491 String all = Messages.get().key(Messages.GUI_CHECKBOX_ALL_0); 492 String none = Messages.get().key(Messages.GUI_CHECKBOX_NONE_0); 493 494 if (hasNormal && hasPublish) { 495 result.setAction(actionSelectAll); 496 result.setText(some); 497 result.setState(CmsTriStateCheckBox.State.middle); 498 } else if (hasNormal) { 499 result.setAction(actionSelectAll); 500 result.setText(none); 501 result.setState(CmsTriStateCheckBox.State.off); 502 } else if (hasPublish) { 503 result.setAction(textDeselectAll); 504 result.setText(all); 505 result.setState(CmsTriStateCheckBox.State.on); 506 } else { 507 result.setText(none); 508 result.setAction(actionSelectAll); 509 result.setState(CmsTriStateCheckBox.State.off); 510 } 511 return result; 512 } 513 514 /** 515 * Check for problems with new/deleted folders in the publish selection.<p> 516 * 517 * @param resourceIds the ids of the resources selected for publishing 518 * @return true if there are problems with nested 519 */ 520 public boolean checkForProblems(Set<CmsUUID> resourceIds) { 521 522 List<CmsPublishResource> pubResources = new ArrayList<CmsPublishResource>(); 523 Set<CmsUUID> publishIds = getResourcesToPublish(); 524 for (CmsUUID publishId : publishIds) { 525 pubResources.add(m_model.getPublishResources().get(publishId)); 526 } 527 for (CmsPublishResource pubResource : pubResources) { 528 String parentPath = CmsResource.getParentFolder(pubResource.getName()); 529 CmsPublishResource parent = m_model.getPublishResourcesByPath().get(parentPath); 530 if (parent != null) { 531 boolean parentIsNew = parent.getResourceState().isNew(); 532 boolean parentIsDeleted = parent.getResourceState().isDeleted(); 533 if (parentIsNew || parentIsDeleted) { 534 if (!resourceIds.contains(parent.getId())) { 535 String title = Messages.get().key(Messages.ERR_CANT_PUBLISH_RESOURCE_TITLE_0); 536 String message = null; 537 if (parentIsNew) { 538 message = Messages.get().key( 539 Messages.ERR_PUBLISH_CANT_PUBLISH_NEW_RESOURCE_2, 540 pubResource.getName(), 541 parent.getName()); 542 } 543 if (parentIsDeleted) { 544 message = Messages.get().key( 545 Messages.ERR_PUBLISH_CANT_PUBLISH_DELETED_RESOURCE_2, 546 pubResource.getName(), 547 parent.getName()); 548 } 549 CmsAlertDialog alert = new CmsAlertDialog(title, message); 550 alert.center(); 551 return true; 552 } 553 } 554 } 555 } 556 return false; 557 } 558 559 /** 560 * Returns the buttons of this panel which should be shown as the buttons of the publish dialog.<p> 561 * 562 * @return a list of buttons 563 */ 564 public List<CmsPushButton> getButtons() { 565 566 List<CmsPushButton> result = new ArrayList<CmsPushButton>(); 567 result.add(m_cancelButton); 568 m_actionButtons.clear(); 569 boolean enable = shouldEnablePublishButton(); 570 if (m_actions != null) { 571 for (final CmsWorkflowAction action : m_actions) { 572 CmsPushButton actionButton = new CmsPushButton(); 573 actionButton.setText(action.getLabel()); 574 actionButton.setUseMinWidth(true); 575 actionButton.addClickHandler(new ClickHandler() { 576 577 public void onClick(ClickEvent event) { 578 579 executeAction(action); 580 } 581 }); 582 actionButton.setEnabled(enable); 583 m_actionButtons.add(actionButton); 584 } 585 } 586 result.addAll(m_actionButtons); 587 return result; 588 } 589 590 /** 591 * Returns the ids of the resources which should be published.<p> 592 * 593 * @return a set of id strings 594 */ 595 public Set<CmsUUID> getResourcesToPublish() { 596 597 return new HashSet<CmsUUID>(m_model.getPublishIds()); 598 } 599 600 /** 601 * Returns the set of ids of resources which have been selected for removal.<p> 602 * 603 * @return a set of id strings 604 */ 605 public Set<CmsUUID> getResourcesToRemove() { 606 607 Set<CmsUUID> result = new HashSet<CmsUUID>(m_model.getRemoveIds()); 608 result.addAll(m_model.getIdsOfAlreadyPublishedResources()); 609 return result; 610 } 611 612 /** 613 * Gets the global map of selection controllers.<p> 614 * 615 * @return the map of selection controller 616 */ 617 public Map<CmsUUID, CmsPublishItemSelectionController> getSelectionControllers() { 618 619 return m_selectionControllers; 620 } 621 622 /** 623 * Returns if the resource list is being shown.<p> 624 * 625 * The resource list is now shown if it is too long.<p> 626 * 627 * @return true if the resource list is being shown 628 */ 629 public boolean isShowResources() { 630 631 return m_showResources; 632 } 633 634 /** 635 * @see org.opencms.ade.publish.client.I_CmsPublishSelectionChangeHandler#onChangePublishSelection() 636 */ 637 public void onChangePublishSelection() { 638 639 enableActions(shouldEnablePublishButton()); 640 Map<Integer, CmsPublishItemStateSummary> states = m_model.computeGroupSelectionStates(); 641 for (Map.Entry<Integer, CmsPublishItemStateSummary> entry : states.entrySet()) { 642 int key = entry.getKey().intValue(); 643 if (key == -1) { 644 updateCheckboxState(entry.getValue()); 645 } else { 646 if (key < m_groupPanels.size()) { 647 m_groupPanels.get(key).updateCheckboxState(entry.getValue()); 648 } 649 } 650 } 651 } 652 653 /** 654 * Sets the publish groups used by this widget.<p> 655 * 656 * @param groups the new publish groups 657 * @param newData true if the groups are new data which has been loaded 658 * @param defaultWorkflow if not null, selects the given workflow 659 */ 660 public void setGroupList(CmsPublishGroupList groups, boolean newData, String defaultWorkflow) { 661 662 if (groups.getToken() == null) { 663 setGroups(groups.getGroups(), newData, defaultWorkflow); 664 setShowResources(true, ""); 665 } else { 666 setShowResources(false, groups.getTooManyResourcesMessage()); 667 } 668 boolean isDirectPublish = m_publishDialog.getPublishOptions().getProjectId().equals(m_directPublishId); 669 m_checkboxAddContents.setVisible(isDirectPublish); 670 } 671 672 /** 673 * Sets the mode to either show resources, or only show a "too many resources" message.<p> 674 * In the latter case, the check boxes for the siblings/related resources will be deactivated.<p> 675 * 676 * @param showResources true if the resource list should be shown, false if only the given message should be shown 677 * @param tooManyResourcesMessage the message to show if there are too many resources to display 678 */ 679 public void setShowResources(boolean showResources, String tooManyResourcesMessage) { 680 681 m_showResources = showResources; 682 m_checkboxRelated.setEnabled(showResources); 683 m_checkboxRelated.setChecked(showResources && m_publishDialog.getPublishOptions().isIncludeRelated()); 684 m_checkboxSiblings.setEnabled(showResources); 685 m_checkboxSiblings.setChecked(showResources && m_publishDialog.getPublishOptions().isIncludeSiblings()); 686 m_groupPanelContainer.setVisible(showResources); 687 m_tooManyResources.setVisible(!showResources); 688 m_tooManyResources.setText(tooManyResourcesMessage); 689 m_selectAll.setVisible(showResources); 690 enableActions(true); 691 if (!showResources) { 692 m_checkboxProblems.setVisible(false); 693 m_noResources.setVisible(false); 694 m_scrollPanel.setVisible(false); 695 } else { 696 addMoreListItems(); 697 showProblemCount(m_model.countProblems()); 698 onChangePublishSelection(); 699 } 700 } 701 702 /** 703 * Returns true if the publish button should be enabled.<p> 704 * 705 * @return true if the publish button should be enabled 706 */ 707 public boolean shouldEnablePublishButton() { 708 709 boolean enablePublishButton = !m_showResources 710 || (getResourcesToRemove().size() != 0) 711 || (getResourcesToPublish().size() != 0); 712 return enablePublishButton; 713 714 } 715 716 /** 717 * @see org.opencms.ade.publish.client.I_CmsPublishItemStatusUpdateHandler#update(org.opencms.util.CmsUUID, org.opencms.ade.publish.client.CmsPublishItemStatus) 718 */ 719 public void update(CmsUUID id, CmsPublishItemStatus status) { 720 721 CmsPublishItemSelectionController selectionController = m_selectionControllers.get(id); 722 if (selectionController != null) { 723 selectionController.update(status); 724 } 725 } 726 727 /** 728 * Updates the dialog title.<p> 729 **/ 730 public void updateDialogTitle() { 731 732 String title; 733 if ((m_model != null) && (m_model.getGroups().size() > 1)) { 734 title = Messages.get().key( 735 Messages.GUI_PUBLISH_DIALOG_TITLE_3, 736 m_publishDialog.getSelectedWorkflow().getNiceName(), 737 String.valueOf(m_model.getGroups().size()), 738 String.valueOf(m_model.getPublishResources().size())); 739 } else { 740 title = m_publishDialog.getSelectedWorkflow().getNiceName(); 741 } 742 m_publishDialog.setCaption(title); 743 } 744 745 /** 746 * Adds more publish list items to the panel.<p> 747 */ 748 protected void addMoreListItems() { 749 750 MoreItemsCommand cmd = new MoreItemsCommand(MIN_BATCH_SIZE); 751 // we use a repeating command instead of a loop because a loop locks up the browser for too long in IE7. 752 Scheduler.get().scheduleFixedDelay(cmd, 0); 753 } 754 755 /** 756 * Tries to add a new publish list item to the panel, and returns false if there aren't any items left.<p> 757 * 758 * @return true if an item could be added, false if no items are left 759 */ 760 protected boolean addNextItem() { 761 762 // this method is so complicated because to add the next item, 763 // you may need to skip to another group and create the corresponding widget 764 765 if (m_model.isEmpty()) { 766 return false; 767 } 768 // now we know there is at least one group 769 if (m_currentGroupPanel == null) { 770 // this case happens if the method is called for the first time 771 m_currentGroupPanel = addGroupPanel(m_model.getGroups().get(0), 0); 772 } 773 while (true) { 774 if (m_currentGroupPanel.hasMoreItems()) { 775 // found next item in the current group 776 boolean found = m_currentGroupPanel.addNextItem(); 777 if (found) { 778 m_scrollPanel.onResizeDescendant(); 779 return true; 780 } 781 } else if (m_currentGroupIndex < (m_model.getGroups().size() - 1)) { 782 // didn't find item in the current group, so skip to next group if available 783 // and create the group widget 784 m_currentGroupIndex += 1; 785 m_currentGroupPanel = addGroupPanel(m_model.getGroups().get(m_currentGroupIndex), m_currentGroupIndex); 786 } else { 787 // all groups exhausted 788 m_scrollPanel.onResizeDescendant(); 789 return false; 790 } 791 } 792 } 793 794 /** 795 * Executes the given action.<p> 796 * 797 * @param action the action to execute on the selected resources 798 */ 799 protected void executeAction(CmsWorkflowAction action) { 800 801 m_publishDialog.executeAction(action); 802 } 803 804 /** 805 * The method to call when the items have finished being loaded into the list.<p> 806 */ 807 protected void finishLoading() { 808 809 m_loading = false; 810 onChangePublishSelection(); 811 } 812 813 /** 814 * Event handler for the 'add contents' check box.<p> 815 * 816 * @param event the click event 817 */ 818 @UiHandler("m_checkboxAddContents") 819 protected void onAddContentsClick(ClickEvent event) { 820 821 setAddContents(m_checkboxAddContents.isChecked()); 822 m_publishDialog.updateResourceList(); 823 } 824 825 /** 826 * The event handler for the Cancel button.<p> 827 * 828 * @param e the event 829 */ 830 @UiHandler("m_cancelButton") 831 protected void onClickCancel(ClickEvent e) { 832 833 m_publishDialog.onCancel(); 834 } 835 836 /** 837 * Handles the click event for problem resources check box.<p> 838 * 839 * @param event the click event 840 * 841 * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) 842 */ 843 @UiHandler("m_checkboxProblems") 844 protected void onProblemClick(ClickEvent event) { 845 846 setProblemMode(m_checkboxProblems.isChecked()); 847 } 848 849 /** 850 * Handling the value change event for the project selector.<p> 851 * 852 * @param event the change event 853 * 854 * @see com.google.gwt.event.logical.shared.ValueChangeHandler#onValueChange(ValueChangeEvent) 855 */ 856 @UiHandler("m_projectSelector") 857 protected void onProjectChange(ValueChangeEvent<String> event) { 858 859 if (m_initialized) { 860 m_publishDialog.setProjectId(new CmsUUID(event.getValue())); 861 m_publishDialog.setProjectChanged(); 862 m_publishDialog.updateResourceList(); 863 } 864 } 865 866 /** 867 * Handles the click event for related resources check box.<p> 868 * 869 * @param event the click event 870 * 871 * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) 872 */ 873 @UiHandler("m_checkboxRelated") 874 protected void onRelatedClick(ClickEvent event) { 875 876 if (!m_showResources) { 877 return; 878 } 879 m_publishDialog.setIncludeRelated(m_checkboxRelated.isChecked()); 880 m_publishDialog.updateResourceList(); 881 } 882 883 /** 884 * Handles the click event for sibling resources check box.<p> 885 * 886 * @param event the click event 887 * 888 * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) 889 */ 890 @UiHandler("m_checkboxSiblings") 891 protected void onSiblingClick(ClickEvent event) { 892 893 if (!m_showResources) { 894 return; 895 } 896 m_publishDialog.setIncludeSiblings(m_checkboxSiblings.isChecked()); 897 m_publishDialog.updateResourceList(); 898 } 899 900 /** 901 * Handling the value change event for the project selector.<p> 902 * 903 * @param event the change event 904 * 905 * @see com.google.gwt.event.logical.shared.ValueChangeHandler#onValueChange(ValueChangeEvent) 906 */ 907 @UiHandler("m_workflowSelector") 908 protected void onWorkflowChange(ValueChangeEvent<String> event) { 909 910 if (m_initialized) { 911 m_publishDialog.setWorkflowId(event.getValue()); 912 // check for workflow project 913 if (!m_publishDialog.getSelectedWorkflow().getId().equals(event.getValue())) { 914 m_publishDialog.setProjectId(new CmsUUID(event.getValue())); 915 m_projectSelector.setEnabled(false); 916 } else { 917 m_projectSelector.setEnabled(true); 918 m_publishDialog.setProjectId(new CmsUUID(m_projectSelector.getFormValueAsString())); 919 } 920 m_actions = m_publishDialog.getSelectedWorkflow().getActions(); 921 m_publishDialog.updateResourceList(); 922 } 923 } 924 925 /** 926 * Sets the publish groups.<p> 927 * 928 * @param groups the list of publish groups 929 * @param newData true if the data is new 930 */ 931 protected void setGroups(List<CmsPublishGroup> groups, boolean newData) { 932 933 m_model = new CmsPublishDataModel(groups, this); 934 m_model.setSelectionChangeAction(new Runnable() { 935 936 public void run() { 937 938 onChangePublishSelection(); 939 } 940 }); 941 m_currentGroupIndex = 0; 942 m_currentGroupPanel = null; 943 m_problemsPanel.clear(); 944 if (newData) { 945 m_showProblemsOnly = false; 946 m_checkboxProblems.setChecked(false); 947 m_checkboxProblems.setVisible(false); 948 m_problemsPanel.setVisible(false); 949 } 950 m_groupPanels.clear(); 951 m_groupPanelContainer.clear(); 952 m_scrollPanel.onResizeDescendant(); 953 enableActions(false); 954 955 int numGroups = groups.size(); 956 setResourcesVisible(numGroups > 0); 957 958 if (numGroups == 0) { 959 return; 960 } 961 enableActions(true); 962 addMoreListItems(); 963 showProblemCount(m_model.countProblems()); 964 } 965 966 /** 967 * Sets the publish groups.<p> 968 * 969 * @param groups the list of publish groups 970 * @param newData true if the data is new 971 * @param defaultWorkflow the default workflow id 972 */ 973 protected void setGroups(List<CmsPublishGroup> groups, boolean newData, String defaultWorkflow) { 974 975 m_model = new CmsPublishDataModel(groups, this); 976 m_model.setSelectionChangeAction(new Runnable() { 977 978 public void run() { 979 980 onChangePublishSelection(); 981 } 982 }); 983 m_currentGroupIndex = 0; 984 m_currentGroupPanel = null; 985 m_problemsPanel.clear(); 986 if (newData) { 987 m_showProblemsOnly = false; 988 m_checkboxProblems.setChecked(false); 989 m_checkboxProblems.setVisible(false); 990 m_problemsPanel.setVisible(false); 991 } 992 m_groupPanels.clear(); 993 m_groupPanelContainer.clear(); 994 m_scrollPanel.onResizeDescendant(); 995 enableActions(false); 996 997 int numGroups = groups.size(); 998 setResourcesVisible(numGroups > 0); 999 1000 if (numGroups == 0) { 1001 return; 1002 } 1003 enableActions(true); 1004 addMoreListItems(); 1005 showProblemCount(m_model.countProblems()); 1006 1007 if (defaultWorkflow != null) { 1008 m_workflowSelector.setFormValue(defaultWorkflow, false); 1009 m_publishDialog.setWorkflowId(defaultWorkflow); 1010 m_actions = m_publishDialog.getSelectedWorkflow().getActions(); 1011 m_publishDialog.setPanel(CmsPublishDialog.PANEL_SELECT); 1012 } 1013 } 1014 1015 /** 1016 * Enables or disables the "only show resources with problems" mode.<p> 1017 * 1018 * @param enabled if true, enable the mode, else disable it 1019 */ 1020 protected void setProblemMode(boolean enabled) { 1021 1022 m_showProblemsOnly = enabled; 1023 setGroups(m_model.getGroups(), false, null); 1024 } 1025 1026 /** 1027 * The method which should be called when new items start being inserted into the list.<p> 1028 */ 1029 protected void startLoading() { 1030 1031 m_loading = true; 1032 } 1033 1034 /** 1035 * Gets the context menu handler for the publish items' context menus.<p> 1036 * 1037 * @return the context menu handler 1038 */ 1039 CmsContextMenuHandler getContextMenuHandler() { 1040 1041 return m_publishDialog.getContextMenuHandler(); 1042 1043 } 1044 1045 /** 1046 * Returns the content editor handler.<p> 1047 * 1048 * @return the content editor handler 1049 */ 1050 I_CmsContentEditorHandler getEditorHandler() { 1051 1052 return m_publishDialog.getEditorHandler(); 1053 } 1054 1055 /** 1056 * Adds a new group panel.<p> 1057 * 1058 * @param group the publish group for which a panel should be added 1059 * @param currentIndex the index of the publish group 1060 * 1061 * @return the publish group panel which has been added 1062 */ 1063 private CmsPublishGroupPanel addGroupPanel(CmsPublishGroup group, int currentIndex) { 1064 1065 String header = group.getName(); 1066 CmsPublishGroupPanel groupPanel = new CmsPublishGroupPanel( 1067 group, 1068 header, 1069 currentIndex, 1070 this, 1071 m_model, 1072 m_selectionControllers, 1073 getContextMenuHandler(), 1074 getEditorHandler(), 1075 m_showProblemsOnly); 1076 if (m_model.hasSingleGroup()) { 1077 groupPanel.hideGroupSelectCheckBox(); 1078 } 1079 m_groupPanels.add(groupPanel); 1080 m_groupPanelContainer.add(groupPanel); 1081 return groupPanel; 1082 } 1083 1084 /** 1085 * Adds the scroll handler to the scroll panel which makes more groups visible when the user 1086 * scrolls to the bottom.<p> 1087 */ 1088 private void addScrollHandler() { 1089 1090 m_scrollPanel.addScrollHandler(new CmsScrollToBottomHandler(new Runnable() { 1091 1092 /** 1093 * @see java.lang.Runnable#run() 1094 */ 1095 public void run() { 1096 1097 if (!m_loading) { 1098 startLoading(); 1099 addMoreListItems(); 1100 } 1101 } 1102 }, SCROLL_THRESHOLD)); 1103 1104 } 1105 1106 /** 1107 * Enables action buttons.<p> 1108 * 1109 * @param enable <code>true</code> to enable the action buttons 1110 */ 1111 private void enableActions(boolean enable) { 1112 1113 for (CmsPushButton button : m_actionButtons) { 1114 button.setEnabled(enable); 1115 } 1116 } 1117 1118 /** 1119 * Enables / disables the 'add contents' option in the publish options object.<p> 1120 * 1121 * @param addContents true if folder contents should be added 1122 */ 1123 private void setAddContents(boolean addContents) { 1124 1125 m_publishDialog.getPublishOptions().getParameters().put( 1126 CmsPublishOptions.PARAM_INCLUDE_CONTENTS, 1127 "" + addContents); 1128 } 1129 1130 /** 1131 * Shows either the scroll panel or the "no resources" label and hides the other one.<p> 1132 * 1133 * @param visible if true, set the scroll panel to visible, otherwise the "no resources" label 1134 */ 1135 private void setResourcesVisible(boolean visible) { 1136 1137 m_noResources.setVisible(!visible); 1138 m_scrollPanel.setVisible(visible); 1139 m_topBar.getElement().getStyle().setVisibility(visible ? Visibility.VISIBLE : Visibility.HIDDEN); 1140 m_checkboxSiblings.setVisible(true); 1141 m_checkboxRelated.setVisible(true); 1142 } 1143 1144 /** 1145 * Shows the problem count in the panel.<p> 1146 * 1147 * @param numProblems the number of resources with publish problems 1148 */ 1149 private void showProblemCount(int numProblems) { 1150 1151 m_problemsPanel.clear(); 1152 if (numProblems > 0) { 1153 HorizontalPanel errorBox = new HorizontalPanel(); 1154 Widget warnIcon = FontOpenCms.WARNING.getWidget(20, I_CmsConstantsBundle.INSTANCE.css().colorWarning()); 1155 String message = Messages.get().key(Messages.GUI_PUBLISH_DIALOG_PROBLEM_1, "" + numProblems); 1156 errorBox.add(warnIcon); 1157 errorBox.add(new Label(message)); 1158 m_problemsPanel.add(errorBox); 1159 m_problemsPanel.setVisible(true); 1160 } 1161 m_checkboxProblems.setVisible(numProblems > 0); 1162 } 1163 1164 /** 1165 * Updates the state of the check box for all items.<p> 1166 * 1167 * @param value the state to use to update the check box 1168 */ 1169 private void updateCheckboxState(CmsPublishItemStateSummary value) { 1170 1171 CheckBoxUpdate update = updateCheckbox(value); 1172 m_selectAll.setText(update.getText()); 1173 m_selectAll.setTitle(update.getAction()); 1174 m_selectAll.setState(update.getState(), false); 1175 1176 } 1177}