diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ContentSectionPage.java b/ccm-cms/src/com/arsdigita/cms/ui/ContentSectionPage.java index efef16eb0..219a5bb49 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ContentSectionPage.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ContentSectionPage.java @@ -133,6 +133,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener { private FolderAdminPane m_folderPane; private BrowsePane m_browsePane; private LayoutPanel m_searchPane; + private ImagesPane m_imagesPane; private RoleAdminPane m_rolePane; private WorkflowAdminPane m_workflowPane; private LifecycleAdminPane m_lifecyclePane; @@ -165,6 +166,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener { m_folderPane = getFolderAdminPane(); m_browsePane = getBrowsePane(); m_searchPane = getSearchPane(); + m_imagesPane = getImagesPane(); m_rolePane = getRoleAdminPane(); m_workflowPane = getWorkflowAdminPane(); m_lifecyclePane = getLifecycleAdminPane(); @@ -247,6 +249,13 @@ public class ContentSectionPage extends CMSPage implements ActionListener { return m_searchPane; } + protected ImagesPane getImagesPane() { + if(m_imagesPane == null) { + m_imagesPane = new ImagesPane(); + } + return m_imagesPane; + } + protected RoleAdminPane getRoleAdminPane() { if (m_rolePane == null) { m_rolePane = new RoleAdminPane(); @@ -366,6 +375,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener { //tab(pane, "cms.ui.folders", getFolderAdminPane()); tab(pane, "cms.ui.browse", getBrowsePane()); tab(pane, "cms.ui.search", getSearchPane()); + tab(pane, "cms.ui.images", getImagesPane()); tab(pane, "cms.ui.roles", getRoleAdminPane()); tab(pane, "cms.ui.workflows", getWorkflowAdminPane()); tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane()); @@ -404,6 +414,8 @@ public class ContentSectionPage extends CMSPage implements ActionListener { if (pane == m_searchPane) { m_searchPane.reset(state); + } else if (pane == m_imagesPane) { + m_imagesPane.reset(state); } else if (pane == m_folderPane) { m_folderPane.reset(state); } else if (pane == m_browsePane) { diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ImageBrowser.java b/ccm-cms/src/com/arsdigita/cms/ui/ImageBrowser.java index 049db1b65..ff0874812 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ImageBrowser.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ImageBrowser.java @@ -46,8 +46,8 @@ import java.math.BigDecimal; import org.apache.log4j.Logger; /** - * Displays a list of images in a Table. The table will look - * something like this: + * Displays a list of images in a Table. The table will look something like + * this: * *

  * +-----------+-------+-------+------+----------+
@@ -65,6 +65,9 @@ import org.apache.log4j.Logger;
  */
 public class ImageBrowser extends Table {
 
+    public static final int DISPLAY_ONLY = 0;
+    public static final int SELECT_IMAGE = 1;
+    public static final int ADMIN_IMAGES = 2;
     private ImageBrowserModelBuilder m_builder;
     private static final String[] HEADERS = {"Thumbnail", "Name", "Size", "Type", "Action", ""};
     private static final int THUMB = 0;
@@ -73,7 +76,8 @@ public class ImageBrowser extends Table {
     private static final int TYPE = 3;
     private static final int LINK = 4;
     private static final int DELETE = 5;
-    private static final int NUM_COLUMNS = 6;
+    private static int s_numColumns = -1;
+    private int m_mode = DISPLAY_ONLY;
     private Dimension m_thumbSize;
     private static final Logger s_log = Logger.getLogger(ImageBrowser.class);
 
@@ -84,18 +88,24 @@ public class ImageBrowser extends Table {
      * component with its {@link ImageBrowserModel} during each request
      */
     public ImageBrowser(ImageBrowserModelBuilder b) {
+
+        this(b, ImageBrowser.SELECT_IMAGE);
+    }
+
+    public ImageBrowser(ImageBrowserModelBuilder b, int mode) {
         super(new BuilderAdapter(b), HEADERS);
+        m_mode = mode;
         setThumbnailSize(CMS.getConfig().getImageBrowserThumbnailMaxWidth(),
-                         CMS.getConfig().getImageBrowserThumbnailMaxHeight());
+                CMS.getConfig().getImageBrowserThumbnailMaxHeight());
         m_builder = b;
 
         getHeader().setDefaultRenderer(new DefaultTableCellRenderer(false));
-        getColumn(0).setCellRenderer(new ThumbnailCellRenderer());
-        getColumn(1).setCellRenderer(new DefaultTableCellRenderer(false));
-        getColumn(2).setCellRenderer(new DefaultTableCellRenderer(false));
-        getColumn(3).setCellRenderer(new DefaultTableCellRenderer(false));
-        getColumn(4).setCellRenderer(new DefaultTableCellRenderer(true));
-        getColumn(5).setCellRenderer(new DeleteCellRenderer());
+        addColumn(new ThumbnailCellRenderer());
+        addColumn(new DefaultTableCellRenderer(false));
+        addColumn(new DefaultTableCellRenderer(false));
+        addColumn(new DefaultTableCellRenderer(false));
+        addColumn(new SelectCellRenderer());
+        addColumn(new DeleteCellRenderer());
 
         setCellPadding("4");
         setBorder("1");
@@ -103,6 +113,10 @@ public class ImageBrowser extends Table {
         setClassAttr("imageBrowser");
     }
 
+    private void addColumn(TableCellRenderer renderer) {
+        getColumn(++s_numColumns).setCellRenderer(renderer);
+    }
+
     /**
      * @return the size, in pixels, of the thumbnail images
      */
@@ -112,7 +126,8 @@ public class ImageBrowser extends Table {
 
     /**
      * Set the thumbnail size
-     * @param size  the size, in pixels, of the thumbnail images
+     *
+     * @param size the size, in pixels, of the thumbnail images
      */
     public final void setThumbnailSize(int width, int height) {
         m_thumbSize = new Dimension(width, height);
@@ -127,17 +142,15 @@ public class ImageBrowser extends Table {
 
     /**
      * @param state The current page state
-     * @return the {@link ImageBrowserModel} used in the current
-     *   request
+     * @return the {@link ImageBrowserModel} used in the current request
      */
     public ImageBrowserModel getImageBrowserModel(PageState state) {
         return ((ImageModelAdapter) getTableModel(state)).getModel();
     }
 
     /**
-     * An action listener that only gets fired when the "select"
-     * link is clicked. Child classes should override the
-     * linkClicked method.
+     * An action listener that only gets fired when the "select" link is
+     * clicked. Child classes should override the linkClicked method.
      */
     public static abstract class LinkActionListener
             extends TableActionAdapter {
@@ -192,6 +205,26 @@ public class ImageBrowser extends Table {
         }
     }
 
+    // Renders the select link if the mode needs one
+    private class SelectCellRenderer extends DefaultTableCellRenderer {
+
+        public SelectCellRenderer() {
+            super(true);
+        }
+
+        @Override
+        public Component getComponent(Table table, PageState state, Object value,
+                boolean isSelected, Object key,
+                int row, int column) {
+
+            if (m_mode == ImageBrowser.SELECT_IMAGE) {
+                return super.getComponent(table, state, value, isSelected, key, row, column);
+            }
+
+            return new Label("");
+        }
+    }
+
     // Renders the delete link if the user has permission to delete
     // the asset and it's not used in an article.
     private class DeleteCellRenderer extends DefaultTableCellRenderer {
@@ -204,27 +237,32 @@ public class ImageBrowser extends Table {
         public Component getComponent(Table table, PageState state, Object value,
                 boolean isSelected, Object key,
                 int row, int column) {
-            boolean canDelete = false;
-         // SecurityManager sm = Utilities.getSecurityManager(state);
-            SecurityManager sm = CMS.getSecurityManager(state);
-            if (sm.canAccess(state.getRequest(), SecurityManager.DELETE_IMAGES)) {
-                try {
-                    ImageAsset asset = (ImageAsset) DomainObjectFactory.newInstance(new OID(ImageAsset.BASE_DATA_OBJECT_TYPE, (BigDecimal) key));
+
+            // Only show delete link in admin mode
+            if (m_mode == ADMIN_IMAGES) {
+
+                boolean canDelete = false;
+                // SecurityManager sm = Utilities.getSecurityManager(state);
+                SecurityManager sm = CMS.getSecurityManager(state);
+                if (sm.canAccess(state.getRequest(), SecurityManager.DELETE_IMAGES)) {
+                    try {
+                        ImageAsset asset = (ImageAsset) DomainObjectFactory.newInstance(new OID(ImageAsset.BASE_DATA_OBJECT_TYPE, (BigDecimal) key));
 //XXX Find a new way to figure out, if this image is used by any CI so we can decide if it can be deleted
 //                    if (!GenericArticleImageAssociation.imageHasAssociation(asset)) {
 //                        canDelete = true;
 //                    }
-                } catch (DataObjectNotFoundException e) {
-                    // can't find asset, can't delete it
+                    } catch (DataObjectNotFoundException e) {
+                        // can't find asset, can't delete it
+                    }
+
+                }
+                
+                // can delete image because it's not in use
+                if (canDelete) {
+                    return super.getComponent(table, state, value, isSelected, key, row, column);
                 }
-
-            }
-
-            if (canDelete) {
-                return super.getComponent(table, state, value, isSelected, key, row, column);
-            } else {
-                return new Label("");
             }
+            return new Label("");
         }
     }
 
@@ -262,7 +300,7 @@ public class ImageBrowser extends Table {
 
         @Override
         public int getColumnCount() {
-            return ImageBrowser.NUM_COLUMNS;
+            return ImageBrowser.s_numColumns;
         }
 
         @Override
@@ -311,7 +349,7 @@ public class ImageBrowser extends Table {
                     return m.getMimeType();
 
                 case ImageBrowser.LINK:
-                    return "select";
+                        return "select";
 
                 case ImageBrowser.DELETE:
                     return "delete";
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ImageChooser.java b/ccm-cms/src/com/arsdigita/cms/ui/ImageChooser.java
index b6934f639..55c2a9f77 100755
--- a/ccm-cms/src/com/arsdigita/cms/ui/ImageChooser.java
+++ b/ccm-cms/src/com/arsdigita/cms/ui/ImageChooser.java
@@ -66,32 +66,43 @@ public class ImageChooser extends BoxPanel {
      *
      * @param context the context for the retrieved items. Should be
      *   {@link ContentItem#DRAFT} or {@link ContentItem#LIVE}
+     * @param mode the display mode for the ImageBrowser
      */
-    public ImageChooser(String context) {
+    public ImageChooser(String context, int mode) {
         super(BoxPanel.VERTICAL);
 
         m_keyword = new StringParameter(KEYWORD);
         m_sel = new ParameterSingleSelectionModel(m_keyword);
         m_form = new ImageKeywordForm(m_sel);
-	DefaultImageBrowserModelBuilder modelBuilder = 
-	    new DefaultImageBrowserModelBuilder(m_sel, context);
-        m_browser = new ImageBrowser(modelBuilder);
-	modelBuilder.setImageBrowser(m_browser);
+        DefaultImageBrowserModelBuilder modelBuilder = 
+            new DefaultImageBrowserModelBuilder(m_sel, context);
+        m_browser = new ImageBrowser(modelBuilder, mode);
+        modelBuilder.setImageBrowser(m_browser);
 
 
-	m_paginator = new Paginator
-	    (modelBuilder,
-	     LIST_SIZE);
+        m_paginator = new Paginator
+            (modelBuilder,
+             LIST_SIZE);
         super.add(m_form);
-	super.add(m_paginator);
+        super.add(m_paginator);
         super.add(m_browser);
     }
 
+    /**
+     * Construct a new ImageChooser
+     *
+     * @param context the context for the retrieved items. Should be
+     *   {@link ContentItem#DRAFT} or {@link ContentItem#LIVE}
+     */
+    public ImageChooser(String context) {
+        this(context, ImageBrowser.SELECT_IMAGE);
+    }
+
     /**
      * Construct a new ImageChooser
      */
     public ImageChooser() {
-        this(ContentItem.DRAFT);
+        this(ContentItem.DRAFT, ImageBrowser.SELECT_IMAGE);
     }
 
     /**
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ImageComponent.java b/ccm-cms/src/com/arsdigita/cms/ui/ImageComponent.java
new file mode 100644
index 000000000..2891c4a9a
--- /dev/null
+++ b/ccm-cms/src/com/arsdigita/cms/ui/ImageComponent.java
@@ -0,0 +1,33 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.ui;
+
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.cms.ReusableImageAsset;
+
+/**
+ *
+ * @author Sören Bernstein (quasimodo) 
+ */
+public interface ImageComponent {
+
+    ReusableImageAsset getImage(FormSectionEvent event) throws FormProcessException;
+
+    String getCaption(FormSectionEvent event);
+
+    String getDescription(FormSectionEvent event);
+
+    String getTitle(FormSectionEvent event);
+
+    String getUseContext(FormSectionEvent event);
+
+    SaveCancelSection getSaveCancelSection();
+
+    Form getForm();
+    
+}
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ImageLibraryComponent.java b/ccm-cms/src/com/arsdigita/cms/ui/ImageLibraryComponent.java
new file mode 100644
index 000000000..b9c686e4d
--- /dev/null
+++ b/ccm-cms/src/com/arsdigita/cms/ui/ImageLibraryComponent.java
@@ -0,0 +1,142 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.ui;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.SimpleContainer;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.BigDecimalParameter;
+import com.arsdigita.bebop.parameters.NotNullValidationListener;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ReusableImageAsset;
+import com.arsdigita.domain.DataObjectNotFoundException;
+import java.math.BigDecimal;
+
+/**
+ *
+ * @author Sören Bernstein (quasimodo) 
+ */
+public class ImageLibraryComponent extends SimpleContainer implements ImageComponent {
+    private final ImageChooser m_chooser;
+    private final ItemSelectionModel m_imageModel;
+    private final BigDecimalParameter m_imageID;
+    private final Form m_form;
+    private final TextField m_caption;
+    private final TextField m_description;
+    private final TextField m_title;
+    private final TextField m_useContext;
+    private final SaveCancelSection m_saveCancel;
+
+    public ImageLibraryComponent() {
+        m_imageID = new BigDecimalParameter("imageID");
+        m_imageModel = new ItemSelectionModel(m_imageID);
+        m_chooser = new ImageChooser(ContentItem.DRAFT, ImageBrowser.ADMIN_IMAGES);
+        m_chooser.addImageActionListener(new ImageBrowser.LinkActionListener() {
+
+            public void deleteClicked(PageState ps, BigDecimal imageID) {
+                ImagesPane.s_log.debug("Clicked delete");
+                ReusableImageAsset image = new ReusableImageAsset(imageID);
+                image.delete();
+            }
+
+            public void linkClicked(PageState ps, BigDecimal imageID) {
+                ImagesPane.s_log.debug("Clicked select");
+                try {
+                    ReusableImageAsset image = new ReusableImageAsset(imageID);
+                    m_imageModel.setSelectedObject(ps, image);
+                } catch (DataObjectNotFoundException ex) {
+                    ImagesPane.s_log.error("Selected non-existant image: " + imageID, ex);
+                }
+            }
+        });
+        add(m_chooser);
+        m_form = new Form("imageStepEditLibrary", new ColumnPanel(2));
+        add(m_form);
+        m_form.add(new Label("Caption"));
+        m_caption = new TextField("caption");
+        m_caption.addValidationListener(new NotNullValidationListener());
+        m_caption.setSize(40);
+        m_form.add(m_caption);
+        m_description = new TextField("description");
+        m_description.addValidationListener(new NotNullValidationListener());
+        m_description.setSize(40);
+        m_title = new TextField("title");
+        m_title.addValidationListener(new NotNullValidationListener());
+        m_title.setSize(40);
+        // Only show the title and description fields where these have
+        // been explicitly requested.
+        /*
+         * if
+         * (ItemImageAttachment.getConfig().getIsImageStepDescriptionAndTitleShown())
+         * { m_form.add(new Label("Description"));
+         * m_form.add(m_description); m_form.add(new Label("Title"));
+         * m_form.add(m_title); }
+         */
+        m_form.add(new Label("Use Context"));
+        m_useContext = new TextField("useContext");
+        m_useContext.setSize(40);
+        m_form.add(m_useContext);
+        m_saveCancel = new SaveCancelSection();
+        m_form.add(m_saveCancel);
+        ActionLink upload = new ActionLink("Upload a new image");
+        upload.addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent ev) {
+                //                    setImageComponent(ev.getPageState(), UPLOAD);
+            }
+        });
+        add(upload, ColumnPanel.FULL_WIDTH);
+    }
+
+    public ReusableImageAsset getImage(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (ReusableImageAsset) m_imageModel.getSelectedItem(ps);
+    }
+
+    @Override
+    public void register(Page p) {
+        super.register(p);
+        p.addComponentStateParam(this, m_imageID);
+    }
+
+    public String getCaption(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (String) m_caption.getValue(ps);
+    }
+
+    public String getDescription(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (String) m_description.getValue(ps);
+    }
+
+    public String getTitle(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (String) m_title.getValue(ps);
+    }
+
+    public String getUseContext(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (String) m_useContext.getValue(ps);
+    }
+
+    public Form getForm() {
+        return m_form;
+    }
+
+    public SaveCancelSection getSaveCancelSection() {
+        return m_saveCancel;
+    }
+    
+}
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ImageSelectPage.java b/ccm-cms/src/com/arsdigita/cms/ui/ImageSelectPage.java
new file mode 100644
index 000000000..71fbe64bd
--- /dev/null
+++ b/ccm-cms/src/com/arsdigita/cms/ui/ImageSelectPage.java
@@ -0,0 +1,38 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.ui;
+
+import com.arsdigita.bebop.SimpleContainer;
+import com.arsdigita.bebop.TabbedPane;
+import com.arsdigita.bebop.parameters.BigDecimalParameter;
+import com.arsdigita.cms.CMSConfig;
+import com.arsdigita.cms.dispatcher.CMSPage;
+import com.arsdigita.cms.util.GlobalizationUtil;
+
+/**
+ *
+ * @author Sören Bernstein (quasimodo) 
+ */
+public class ImageSelectPage extends CMSPage {
+
+    private final static String XSL_CLASS = "CMS Admin";
+    private TabbedPane m_tabbedPane;
+    private ImagesPane m_imagePane;
+    private BigDecimalParameter m_sectionId;
+    private static final CMSConfig s_conf = CMSConfig.getInstance();
+    private static final boolean LIMIT_TO_CONTENT_SECTION = false;
+    public static final String CONTENT_SECTION = "section_id";
+
+    public ImageSelectPage() {
+        super(GlobalizationUtil.globalize("cms.ui.item_search.page_title").localize().toString(), new SimpleContainer());
+
+        setClassAttr("cms-admin");
+
+        m_sectionId = new BigDecimalParameter(CONTENT_SECTION);
+        addGlobalStateParam(m_sectionId);
+
+//        m_imagePane = new ImagesPane();
+    }
+}
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ImageUploadComponent.java b/ccm-cms/src/com/arsdigita/cms/ui/ImageUploadComponent.java
new file mode 100644
index 000000000..daf317704
--- /dev/null
+++ b/ccm-cms/src/com/arsdigita/cms/ui/ImageUploadComponent.java
@@ -0,0 +1,131 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.ui;
+
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.form.TextArea;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.NotNullValidationListener;
+import com.arsdigita.bebop.parameters.StringLengthValidationListener;
+import com.arsdigita.cms.ImageAsset;
+import com.arsdigita.cms.ReusableImageAsset;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sören Bernstein (quasimodo) 
+ */
+public class ImageUploadComponent extends Form implements ImageComponent {
+    private final FileUploadSection m_imageFile;
+    private final TextField m_caption;
+    private final TextField m_title;
+    private final TextArea m_description;
+    private final TextField m_useContext;
+    private final SaveCancelSection m_saveCancel;
+
+    public ImageUploadComponent() {
+        super("imageUploadComponent", new ColumnPanel(2));
+        setEncType("multipart/form-data");
+        // Ignoring deprecated constructor.
+        m_imageFile = new FileUploadSection("Image Type", "image", ImageAsset.MIME_JPEG);
+        m_imageFile.getFileUploadWidget().addValidationListener(new NotNullValidationListener());
+        add(m_imageFile, ColumnPanel.FULL_WIDTH);
+        add(new Label("Caption"));
+        m_caption = new TextField("caption");
+        m_caption.addValidationListener(new NotNullValidationListener());
+        m_caption.addValidationListener(new StringLengthValidationListener(40));
+        m_caption.setSize(40);
+        add(m_caption);
+        m_title = new TextField("title");
+        m_description = new TextArea("description");
+        // We only show the title and description fields in the case where
+        // getIsImageStepDescriptionAndTitleShown is false.
+        /*
+         * if
+         * (ItemImageAttachment.getConfig().getIsImageStepDescriptionAndTitleShown())
+         * { add(new Label("Title")); m_title.addValidationListener(new
+         * NotNullValidationListener()); m_title.setSize(40);
+         * m_title.addValidationListener(new
+         * StringLengthValidationListener(40)); add(m_title);
+         *
+         * add(new Label("Description"));
+         * m_description.addValidationListener(new
+         * NotNullValidationListener());
+         * m_description.addValidationListener(new
+         * StringLengthValidationListener(600)); m_description.setCols(30);
+         * m_description.setRows(5); add(m_description);
+         *
+         * }
+         */
+        add(new Label("Use Context"));
+        m_useContext = new TextField("useContext");
+        m_useContext.setSize(40);
+        add(m_useContext);
+        m_saveCancel = new SaveCancelSection();
+        add(m_saveCancel);
+        /*
+         * Removed by Quasimodo: Changed editing workflow, so that library
+         * comes first Also, library mode has now a link to upload images
+         * whixh will link to this form. Consequently, this link will create
+         * a loop, which isn't fatal but confusing ActionLink library = new
+         * ActionLink( "Select an existing image" );
+         * library.addActionListener( new ActionListener() { public void
+         * actionPerformed( ActionEvent ev ) { setImageComponent(
+         * ev.getPageState(), LIBRARY ); } } ); add( library,
+         * ColumnPanel.FULL_WIDTH );
+         */
+    }
+
+    public SaveCancelSection getSaveCancelSection() {
+        return m_saveCancel;
+    }
+
+    public ReusableImageAsset getImage(FormSectionEvent event) throws FormProcessException {
+        PageState ps = event.getPageState();
+        String filename = (String) m_imageFile.getFileName(event);
+        File imageFile = m_imageFile.getFile(event);
+        try {
+            ReusableImageAsset image = new ReusableImageAsset();
+            image.loadFromFile(filename, imageFile, ImageAsset.MIME_JPEG);
+            image.setDescription((String) m_caption.getValue(ps));
+            return image;
+        } catch (IOException ex) {
+            ImagesPane.s_log.error("Error loading image from file", ex);
+            throw new FormProcessException(ex.getMessage());
+        }
+    }
+
+    public String getCaption(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (String) m_caption.getValue(ps);
+    }
+
+    public String getDescription(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (String) m_description.getValue(ps);
+    }
+
+    public String getTitle(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (String) m_title.getValue(ps);
+    }
+
+    public String getUseContext(FormSectionEvent event) {
+        PageState ps = event.getPageState();
+        return (String) m_useContext.getValue(ps);
+    }
+
+    public Form getForm() {
+        return this;
+    }
+    
+}
diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ImagesPane.java b/ccm-cms/src/com/arsdigita/cms/ui/ImagesPane.java
new file mode 100644
index 000000000..95c5281d3
--- /dev/null
+++ b/ccm-cms/src/com/arsdigita/cms/ui/ImagesPane.java
@@ -0,0 +1,148 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.ui;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.MapComponentSelectionModel;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.Resettable;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.SegmentedPanel;
+import com.arsdigita.bebop.SimpleComponent;
+import com.arsdigita.bebop.SimpleContainer;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.form.TextArea;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.BigDecimalParameter;
+import com.arsdigita.bebop.parameters.NotNullValidationListener;
+import com.arsdigita.bebop.parameters.StringLengthValidationListener;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ImageAsset;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ReusableImageAsset;
+import com.arsdigita.cms.util.GlobalizationUtil;
+import com.arsdigita.domain.DataObjectNotFoundException;
+import com.arsdigita.toolbox.ui.LayoutPanel;
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.log4j.Logger;
+
+/**
+ * A LayoutPanel to insert into ContentSectionPage or ImageSelectPage
+ *
+ * @author Sören Bernstein (quasimodo) 
+ */
+public class ImagesPane extends LayoutPanel implements Resettable {
+
+    public static final Logger s_log = Logger.getLogger(BrowsePane.class);
+    //private ImageChooser imageChooser;
+    private final StringParameter m_imageComponentKey;
+    private final MapComponentSelectionModel m_imageComponent;
+    private final String UPLOAD = "upload";
+    private final String LIBRARY = "library";
+
+    public ImagesPane() {
+        // Left column is empty, this is only to provide the same layout for all
+        // tabs in ContentSectionPage
+        setLeft(new SimpleComponent());
+
+        SegmentedPanel body = new SegmentedPanel();
+        body.addSegment(
+                new Label(GlobalizationUtil.globalize("cms.ui.image_browser")),
+                new ImageChooser(ContentItem.DRAFT, ImageBrowser.ADMIN_IMAGES));
+
+        setBody(body);
+        
+        m_imageComponentKey = new StringParameter("imageComponent");
+
+        ParameterSingleSelectionModel componentModel = new ParameterSingleSelectionModel(m_imageComponentKey);
+        m_imageComponent = new MapComponentSelectionModel(componentModel, new HashMap());
+
+        Map selectors = m_imageComponent.getComponentsMap();
+
+//        ImageUploadComponent upload = new ImageUploadComponent();
+//        upload.getForm().addInitListener(this);
+//        upload.getForm().addProcessListener(this);
+//        selectors.put(UPLOAD, upload);
+//        add(upload);
+//
+//        ImageLibraryComponent library = new ImageLibraryComponent();
+//        library.getForm().addInitListener(this);
+//        library.getForm().addProcessListener(this);
+//        selectors.put(LIBRARY,
+//                library);
+//        add(library);
+    }
+
+    public final void register(Page page) {
+        super.register(page);
+    }
+
+    public final void reset(PageState state) {
+        super.reset(state);
+    }
+
+    /*
+     * // Private classes and methods private final class ProcessListener
+     * implements FormProcessListener {
+     *
+     * public void process(FormSectionEvent event) throws FormProcessException {
+     * PageState ps = event.getPageState(); ImageComponent component =
+     * getImageComponent(ps);
+     *
+     * if (!component.getSaveCancelSection().getSaveButton().isSelected(ps)) {
+     * return; }
+     *
+     * ContentItem item = m_imageStep.getItem(ps); if (null == item) {
+     * s_log.error("No item selected in ImageStepEdit", new RuntimeException());
+     * return; }
+     *
+     * ReusableImageAsset image = component.getImage(event);
+     *
+     * ItemImageAttachment attachment = m_imageStep.getAttachment(ps); if (null
+     * == attachment) { attachment = new ItemImageAttachment(item, image); }
+     * attachment.setCaption(component.getCaption(event));
+     *
+     * // We only set the description and title based on the UI in // the case
+     * where getIsImageStepDescriptionAndTitleShown is true. // Otherwise, we
+     * leave this as the default value. This means // existing values are not
+     * overwritten if the image is edited when //
+     * isImageStepDescriptionAndTitleShown is false. if
+     * (ItemImageAttachment.getConfig().getIsImageStepDescriptionAndTitleShown())
+     * { attachment.setDescription(component.getDescription(event));
+     * attachment.setTitle(component.getTitle(event)); }
+     * attachment.setUseContext(component.getUseContext(event)); } }
+     *
+     * private final class SubmissionListener implements FormSubmissionListener
+     * {
+     *
+     * public final void submitted(final FormSectionEvent e) { final PageState s
+     * = e.getPageState();
+     *
+     * }
+     * }
+     */
+    public void init(FormSectionEvent event)
+            throws FormProcessException {
+        PageState ps = event.getPageState();
+
+//        ItemImageAttachment attachment = m_imageStep.getAttachment(ps);
+//        if (null == attachment) {
+        // XXX: Do something
+//        }
+    }
+}