diff --git a/ccm-cms/src/com/arsdigita/cms/ContentBundle.java b/ccm-cms/src/com/arsdigita/cms/ContentBundle.java
index e0a2fe86b..01403f752 100755
--- a/ccm-cms/src/com/arsdigita/cms/ContentBundle.java
+++ b/ccm-cms/src/com/arsdigita/cms/ContentBundle.java
@@ -408,7 +408,7 @@ public class ContentBundle extends ContentItem {
* @return A Collection of language 2-letter codes in
* which this item is available
*/
- public final Collection getLanguages() {
+ public final Collection getLanguages() {
// XXX For LIVE bundles, there might be several PENDING
// instances with the same language. Maybe we should filter
// these out and return only one?
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources.properties b/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources.properties
index 9899f6ca4..226bb32a4 100755
--- a/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources.properties
+++ b/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources.properties
@@ -70,3 +70,4 @@ cms.ui.folder.no_such_item=Item ID supplied does not match an existing Content I
cms.ui.folder.filter.all=All
cms.ui.folder.filter=Filter for work
cms.ui.folder.filter_do=Filter
+cms.ui.folder.languages=
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources_de.properties b/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources_de.properties
index f52ea3a8f..c8f409279 100755
--- a/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources_de.properties
+++ b/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources_de.properties
@@ -66,3 +66,4 @@ cms.ui.folder.remove_asset_link=Entfernen
cms.ui.folder.filter.all=Alle
cms.ui.folder.filter=Nach Begriff filtern
cms.ui.folder.filter_do=Filtern
+cms.ui.folder.languages=
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources_fr.properties b/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources_fr.properties
index 32027ad8d..6ebfd1b34 100755
--- a/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources_fr.properties
+++ b/ccm-cms/src/com/arsdigita/cms/ui/folder/CMSFolderResources_fr.properties
@@ -65,3 +65,4 @@ cms.ui.folder.item_is_live=est en ligne ; Vous devez le d\u00e9-publier avant de
cms.ui.folder.no_permission_for_item=Vous n'avez pas l'autorisation de supprimer ou de d\u00e9placer
cms.ui.folder.no_such_item=L'identifiant fourni pour l'\u00e9l\u00e9ment ne correspond pas \u00e0 un contenu existant.
cms.ui.folder.filter.all=
+cms.ui.folder.languages=
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java b/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java
index 6a4dceb71..1339b0be0 100755
--- a/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java
+++ b/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java
@@ -32,8 +32,6 @@ import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
-import com.arsdigita.bebop.event.ChangeEvent;
-import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener;
@@ -45,12 +43,7 @@ import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableHeader;
import com.arsdigita.bebop.table.TableModel;
-import com.arsdigita.cms.CMS;
-import com.arsdigita.cms.ContentBundle;
-import com.arsdigita.cms.ContentItem;
-import com.arsdigita.cms.ContentSection;
-import com.arsdigita.cms.Folder;
-import com.arsdigita.cms.ItemCollection;
+import com.arsdigita.cms.*;
import com.arsdigita.cms.SecurityManager;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.dispatcher.Utilities;
@@ -68,12 +61,13 @@ import com.arsdigita.util.Assert;
import org.apache.log4j.Logger;
import java.math.BigDecimal;
+import java.util.Iterator;
import javax.servlet.ServletException;
/**
* Browse folders and items. If the user clicks on a folder, the folder
- * selection model is updated. If the user clicks on any other item, an
- * separate item selection model is updated.
+ * selection model is updated. If the user clicks on any other item, an separate
+ * item selection model is updated.
*
* @author David Lutterkort
* @version $Id: FolderBrowser.java 2017 2009-10-04 09:03:45Z pboy $
@@ -82,18 +76,22 @@ public class FolderBrowser extends Table {
private static final Logger s_log = Logger.getLogger(FolderBrowser.class);
private static GlobalizedMessage[] s_headers = {
- globalize("cms.ui.folder.name"), globalize("cms.ui.folder.title"),
+ globalize("cms.ui.folder.name"),
+ globalize("cms.ui.folder.languages"),
+ globalize("cms.ui.folder.title"),
globalize("cms.ui.folder.type"),
globalize("cms.ui.folder.creation_date"),
- globalize("cms.ui.folder.last_modified"), globalize(
- "cms.ui.folder.action"),
+ globalize("cms.ui.folder.last_modified"),
+ globalize("cms.ui.folder.action"),
globalize("cms.ui.folder.index")};
private static GlobalizedMessage[] s_noIndexHeaders = {
- globalize("cms.ui.folder.name"), globalize("cms.ui.folder.title"),
+ globalize("cms.ui.folder.name"),
+ globalize("cms.ui.folder.languages"),
+ globalize("cms.ui.folder.title"),
globalize("cms.ui.folder.type"),
globalize("cms.ui.folder.creation_date"),
- globalize("cms.ui.folder.last_modified"), globalize(
- "cms.ui.folder.action")};
+ globalize("cms.ui.folder.last_modified"),
+ globalize("cms.ui.folder.action")};
private static final String SORT_ACTION_UP = "sortActionUp";
private static final String SORT_ACTION_DOWN = "sortActionDown";
private FolderSelectionModel m_currentFolder;
@@ -122,8 +120,8 @@ public class FolderBrowser extends Table {
setModelBuilder(new FolderTableModelBuilder(currentFolder));
setColumnModel(new DefaultTableColumnModel(hideIndexColumn()
- ? s_noIndexHeaders
- : s_headers));
+ ? s_noIndexHeaders
+ : s_headers));
setHeader(new TableHeader(getColumnModel()));
// DEE 1/18/02: the folder table model builder needs to know about
// 'this' in order to set visibility, but 'this' isn't available
@@ -139,22 +137,22 @@ public class FolderBrowser extends Table {
m_currentFolder = currentFolder;
/*
-
- This code should be uncommented if the desired behaviour is for a change
- of folder to cause reversion to default ordering of contained items
- (by name ascending). Our feeling is that the user selected ordering
- should be retained for the duration of the folder browsing session. If
- anyone wants this alternative behaviour it should be brought in under
- the control of a config parameter.
-
- m_currentFolder.addChangeListener(new ChangeListener() {
-
- public void stateChanged(ChangeEvent e) {
- PageState state = e.getPageState();
- state.setValue(m_sortType, m_sortType.getDefaultValue());
- state.setValue(m_sortDirection, m_sortDirection.getDefaultValue());
-
- }});
+ *
+ * This code should be uncommented if the desired behaviour is for a
+ * change of folder to cause reversion to default ordering of contained
+ * items (by name ascending). Our feeling is that the user selected
+ * ordering should be retained for the duration of the folder browsing
+ * session. If anyone wants this alternative behaviour it should be
+ * brought in under the control of a config parameter.
+ *
+ * m_currentFolder.addChangeListener(new ChangeListener() {
+ *
+ * public void stateChanged(ChangeEvent e) { PageState state =
+ * e.getPageState(); state.setValue(m_sortType,
+ * m_sortType.getDefaultValue()); state.setValue(m_sortDirection,
+ * m_sortDirection.getDefaultValue());
+ *
+ * }});
*/
setClassAttr("dataTable");
@@ -164,16 +162,17 @@ public class FolderBrowser extends Table {
m_nameColumn = getColumn(0);
m_nameColumn.setCellRenderer(new NameCellRenderer());
m_nameColumn.setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_NAME));
- getColumn(1).setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_TITLE));
- getColumn(3).setHeaderRenderer(new HeaderCellRenderer(
- SORT_KEY_CREATION_DATE));
+ getColumn(1).setCellRenderer(new LanguagesCellRenderer());
+ getColumn(2).setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_TITLE));
getColumn(4).setHeaderRenderer(new HeaderCellRenderer(
+ SORT_KEY_CREATION_DATE));
+ getColumn(5).setHeaderRenderer(new HeaderCellRenderer(
SORT_KEY_LAST_MODIFIED_DATE));
- m_deleteColumn = getColumn(5);
+ m_deleteColumn = getColumn(6);
m_deleteColumn.setCellRenderer(new ActionCellRenderer());
m_deleteColumn.setAlign("center");
if (!hideIndexColumn()) {
- m_indexColumn = getColumn(6);
+ m_indexColumn = getColumn(7);
m_indexColumn.setCellRenderer(new IndexToggleRenderer());
m_indexColumn.setAlign("center");
@@ -217,7 +216,7 @@ public class FolderBrowser extends Table {
boolean canDelete =
sm.canAccess(state.getRequest(), SecurityManager.DELETE_ITEM,
- folder);
+ folder);
m_deleteColumn.setVisible(state, canDelete);
}
@@ -261,7 +260,7 @@ public class FolderBrowser extends Table {
private class FolderTableModelBuilder
extends AbstractTableModelBuilder
implements PaginationModelBuilder,
- FolderManipulator.FilterFormModelBuilder {
+ FolderManipulator.FilterFormModelBuilder {
private FolderSelectionModel m_folder;
private RequestLocal m_size;
@@ -273,7 +272,7 @@ public class FolderBrowser extends Table {
}
public FolderTableModelBuilder(FolderSelectionModel sel,
- FolderBrowser fb) {
+ FolderBrowser fb) {
super();
m_folder = sel;
m_size = new RequestLocal();
@@ -282,8 +281,7 @@ public class FolderBrowser extends Table {
}
public TableModel makeModel(Table t, PageState s) {
- FolderSelectionModel sel = ((FolderBrowser) t).
- getFolderSelectionModel();
+ FolderSelectionModel sel = ((FolderBrowser) t).getFolderSelectionModel();
Folder f = (Folder) sel.getSelectedObject(s);
if (f == null) {
return Table.EMPTY_MODEL;
@@ -291,7 +289,7 @@ public class FolderBrowser extends Table {
t.getRowSelectionModel().clearSelection(s);
s_log.debug(String.format("filter = '%s'", s.getValue(m_filter)));
Folder.ItemCollection itemColl =
- (Folder.ItemCollection) m_itemColl.get(s);
+ (Folder.ItemCollection) m_itemColl.get(s);
s_log.debug(String.format("itemColl.size = %d", itemColl.size()));
m_folderSize = itemColl.size();
@@ -363,7 +361,7 @@ public class FolderBrowser extends Table {
size = new Integer((int) itemColl.size());
itemColl.setRange(new Integer(paginator.getFirst(state)),
- new Integer(paginator.getLast(state) + 1));
+ new Integer(paginator.getLast(state) + 1));
String sortKey = (String) state.getValue(m_sortType);
String direction = "asc";
@@ -374,13 +372,13 @@ public class FolderBrowser extends Table {
if (sortKey.equals(SORT_KEY_TITLE)) {
itemColl.setOrder("lower(item." + ContentItem.DISPLAY_NAME
- + ") " + direction);
+ + ") " + direction);
} else if (sortKey.equals(SORT_KEY_NAME)) {
itemColl.setOrder("lower(item." + ContentItem.NAME + ") "
- + direction);
+ + direction);
} else if (sortKey.equals(SORT_KEY_LAST_MODIFIED_DATE)) {
itemColl.setOrder("item.auditing.lastModifiedDate "
- + direction);
+ + direction);
} else if (sortKey.equals(SORT_KEY_CREATION_DATE)) {
itemColl.setOrder("item.auditing.creationDate " + direction);
}
@@ -397,11 +395,11 @@ public class FolderBrowser extends Table {
}
/**
- * Indicates whether the paginator should be visible,
- * based on the visibility of the folder browser itself.
+ * Indicates whether the paginator should be visible, based on the
+ * visibility of the folder browser itself.
*
- * @return true if folder browser is visible, or if the
- * associated folder browser is unknown.
+ * @return true if folder browser is visible, or if the associated
+ * folder browser is unknown.
*/
public boolean isVisible(PageState state) {
return (m_fb != null) ? m_fb.isVisible(state) : true;
@@ -419,9 +417,9 @@ public class FolderBrowser extends Table {
}
public Component getComponent(final Table table, final PageState state,
- Object value,
- boolean isSelected, Object key,
- int row, int column) {
+ Object value,
+ boolean isSelected, Object key,
+ int row, int column) {
String headerName = (String) ((GlobalizedMessage) value).localize();
String sortKey = (String) state.getValue(m_sortType);
final boolean isCurrentKey = sortKey.equals(m_key);
@@ -442,14 +440,14 @@ public class FolderBrowser extends Table {
// by default, everything sorts "up" unless it
// is the current key and it is already pointing up
if (SORT_ACTION_UP.equals(currentSortDirection)
- && isCurrentKey) {
+ && isCurrentKey) {
sortDirectionAction = SORT_ACTION_DOWN;
} else {
sortDirectionAction = SORT_ACTION_UP;
}
ps.setControlEvent(table,
- sortDirectionAction,
- m_key);
+ sortDirectionAction,
+ m_key);
}
};
Label l = new Label();
@@ -470,8 +468,8 @@ public class FolderBrowser extends Table {
}
/**
- * Produce links to view an item or control links for folders
- * to change into the folder.
+ * Produce links to view an item or control links for folders to change into
+ * the folder.
*/
private class NameCellRenderer extends DefaultTableCellRenderer {
@@ -481,14 +479,14 @@ public class FolderBrowser extends Table {
@Override
public Component getComponent(Table table, PageState state, Object value,
- boolean isSelected, Object key,
- int row, int column) {
+ boolean isSelected, Object key,
+ int row, int column) {
Folder.ItemCollection coll = (Folder.ItemCollection) value;
String name = coll.getName();
if (coll.isFolder()) {
return super.getComponent(table, state, name,
- isSelected, key, row, column);
+ isSelected, key, row, column);
} else {
ContentSection section = CMS.getContext().getContentSection();
BigDecimal id = coll.getID();
@@ -498,9 +496,101 @@ public class FolderBrowser extends Table {
} else {
ItemResolver resolver = section.getItemResolver();
return new Link(name, resolver.generateItemURL(state, id,
- name, section,
- coll.
- getVersion()));
+ name, section, coll.getVersion()));
+ }
+ }
+ }
+ }
+
+ /**
+ * Added by: Sören Bernstein
+ *
+ * Produce links to view an item in a specific language and show all
+ * existing language version and the live status in the folder browser.
+ */
+ private class LanguagesCellRenderer extends DefaultTableCellRenderer {
+
+ public LanguagesCellRenderer() {
+ super(true);
+ }
+
+ @Override
+ public Component getComponent(Table table, PageState state, Object value,
+ boolean isSelected, Object key,
+ int row, int column) {
+
+ Folder.ItemCollection coll = (Folder.ItemCollection) value;
+ String name = coll.getName();
+ if (coll.isFolder()) {
+ // Nothing to show on folders
+ return new Label();
+ } else {
+
+ ContentPage cp;
+
+ try {
+ cp = new ContentPage(coll.getID());
+ } catch (DataObjectNotFoundException ex) {
+ // Content item was not found, return nothing
+ return new Label();
+ }
+
+ ContentBundle bundle = cp.getContentBundle();
+ ContentSection section = CMS.getContext().getContentSection();
+
+
+ if (bundle != null
+ && !(cp instanceof LanguageInvariantContentItem
+ && ((LanguageInvariantContentItem) cp).isLanguageInvariant())) {
+
+ Iterator languages = bundle.getLanguages().iterator();
+
+
+
+ StringBuilder temp = new StringBuilder(20);
+ SimpleContainer container = new SimpleContainer();
+
+ while (languages.hasNext()) {
+ String lang = languages.next();
+ ContentItem ci = bundle.getInstance(lang, false);
+ StringBuilder fontWeight = new StringBuilder(2);
+ StringBuilder classes = new StringBuilder(20);
+
+ if (ci.isLive()) {
+ fontWeight.append(Label.BOLD);
+ classes.append("live ");
+ }
+ if (bundle.getPrimaryInstance().equals(ci)) {
+ fontWeight.append(Label.ITALIC);
+ classes.append("primaryInstance");
+ }
+
+ Label langLabel = new Label(lang);
+ langLabel.setFontWeight(fontWeight.toString().trim());
+ langLabel.setClassAttr(classes.toString().trim());
+
+ if (section == null) {
+ container.add(langLabel);
+
+ } else {
+ ItemResolver resolver = section.getItemResolver();
+ container.add(
+ new Link(langLabel,
+ resolver.generateItemURL(state,
+ ci.getID(),
+ name,
+ section,
+ coll.getVersion())));
+ }
+ if (languages.hasNext()) {
+ container.add(new Label(" ", false));
+ }
+
+ }
+
+ return container;
+ } else {
+ return new Label();
}
}
}
@@ -527,8 +617,8 @@ public class FolderBrowser extends Table {
}
public Component getComponent(Table table, PageState state, Object value,
- boolean isSelected, Object key,
- int row, int column) {
+ boolean isSelected, Object key,
+ int row, int column) {
if (((Boolean) value).booleanValue()) {
return s_link;
} else {
@@ -540,8 +630,8 @@ public class FolderBrowser extends Table {
private final class IndexToggleRenderer implements TableCellRenderer {
public Component getComponent(Table table, PageState state, Object value,
- boolean isSelected, Object key, int row,
- int column) {
+ boolean isSelected, Object key, int row,
+ int column) {
if (value == null) {
return new Label(GlobalizationUtil.globalize("cms.ui.folder.na"));
@@ -558,7 +648,7 @@ public class FolderBrowser extends Table {
}
}
- // Deletes an item
+// Deletes an item
private class ItemDeleter extends TableActionAdapter {
public void cellSelected(TableActionEvent e) {
@@ -596,12 +686,13 @@ public class FolderBrowser extends Table {
private static class FolderTableModel implements TableModel {
private static final int NAME = 0;
- private static final int TITLE = 1;
- private static final int TYPE = 2;
- private static final int CREATION_DATE = 3;
- private static final int LAST_MODIFIED = 4;
- private static final int DELETABLE = 5;
- private static final int IS_INDEX = 6;
+ private static final int LANGUAGES = 1;
+ private static final int TITLE = 2;
+ private static final int TYPE = 3;
+ private static final int CREATION_DATE = 4;
+ private static final int LAST_MODIFIED = 5;
+ private static final int DELETABLE = 6;
+ private static final int IS_INDEX = 7;
private PageState m_state;
private FolderBrowser m_table;
private Folder.ItemCollection m_itemColl;
@@ -613,7 +704,7 @@ public class FolderBrowser extends Table {
//m_itemColl = folder.getItems();
//}
public FolderTableModel(FolderBrowser table, PageState state,
- Folder.ItemCollection itemColl) {
+ Folder.ItemCollection itemColl) {
m_state = state;
m_table = table;
m_itemColl = itemColl;
@@ -631,7 +722,7 @@ public class FolderBrowser extends Table {
}
public int getColumnCount() {
- return hideIndexColumn() ? 6 : 7;
+ return hideIndexColumn() ? 7 : 8;
}
public boolean nextRow() {
@@ -642,6 +733,8 @@ public class FolderBrowser extends Table {
switch (columnIndex) {
case NAME:
return m_itemColl;
+ case LANGUAGES:
+ return m_itemColl;
case TITLE:
return m_itemColl.getDisplayName();
case TYPE:
@@ -655,7 +748,7 @@ public class FolderBrowser extends Table {
}
case LAST_MODIFIED: {
java.util.Date lastModified =
- m_itemColl.getLastModifiedDate();
+ m_itemColl.getLastModifiedDate();
if (lastModified == null) {
return "--";
}
@@ -675,13 +768,12 @@ public class FolderBrowser extends Table {
if (m_folIndexID == null) {
return new Boolean(false);
}
- return new Boolean(m_folIndexID.compareTo(m_itemColl.
- getBundleID()) == 0);
+ return new Boolean(m_folIndexID.compareTo(m_itemColl.getBundleID()) == 0);
}
default:
throw new IndexOutOfBoundsException("Column index "
- + columnIndex
- + " not in table model.");
+ + columnIndex
+ + " not in table model.");
}
}
@@ -702,13 +794,13 @@ public class FolderBrowser extends Table {
if (!m_itemColl.hasChildren()) {
if (s_log.isDebugEnabled()) {
s_log.debug("The item is an empty folder; it may be "
- + "deleted");
+ + "deleted");
}
return true;
} else {
if (s_log.isDebugEnabled()) {
s_log.debug("The folder is not empty; it cannot be "
- + "deleted");
+ + "deleted");
}
return false;
}
@@ -724,7 +816,7 @@ public class FolderBrowser extends Table {
public Object getKeyAt(int columnIndex) {
// Mark folders by using their negative ID (dirty, dirty)
return (m_itemColl.isFolder()) ? m_itemColl.getID().negate()
- : m_itemColl.getBundleID();
+ : m_itemColl.getBundleID();
}
}
@@ -767,11 +859,10 @@ public class FolderBrowser extends Table {
Folder folder = (Folder) m_fol.getSelectedObject(state);
- ContentBundle currentIndexItem = (ContentBundle) folder.
- getIndexItem();
+ ContentBundle currentIndexItem = (ContentBundle) folder.getIndexItem();
if (currentIndexItem == null || (currentIndexItem.getID().
- compareTo(contentItem.getID())
- != 0)) {
+ compareTo(contentItem.getID())
+ != 0)) {
folder.setIndexItem(contentItem);
} else {
folder.removeIndexItem();
@@ -786,8 +877,7 @@ public class FolderBrowser extends Table {
/**
* Getting the GlobalizedMessage using a CMS Class targetBundle.
*
- * @param key The resource key
- * @pre ( key != null )
+ * @param key The resource key @pre ( key != null )
*/
private static GlobalizedMessage globalize(String key) {
return FolderManipulator.globalize(key);