Portal Layout

Hello, folks!

I have recently published
the first version of the PortalLayout for Vaadin
.

What is Portal?

Portal is basically a stack panel that has portlets laid out in a column.


What is portlet?

Portlet is a client side wrapper for the component. You add component to the portal on the server side and the add-on automatically wraps it in portlet. Portlet holds the caption of the component in the header. Header is also works as a draggable area of the portlet and keeps the controls (collapse and close buttons currently).


If a portal is a simple column, what cool I can do with it?

The good news is that portals can share the contents between each other. For example, you can take a panel with a HorizontalLayout, put several PortalLayouts in it, adjust expand ratios etc. And then you can use the set of Portals like one big. When component is dragged from one portal to another or closed, collapsed etc - server side gets notified. Using this approach you can achieve rather complex structure of your portal views.


What if I don’t want my portlets to be closable/collapsible/draggable

This all is customizable through the server side API which is pretty minimalistic. All the methods resemble smth like:


portal.setClosable(component, false);


What about the size restrictions?

The width of all the portlets is 100% always, so should be the width of the components. If you do not set it to 100%, add-on will do it for you. Height is not that restricted - it can be either fixed (e.g. “200px”) or relative (e.g. “50%”) or undefined. In the scope of PortalLayout relative height is understood the percentage of free space that the portlet would try to consume. Free space - space left after calculation of the space required for the fixed height portlets. If there’s so called “overflow” of relative height - then each portlet with relative height will get normalized amount of space. For instance, we have occasionally have three portlets in one portal each trying to consumed 50% of space (150% totally). Then the space is evenly divided among them.
It is worth mentioning that if you want to have multiple fixed sized portlets on your view - it is a good choice to put portals inside the panels and give them some initial fixed size. In this case you will get scrollbars from the panel if needed. Anyway, portal should never clip its contents.


What if I do not want some of my portals share content with others?

Try passing false to this method:


void setCommunicative(boolean isCommunicative)

And your portlets will be draggable only within current portal, which won’t also accept contents from other portals.


What should be inside of the portlets?

Each portlet holds one component. So you can add a single button or a TextField inside. However, it would be more logically to add something more complex, like tables, panels, other ComponentContainers.

So far, there are a lot of things to be accomplished and they are on the schedule. You are welcome to try the add-on out. I would highly appreciate your your suggestions, complaints, ideas.

Best Regards,
Alexander.

Hi,

Two embedded flash objects in one portallayout fails. Did somebody encounter the same problem?

regards,
Alper.

Hi,

The code snippet would be a perfect thing that would help me to resolve the problem you encountered. However, those video samples form demo are basically flash objects and can be added to the portal just fine.


Sasha.

UPD. Created
a small demo
, where all the players - embedded objects
like in the sampler
. If it might help - here is the code of the view.

package org.vaadin.sasha.portalappdemo;

import org.vaadin.sasha.portallayout.PortalLayout;

import com.vaadin.terminal.ExternalResource;
import com.vaadin.ui.Component;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;

@SuppressWarnings("serial")
public class TestEmbeddedTab extends Panel{

    private final HorizontalLayout layout = new HorizontalLayout();
    
    public TestEmbeddedTab() {
        super();
        setSizeFull();
        layout.setWidth("100%");
        layout.setMargin(true);
        layout.setSpacing(true);
        setContent(layout);
        buildPortals();
    }

    private void buildPortals() {
        for (int i = 0; i < 3; ++i) {
            final PortalLayout portal = new PortalLayout();
            portal.setHeight("700px");
            layout.addComponent(portal);
            
            Component c = createTestEmbedded();
            portal.addComponent(c);
            portal.setComponentCaption(c, "test");
            
            c = createTestEmbedded();
            portal.addComponent(c);
            portal.setComponentCaption(c, "test1");
        }
    }
    
