/* * Copyright (c) 2010 Lockheed Martin Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.eurekastreams.web.client.ui.pages.start; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.eurekastreams.server.action.request.start.SetGadgetStateRequest.State; import org.eurekastreams.server.domain.Gadget; import org.eurekastreams.server.domain.GadgetDefinition; import org.eurekastreams.server.domain.Layout; import org.eurekastreams.server.domain.Tab; import org.eurekastreams.web.client.events.GadgetAddedToStartPageEvent; import org.eurekastreams.web.client.events.Observer; import org.eurekastreams.web.client.events.StartPageTabReadyEvent; import org.eurekastreams.web.client.events.data.DeletedGadgetResponseEvent; import org.eurekastreams.web.client.events.data.ReorderedGadgetResponseEvent; import org.eurekastreams.web.client.events.data.UnDeletedGadgetResponseEvent; import org.eurekastreams.web.client.events.data.UpdatedGadgetMinimizedStateResponseEvent; import org.eurekastreams.web.client.jsni.GadgetMetaDataFetcher; import org.eurekastreams.web.client.jsni.GadgetRenderer; import org.eurekastreams.web.client.ui.Session; import org.eurekastreams.web.client.ui.pages.master.StaticResourceBundle; import org.eurekastreams.web.client.ui.pages.start.dragging.GadgetDragController; import org.eurekastreams.web.client.ui.pages.start.dragging.GadgetDragHandler; import org.eurekastreams.web.client.ui.pages.start.dragging.NoInsertAtEndIndexDropController; import org.eurekastreams.web.client.ui.pages.start.dragging.TabSelectingDropController; import org.eurekastreams.web.client.ui.pages.start.layouts.DropZonePanel; import org.eurekastreams.web.client.ui.pages.start.layouts.LayoutPanelStrategy; import org.eurekastreams.web.client.ui.pages.start.layouts.OneColumnLayoutStrategy; import org.eurekastreams.web.client.ui.pages.start.layouts.TabLayoutSelectorPanel; import org.eurekastreams.web.client.ui.pages.start.layouts.ThreeColumnLayoutStrategy; import org.eurekastreams.web.client.ui.pages.start.layouts.ThreeColumnLeftWideHeaderLayoutStrategy; import org.eurekastreams.web.client.ui.pages.start.layouts.ThreeColumnRightWideHeaderLayoutStrategy; import org.eurekastreams.web.client.ui.pages.start.layouts.TwoColumnLayoutStrategy; import org.eurekastreams.web.client.ui.pages.start.layouts.TwoColumnLeftWideLayoutStrategy; import org.eurekastreams.web.client.ui.pages.start.layouts.TwoColumnRightWideLayoutStrategy; import org.eurekastreams.web.client.ui.pages.start.preferences.PortalPreferencePanel; import com.allen_sauer.gwt.dnd.client.PickupDragController; import com.allen_sauer.gwt.dnd.client.drop.IndexedDropController; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.RootPanel; /** * The tab content for a start page tab. Lays down all the drop zones and gadgets. * */ public class StartPageTabContent extends FlowPanel { /** * The preference panel. */ private PortalPreferencePanel prefPanel = new PortalPreferencePanel(); /** * Are we rendered? */ private boolean rendered = false; /** * This panel is unfortunately needed at the bottom of the layout to keep the footer from floating up. */ private FlowPanel breakPanel = new FlowPanel(); /** * the list of gadgets to render. */ private List<Gadget> gadgets; /** * The list of drop zones to render to. */ private List<DropZonePanel> dropZones = new LinkedList<DropZonePanel>(); /** * The drop zone columns. */ private List<DropZonePanel> columns = new LinkedList<DropZonePanel>(); /** * The default drag sensitivity. */ private static final int DRAG_SENSITIVITY = 10; /** * The gadget drag controller. */ private PickupDragController gadgetDragController; /** * */ private GadgetDragHandler gadgetDragHandler; /** * Absolute panel is needed because gwt-dnd only accepts them. */ private AbsolutePanel layoutContainer = new AbsolutePanel(); /** * Default constructor. * * @param inTab * the tab. */ public StartPageTabContent(final Tab inTab) { layoutContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().startTabContentContainer()); prefPanel.setPreferenceWidget(new TabLayoutSelectorPanel(inTab.getId(), inTab.getTabLayout())); this.add(prefPanel); prefPanel.hidePanel(); renderGadgetContainer(inTab); Session.getInstance().getEventBus().addObservers(new Observer() { public void update(final Object arg1) { resetEmptyZones(); } }, ReorderedGadgetResponseEvent.class, UnDeletedGadgetResponseEvent.class, GadgetAddedToStartPageEvent.class, DeletedGadgetResponseEvent.class, UpdatedGadgetMinimizedStateResponseEvent.class); Session.getInstance().getEventBus().addObserver(StartPageTabReadyEvent.class, new Observer<StartPageTabReadyEvent>() { public void update(final StartPageTabReadyEvent event) { gadgetDragController.registerDropController(new TabSelectingDropController(event.getTab())); } }); } /** * Render the gadget container. If a new tab is put in here the tab will rerender everything. * * @param inTab * the tab. */ public void renderGadgetContainer(final Tab inTab) { rendered = false; gadgetDragHandler = new GadgetDragHandler(inTab.getId()); gadgetDragController = new GadgetDragController(RootPanel.get(), false); gadgetDragController.setBehaviorConstrainedToBoundaryPanel(false); gadgetDragController.setBehaviorMultipleSelection(false); gadgetDragController.setBehaviorDragStartSensitivity(DRAG_SENSITIVITY); gadgetDragController.addDragHandler(gadgetDragHandler); gadgetDragController.setBehaviorDragProxy(true); layoutContainer.clear(); gadgets = inTab.getGadgets(); LayoutPanelStrategy strategy = getStrategy(inTab.getTabLayout()); dropZones = strategy.getDropZones(); columns = strategy.getColumns(); for (DropZonePanel column : columns) { layoutContainer.add(column); } for (Gadget gadget : gadgets) { insertGadget(gadget, false); } for (DropZonePanel dropZone : dropZones) { dropZone.setSpacer(new FlowPanel()); IndexedDropController gadgetDropController = new NoInsertAtEndIndexDropController(dropZone); gadgetDragController.registerDropController(gadgetDropController); } this.add(layoutContainer); // The break panel is needed for CSS lameness so the footer doesn't // float up. breakPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().breakClass()); layoutContainer.add(breakPanel); resetEmptyZones(); } /** * Reset empty zones. */ public void resetEmptyZones() { for (DropZonePanel dropZone : dropZones) { if (dropZone.getVisibleGadgetCount() == 0) { dropZone.addStyleName(StaticResourceBundle.INSTANCE.coreCss().emptyZone()); } else { dropZone.setVisible(true); dropZone.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().emptyZone()); } } } /** * Insert a gadget. * * @param gadget * the gadget. * @param render * whether or not to render it now with shindig. */ public void insertGadget(final Gadget gadget, final boolean render) { insertGadgetPanel(new GadgetPanel(gadget), gadget.getZoneNumber(), gadget.getZoneIndex()); if (render) { GadgetRenderer.getInstance().renderGadget(Long.toString(gadget.getId())); if (gadget.getGadgetUserPref() != null && !gadget.getGadgetUserPref().equals("")) { saveUserPrefs(gadget.getId()); } } } /** * Insert a gadget panel. * * @param gadgetPanel * the gadget panel. * @param zoneNumber * the zone. * @param zoneIndex * the index. */ public void insertGadgetPanel(final GadgetPanel gadgetPanel, final int zoneNumber, final int zoneIndex) { gadgetPanel.makeGadgetDraggable(gadgetDragController); dropZones.get(zoneNumber).insertGadget(gadgetPanel, zoneIndex); for (DropZonePanel dropZone : dropZones) { for (GadgetPanel anyGadget : dropZone.getGadgetZones()) { if (anyGadget.getGadgetState().equals(State.MAXIMIZED)) { gadgetPanel.setVisible(false); } } } } /** * Are any of the gadgets maximized? * @return the value. */ public boolean isAnyGadgetMaximized() { for (DropZonePanel dropZone : dropZones) { for (GadgetPanel anyGadget : dropZone.getGadgetZones()) { if (anyGadget.getGadgetState().equals(State.MAXIMIZED)) { return true; } } } return false; } /** * Save the user prefs. * * @param id * the id of the gadget. */ private static native void saveUserPrefs(final Long id) /*-{        var gadget = $wnd.shindig.container.getGadget(id);        gadget.setUserPrefs(gadget.userPrefs_); }-*/; /** * Show the tab layout selector. */ public void showTabLayoutSelector() { prefPanel.showPanel(); } /** * Hide the tab layout selector. */ public void hideTabLayoutSelector() { prefPanel.hidePanel(); } /** * Render the gadgets. Has to be done after everything else. */ public void renderGadgets() { DeferredCommand.addCommand(new Command() { public void execute() { if (!rendered) { for (Gadget gadget : gadgets) { if (!gadget.isMinimized()) { GadgetRenderer.getInstance().renderGadget(Long.toString(gadget.getId())); } } for (DropZonePanel dropZone : dropZones) { for (GadgetPanel gadgetPanel : dropZone.getGadgetZones()) { if (gadgetPanel.getGadgetData().isMaximized() != null && gadgetPanel.getGadgetData().isMaximized()) { gadgetPanel.setGadgetState(State.MAXIMIZED); } } } } rendered = true; } }); } /** * Refresh metadata for all gadgets on this tab. */ public void refreshGadgetMetadata() { if (gadgets != null && gadgets.size() > 0) { List<GadgetDefinition> gadgetDefList = new ArrayList<GadgetDefinition>(); for (Gadget gadget : gadgets) { gadgetDefList.add(gadget.getGadgetDefinition()); } (new GadgetMetaDataFetcher(gadgetDefList)).fetchMetaData(); } } /** * Identify the LayoutPanelStrategy that works for the layout. * * @param layout * the layout to get a strategy for. * @return the strategy. */ private LayoutPanelStrategy getStrategy(final Layout layout) { switch (layout) { case ONECOLUMN: return new OneColumnLayoutStrategy(); case TWOCOLUMN: return new TwoColumnLayoutStrategy(); case TWOCOLUMNLEFTWIDE: return new TwoColumnLeftWideLayoutStrategy(); case TWOCOLUMNRIGHTWIDE: return new TwoColumnRightWideLayoutStrategy(); case THREECOLUMNLEFTWIDEHEADER: return new ThreeColumnLeftWideHeaderLayoutStrategy(); case THREECOLUMNRIGHTWIDEHEADER: return new ThreeColumnRightWideHeaderLayoutStrategy(); case THREECOLUMN: return new ThreeColumnLayoutStrategy(); default: return new OneColumnLayoutStrategy(); } } }