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.ui.sitemap; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.CmsResourceFilter; 033import org.opencms.gwt.CmsIconUtil; 034import org.opencms.gwt.shared.CmsGwtConstants; 035import org.opencms.i18n.CmsLocaleGroup; 036import org.opencms.i18n.CmsLocaleGroupService; 037import org.opencms.main.CmsException; 038import org.opencms.main.CmsLog; 039import org.opencms.main.OpenCms; 040import org.opencms.site.CmsSite; 041import org.opencms.ui.A_CmsUI; 042import org.opencms.ui.CmsVaadinUtils; 043import org.opencms.ui.FontOpenCms; 044import org.opencms.ui.Messages; 045import org.opencms.ui.components.CmsErrorDialog; 046import org.opencms.ui.components.OpenCmsTheme; 047import org.opencms.util.CmsUUID; 048import org.opencms.workplace.explorer.CmsResourceUtil; 049 050import java.util.Collection; 051import java.util.List; 052import java.util.Locale; 053 054import org.apache.commons.logging.Log; 055 056import com.google.common.collect.Lists; 057import com.vaadin.server.Resource; 058import com.vaadin.ui.CssLayout; 059import com.vaadin.ui.JavaScript; 060import com.vaadin.ui.Notification; 061import com.vaadin.v7.data.Property.ValueChangeEvent; 062import com.vaadin.v7.data.Property.ValueChangeListener; 063import com.vaadin.v7.ui.ComboBox; 064import com.vaadin.v7.ui.VerticalLayout; 065 066/** 067 * View used to compare sitemaps across locales.<p> 068 */ 069public class CmsLocaleComparePanel extends VerticalLayout implements I_CmsLocaleCompareContext { 070 071 /** Icon for the main locale option in select boxes. */ 072 public static final Resource MAIN_LOCALE_ICON = FontOpenCms.CIRCLE_INFO; 073 074 /** The logger instance for this class. */ 075 private static final Log LOG = CmsLog.getLog(CmsLocaleComparePanel.class); 076 077 /** The serial version id. */ 078 private static final long serialVersionUID = 1L; 079 080 /** The parent layout of the tree. */ 081 protected CssLayout m_treeContainer = new CssLayout(); 082 083 /** The selected comparison locale. */ 084 private Locale m_comparisonLocale; 085 086 /** The comparison locale selector. */ 087 private ComboBox m_comparisonLocaleSelector; 088 089 /** The current root of the tree. */ 090 private CmsResource m_currentRoot; 091 092 /** Flag which is set while the user switches one of the locales. */ 093 private boolean m_handlingLocaleChange; 094 095 /** The root locale (locale of the root resource). */ 096 private Locale m_rootLocale; 097 098 /** The root locale selector. */ 099 private ComboBox m_rootLocaleSelector; 100 101 /** 102 * Creates a new instance.<p> 103 * 104 * @param id the id of a sitemap entry 105 */ 106 public CmsLocaleComparePanel(String id) { 107 108 super(); 109 Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(A_CmsUI.getCmsObject()); 110 A_CmsUI.get().setLocale(locale); 111 try { 112 initialize(new CmsUUID(id), null); 113 } catch (CmsException e) { 114 LOG.error(e.getLocalizedMessage(), e); 115 CmsErrorDialog.showErrorDialog(e); 116 } 117 } 118 119 /** 120 * @see org.opencms.ui.sitemap.I_CmsLocaleCompareContext#getComparisonLocale() 121 */ 122 public Locale getComparisonLocale() { 123 124 return m_comparisonLocale; 125 126 } 127 128 /** 129 * Gets the locales selectable as comparison locales.<p> 130 * 131 * @return the possible comparison locales 132 */ 133 public List<Locale> getComparisonLocales() { 134 135 CmsObject cms = A_CmsUI.getCmsObject(); 136 cms.getLocaleGroupService(); 137 List<Locale> result = CmsLocaleGroupService.getPossibleLocales(cms, m_currentRoot); 138 return result; 139 } 140 141 /** 142 * @see org.opencms.ui.sitemap.I_CmsLocaleCompareContext#getLocaleGroup() 143 */ 144 public CmsLocaleGroup getLocaleGroup() { 145 146 try { 147 CmsObject cms = A_CmsUI.getCmsObject(); 148 CmsLocaleGroupService service = cms.getLocaleGroupService(); 149 return service.readLocaleGroup(m_currentRoot); 150 } catch (Exception e) { 151 LOG.error(e.getLocalizedMessage(), e); 152 return null; 153 } 154 155 } 156 157 /** 158 * @see org.opencms.ui.sitemap.I_CmsLocaleCompareContext#getRoot() 159 */ 160 public CmsResource getRoot() { 161 162 return m_currentRoot; 163 } 164 165 /** 166 * @see org.opencms.ui.sitemap.I_CmsLocaleCompareContext#getRootLocale() 167 */ 168 public Locale getRootLocale() { 169 170 return m_rootLocale; 171 } 172 173 /** 174 * Initializes the locale comparison view.<p> 175 * 176 * @param id the structure id of the currrent sitemap root entry 177 * @param initialComparisonLocale if not null, the initially selected ccomparison locale 178 * 179 * @throws CmsException if something goes wrong 180 */ 181 public void initialize(CmsUUID id, Locale initialComparisonLocale) throws CmsException { 182 183 removeAllComponents(); 184 CmsObject cms = A_CmsUI.getCmsObject(); 185 CmsResource res = cms.readResource(id); 186 m_currentRoot = res; 187 CmsSite site = OpenCms.getSiteManager().getSiteForRootPath(res.getRootPath()); 188 189 Locale rootLocale = OpenCms.getLocaleManager().getDefaultLocale(cms, res); 190 m_rootLocale = rootLocale; 191 Locale mainLocale = site.getMainTranslationLocale(null); 192 List<Locale> secondaryLocales = site.getSecondaryTranslationLocales(); 193 194 List<Locale> possibleLocaleSelections = getMainLocaleSelectOptions(cms, res, mainLocale, secondaryLocales); 195 m_rootLocaleSelector = new ComboBox(); 196 m_rootLocaleSelector.addStyleName("o-sitemap-localeselect"); 197 m_rootLocaleSelector.setNullSelectionAllowed(false); 198 for (Locale selectableLocale : possibleLocaleSelections) { 199 m_rootLocaleSelector.addItem(selectableLocale); 200 m_rootLocaleSelector.setItemIcon(selectableLocale, FontOpenCms.SPACE); 201 m_rootLocaleSelector.setItemCaption( 202 selectableLocale, 203 selectableLocale.getDisplayName(A_CmsUI.get().getLocale())); 204 } 205 m_rootLocaleSelector.setItemIcon(mainLocale, MAIN_LOCALE_ICON); 206 m_rootLocaleSelector.setValue(m_rootLocale); 207 m_rootLocaleSelector.addValueChangeListener(new ValueChangeListener() { 208 209 private static final long serialVersionUID = 1L; 210 211 @SuppressWarnings("synthetic-access") 212 public void valueChange(ValueChangeEvent event) { 213 214 if (!m_handlingLocaleChange) { 215 m_handlingLocaleChange = true; 216 try { 217 Locale newLocale = (Locale)(event.getProperty().getValue()); 218 switchToLocale(newLocale); 219 } catch (Exception e) { 220 LOG.error(e.getLocalizedMessage(), e); 221 CmsErrorDialog.showErrorDialog(e); 222 } finally { 223 m_handlingLocaleChange = false; 224 } 225 } 226 } 227 }); 228 229 m_comparisonLocaleSelector = new ComboBox(); 230 m_comparisonLocaleSelector.addStyleName("o-sitemap-localeselect"); 231 m_comparisonLocaleSelector.setNullSelectionAllowed(false); 232 233 List<Locale> comparisonLocales = getComparisonLocales(); 234 Locale selectedComparisonLocale = null; 235 for (Locale comparisonLocale : comparisonLocales) { 236 m_comparisonLocaleSelector.addItem(comparisonLocale); 237 m_comparisonLocaleSelector.setItemIcon(comparisonLocale, FontOpenCms.SPACE); 238 m_comparisonLocaleSelector.setItemCaption( 239 comparisonLocale, 240 comparisonLocale.getDisplayName(A_CmsUI.get().getLocale())); 241 if ((selectedComparisonLocale == null) && !comparisonLocale.equals(m_rootLocale)) { 242 selectedComparisonLocale = comparisonLocale; 243 } 244 if ((initialComparisonLocale != null) 245 && comparisonLocale.equals(initialComparisonLocale) 246 && !comparisonLocale.equals(m_rootLocale)) { 247 // if an initial comparison locale is given, it should have priority over the first comparison locale 248 selectedComparisonLocale = comparisonLocale; 249 } 250 251 } 252 m_comparisonLocale = selectedComparisonLocale; 253 m_comparisonLocaleSelector.setValue(selectedComparisonLocale); 254 m_comparisonLocaleSelector.setItemIcon(mainLocale, MAIN_LOCALE_ICON); 255 256 m_comparisonLocaleSelector.addValueChangeListener(new ValueChangeListener() { 257 258 private static final long serialVersionUID = 1L; 259 260 @SuppressWarnings("synthetic-access") 261 public void valueChange(ValueChangeEvent event) { 262 263 if (!m_handlingLocaleChange) { 264 m_handlingLocaleChange = true; 265 try { 266 Locale locale = (Locale)(event.getProperty().getValue()); 267 if (m_rootLocale.equals(locale)) { 268 Locale oldComparisonLocale = m_comparisonLocale; 269 if (getLocaleGroup().getResourcesByLocale().keySet().contains(oldComparisonLocale)) { 270 m_comparisonLocale = locale; 271 switchToLocale(oldComparisonLocale); 272 updateLocaleWidgets(); 273 } else { 274 Notification.show( 275 CmsVaadinUtils.getMessageText( 276 Messages.GUI_LOCALECOMPARE_CANNOT_SWITCH_COMPARISON_LOCALE_0)); 277 m_comparisonLocaleSelector.setValue(oldComparisonLocale); 278 } 279 } else { 280 m_comparisonLocale = locale; 281 updateLocaleWidgets(); 282 initTree(m_currentRoot); 283 } 284 285 } catch (Exception e) { 286 LOG.error(e.getLocalizedMessage(), e); 287 CmsErrorDialog.showErrorDialog(e); 288 } finally { 289 m_handlingLocaleChange = false; 290 } 291 } 292 } 293 }); 294 295 CssLayout localeSelectors = new CssLayout(); 296 localeSelectors.addStyleName(OpenCmsTheme.SITEMAP_LOCALE_BAR); 297 298 m_rootLocaleSelector.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_LOCALECOMPARE_MAIN_LOCALE_0)); 299 m_comparisonLocaleSelector.setCaption( 300 CmsVaadinUtils.getMessageText(Messages.GUI_LOCALECOMPARE_COMPARISON_LOCALE_0)); 301 302 localeSelectors.setWidth("100%"); 303 localeSelectors.addComponent(m_rootLocaleSelector); 304 localeSelectors.addComponent(m_comparisonLocaleSelector); 305 // localeSelectors.setComponentAlignment(wrapper2, Alignment.MIDDLE_RIGHT); 306 307 setSpacing(true); 308 addComponent(localeSelectors); 309 addComponent(m_treeContainer); 310 m_treeContainer.setWidth("100%"); 311 initTree(res); 312 } 313 314 /** 315 * @see org.opencms.ui.sitemap.I_CmsLocaleCompareContext#refreshAll() 316 */ 317 public void refreshAll() { 318 319 try { 320 initialize(m_currentRoot.getStructureId(), m_comparisonLocale); 321 } catch (CmsException e) { 322 LOG.error(e.getLocalizedMessage(), e); 323 CmsErrorDialog.showErrorDialog(e); 324 } 325 } 326 327 /** 328 * Switches the root locale to the given value.<p> 329 * 330 * @param locale the new root locale 331 * @throws CmsException if something goes wrong 332 */ 333 public void switchToLocale(Locale locale) throws CmsException { 334 335 CmsObject cms = A_CmsUI.getCmsObject(); 336 CmsLocaleGroupService groupService = cms.getLocaleGroupService(); 337 CmsLocaleGroup localeGroup = groupService.readDefaultFileLocaleGroup(m_currentRoot); 338 Collection<CmsResource> resources = localeGroup.getResourcesForLocale(locale); 339 if (resources.isEmpty()) { 340 LOG.error( 341 "Can not switch to locale " 342 + locale 343 + ": no page found in locale group of " 344 + m_currentRoot.getRootPath()); 345 } 346 CmsResource localeVariant = resources.iterator().next(); 347 if (!localeVariant.isFolder()) { 348 CmsResource parentFolder = cms.readParentFolder(localeVariant.getStructureId()); 349 if (m_comparisonLocale.equals(locale)) { 350 m_comparisonLocale = m_rootLocale; 351 m_rootLocale = locale; 352 } else { 353 m_rootLocale = locale; 354 } 355 updateLocaleWidgets(); 356 initTree(parentFolder); 357 } else { 358 LOG.error("locale variant should not be a folder: " + localeVariant.getRootPath()); 359 } 360 } 361 362 /** 363 * Initializes the tree with the given resource as a root.<p> 364 * 365 * @param rootRes the new tree root resource 366 * @throws CmsException if something goes wrong 367 */ 368 protected void initTree(CmsResource rootRes) throws CmsException { 369 370 m_currentRoot = rootRes; 371 m_treeContainer.removeAllComponents(); 372 showHeader(); 373 CmsSitemapTreeController controller = new CmsSitemapTreeController( 374 A_CmsUI.getCmsObject(), 375 rootRes, 376 this, 377 m_treeContainer); 378 379 // no need to escape a structure id 380 JavaScript.eval(CmsGwtConstants.VAR_LOCALE_ROOT + "='" + rootRes.getStructureId() + "'"); 381 382 CmsSitemapUI ui = (CmsSitemapUI)(A_CmsUI.get()); 383 ui.getSitemapExtension().setSitemapTreeController(controller); 384 CmsSitemapTreeNode root1 = controller.createRootNode(); 385 controller.initEventHandlers(root1); 386 m_treeContainer.addComponent(root1); 387 controller.onClickOpen(root1); 388 } 389 390 /** 391 * Shows the current loale values in their corresponding widgets. 392 */ 393 protected void updateLocaleWidgets() { 394 395 m_rootLocaleSelector.setValue(m_rootLocale); 396 m_comparisonLocaleSelector.setValue(m_comparisonLocale); 397 } 398 399 /** 400 * Gets the possible locale values selectable as main locale.<p> 401 * 402 * @param cms the CMS context 403 * @param res the resource 404 * @param mainLocale the main locale 405 * @param secondaryLocales the secondary locales 406 * 407 * @return the possible locale selections 408 */ 409 private List<Locale> getMainLocaleSelectOptions( 410 CmsObject cms, 411 CmsResource res, 412 Locale mainLocale, 413 List<Locale> secondaryLocales) { 414 415 try { 416 CmsLocaleGroup localeGroup = cms.getLocaleGroupService().readDefaultFileLocaleGroup(res); 417 List<Locale> result = Lists.newArrayList(); 418 if (localeGroup.hasLocale(mainLocale)) { 419 result.add(mainLocale); 420 } 421 for (Locale locale : secondaryLocales) { 422 if (localeGroup.hasLocale(locale)) { 423 result.add(locale); 424 } 425 } 426 return result; 427 } catch (CmsException e) { 428 LOG.error(e.getLocalizedMessage(), e); 429 return Lists.newArrayList(); 430 } 431 } 432 433 /** 434 * Shows the header for the currently selected sitemap root.<p> 435 * 436 * @throws CmsException if something goes wrong 437 */ 438 private void showHeader() throws CmsException { 439 440 CmsSitemapUI ui = (CmsSitemapUI)A_CmsUI.get(); 441 String title = null; 442 String description = null; 443 String path = null; 444 String locale = m_rootLocale.toString(); 445 CmsObject cms = A_CmsUI.getCmsObject(); 446 CmsResource targetRes = getRoot(); 447 if (targetRes.isFolder()) { 448 targetRes = cms.readDefaultFile(targetRes, CmsResourceFilter.IGNORE_EXPIRATION); 449 if (targetRes == null) { 450 targetRes = getRoot(); 451 } 452 } 453 CmsResourceUtil resUtil = new CmsResourceUtil(cms, getRoot()); 454 title = resUtil.getTitle(); 455 description = resUtil.getGalleryDescription(A_CmsUI.get().getLocale()); 456 path = OpenCms.getLinkManager().getServerLink( 457 cms, 458 cms.getRequestContext().removeSiteRoot(targetRes.getRootPath())); 459 String iconClasses = CmsIconUtil.getIconClasses( 460 CmsIconUtil.getDisplayType(cms, getRoot()), 461 getRoot().getName(), 462 false); 463 ui.getSitemapExtension().showInfoHeader(title, description, path, locale, iconClasses); 464 } 465}