    private Embedded createTestEmbedded() {
        Embedded e = new Embedded(null, new ExternalResource(
                "http://www.youtube.com/v/meXvxkn1Y_8&hl=en_US&fs=1&"));
        e.setMimeType("application/x-shockwave-flash");
        e.setParameter("allowFullScreen", "true");
        e.setWidth("320px");
        e.setHeight("265px");
        return e;
    }
}

By the way,

The new add-on version (0.4.1) is out there.


Sasha.

Hi,
I am using open flash chart add-on(http://code.google.com/p/ofcvaadin/),but change it a little bit. The following code is inside a custom component. Iwill check 0.4.1
Thanks,.

        [code]

final ClassResource flashResource = new ClassResource(this.getClass(), “open-flash-chart.swf”, application);
// Display the resource in a Embedded compoant
final Embedded embedded = new Embedded(“Embedded Caption”, flashResource);
embedded.setMimeType(“application/x-shockwave-flash”);
// This is the default type, but we set it anyway.
embedded.setType(Embedded.TYPE_OBJECT);
// This is recorgnized automatically, but set it anyway.
embedded.setMimeType(“application/x-shockwave-flash”);
embedded.setParameter(“quality”, “high”);
embedded.setParameter(“bgcolor”, “#000000”);
embedded.setParameter(“wmode”, “transparent”);
embedded.setParameter(“width”, “500px”);
embedded.setParameter(“height”, “200px”);
embedded.setParameter(“name”, flashObjectId);
embedded.setParameter(“flashvars”, “data-file=” + dataUrl + “?time=” + System.currentTimeMillis());
embedded.setParameter(“align”, “middle”);
embedded.setParameter(“allowScriptAccess”, “sameDomain”);
embedded.setParameter(“type”, “application/x-shockwave-flash”);
embedded.setParameter(“pluginspage”, “http://www.macromedia.com/go/getflashplayer”);
embedded.setWidth(“500px”);
embedded.setHeight(“200px”);

        setCompositionRoot(embedded

[/code]);

Hi,

Flash problem is solved some how with 0.4.1, This version is more stable I suppose.-_-

thanks,

Hi,

Awesome! I am very glad it helped!


Sasha

I’m addicted to icons… can we get icons into the portlet header?

Also, any reason why PortalLayout.addComponent(Component) doesn’t set the caption to the components caption? ie. so you don’t have to addComponent(comp) then setComponentCaption(comp, comp.getCaption())?

–jason

Hi, Jason,

The full and proper support for Vaadin captions (both on client and server side) is coming out right in the next version (most likely next weekend). This also implies icons and error indicators.


sasha

Cool.

How about getting the [-]
icon to flip to a [+]
icon when the porlet is minimized?

Also, I tried to increase the spacing between portlets when setSpacing(true) is set, with:


.v-portallayout-spacing {
    height: 12px;
    width: 12px;
}

But this seem to um, like work 25% of the time and would get lost on reloading the page.

I added a shadow around portlets and the default spacing is too small:


.v-portlet-header {
    border-radius: 5px 5px 0 0;
    -moz-box-shadow: 5px 5px 5px #ccc;
    -webkit-box-shadow: 5px 5px 5px #ccc;
    box-shadow: 5px 5px 5px #ccc;
}
.v-portlet-content {
    background-color: #FEFEFE;
    -moz-box-shadow: 5px 5px 5px #ccc;
    -webkit-box-shadow: 5px 5px 5px #ccc;
    box-shadow: 5px 5px 5px #ccc;
    border-left: 1px solid #DFDFDF;
}

Have you been able to change the spacing size and have it stick?

BTW all of the other developers we have working on our Vaadin app really like the portlets, really helps make the UI feel more dynamic.

–jason

Hello!
Is there a possibility to add any custom action when clicking on the close/remove (x) button? I store the content of a portlet in the database and if someone clicks on the close/remove button I want to remove the content form the portlet from the database.
The closeListener form vaadin window can´t be used.

Beside this a really great work, thank you! :grin:

Greetings,
Florian

Hi Florian!

Didn’t find a way to add custom action to close, but did the following quick workaround:


portal.setClosable(comp, false);
ThemeResource icon = new ThemeResource("../reindeer/window/img/close.png");
portal.addAction(comp, new ToolbarAction(icon ) {
			
		@Override
		public void execute() {

			// Custom close handling goes here

			// Actually do the pending close
			PortalLayout portal = (PortalLayout) comp.getParent();
			portal.removeComponent(comp);
			portal.requestRepaint();
		}
});

Hi,

That’s what I’ve surely overlooked.
Thanks guys for pointing out the things to be improved. Doing my best to save the weekend for this project.

Stay online.

sasha

I might suggest a small API change for ToolbarAction: Pass the context information to the execute method.

Something like:

public void execute(PortalLayout parent, Component component);

That would make the implementation (and possibly reuse) of action handlers much easier.

Thank you for your help, you answered nearly on time that´s great. The workaround is working fine, I did not think about that!.

During testing I found two additonal small things:

First, when you move a lot around with the portlets in my code it can happen that if I click on the top of the portlet to move I mark the text instead of moving around. I do not know if this only happens to me.

Second, if you do not use a fix height for the portlets and have portlets with different sizes it is not rendering right. The marker which shows me where I can put the portlet is somewhere behind another portlet. But I think this is a failure by my code because I should use a fix height for the portlets.

However, thank you a lot for your help!
Florian

Hi,

What do you imply under portlet height not fixed - is it a relative height or just height undefined? There are might be some tricky cases when you have to be careful with the size set up (both for portlets and portal). Anyway, what I would propose in most cases - to use a Panel (fixed height, content height - not set) with several Portals in it. In such case everything wil most likely work just fine and you’ll never get your portlets clipped by the container that holds portal.


sasha

I have a problem with the replaceComponent method of the PortalLayout. I used previously a VerticalLayout with a component where one coud choose the portlet to display. Upon clicking on the add button that component gets replaced by the portlet.

I have something like


@Override
    public void buttonClick(Button.ClickEvent event) {
        portletContext.replacePortlet(portletDefinition.createPortlet());
        getApplication().getMainWindow().removeWindow(window);
    }

which does something like


public void replacePortlet(Component newPortlet) {
        if (newPortlet == null) {
            throw new IllegalArgumentException("newPortlet could not be null.");
        }
        owner.replaceComponent(portlet, newPortlet);
}

where owner is my VerticalLayout. If I replace VerticalLayout with PortalLayout, I get the portlets right and the ability to drag and drop them but the code that replace the components does not work anymore.

Is this a bug in the PortalLayout#replaceComponent method or should I use another mechanism to replace the content of a component within a PortalLayout.

Thanks!

Hi,

Sounds like a bug.

As a temporary workaround I would suggest you trying to remove the component with:

removeComponent(...)

and then addding with:

addComponent(...)

Should do the thing. I will include this case in my add-on review this weekend.

Appreciate your feedback

sasha

Well I guess this answers my question:
http://code.google.com/p/vaadin-portal-layout/source/browse/trunk/src/org/vaadin/sasha/portallayout/PortalLayout.java#554

Why is this code empty? How about throwing an exception stating that you don’t support the feature instead? If so, how can I achieve my use case with this layout?

Thanks

Well, I could do that but I want to replace that component, no add a new one. Say I have 3 portlets aligned vertically (A, B, C). Initially, I just have 3 portlets with a central add button. If I click it opens a pop-up window asking me to choose the portlet. When I click on add, it replaces that empty portlet with the add button with the portlet I have chosen. I guess add will add the component at the end right? So If click on A, I would get the portlet after B and C

Anyway, it’s not a blocker :slight_smile:

I am on training next week in your facilities so we can have a quick chat about the PortalLayout. I think it’s a great feature and we might use it.

Thanks for the quick reply btw,
S.