/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.ui.figures; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.draw2d.ActionEvent; import org.eclipse.draw2d.ActionListener; import org.eclipse.draw2d.Border; import org.eclipse.draw2d.ButtonModel; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.LayoutAnimator; import org.eclipse.draw2d.LayoutManager; import org.eclipse.draw2d.Toggle; import org.whole.lang.ui.layout.ITabularLayoutClient; import org.whole.lang.ui.layout.ITabularLayoutServer; import org.whole.lang.ui.layout.MonoLayout; import org.whole.lang.ui.layout.StackLayout; import org.whole.lang.ui.layout.ViewportTracking; import org.whole.lang.ui.util.AnimableRunnable; import org.whole.lang.util.CompositeUtils; /** * @author Riccardo Solmi */ public class ContentPaneFigure extends EntityFigure implements IFoldableFigure { public static final int[] EMPTY_INT_ARRAY = new int[0]; protected IEntityFigure[] contentPanes = null; protected int[] toggleIndexOfContentPane = EMPTY_INT_ARRAY; private List<Toggle> foldingToggles = Collections.emptyList(); protected ContentPaneFigure() { } public ContentPaneFigure(LayoutManager layout) { super(layout); } public List<Toggle> getFoldingToggles() { return foldingToggles; } public Toggle getFoldingToggle(int toggleIndex) { return getFoldingToggles().get(toggleIndex); } public List<Toggle> getFoldingToggles(IFigure figure) { List<Toggle> result = new ArrayList<Toggle>(2); int paneIndex = ancestorOrSelfContentPaneIndexOf(figure); if (paneIndex == -1) return result; int toggleIndex = toggleIndexOf(paneIndex); if (toggleIndex == -1) return result; result.add(getFoldingToggle(toggleIndex)); return result; } protected int toggleIndexOf(int paneIndex) { return paneIndex >= toggleIndexOfContentPane.length ? -1 : toggleIndexOfContentPane[paneIndex]; } protected void bindFoldingToggle(int toggleIndex, int... paneIndexes) { int maxIndex = contentPanes.length-1; for (int i = 0; i < paneIndexes.length; i++) if (paneIndexes[i] > maxIndex) maxIndex = paneIndexes[i]; toggleIndexOfContentPane = CompositeUtils.grow(toggleIndexOfContentPane, maxIndex+1, -1); for (int paneIndex : paneIndexes) if (paneIndex >= 0 && paneIndex < toggleIndexOfContentPane.length) toggleIndexOfContentPane[paneIndex] = toggleIndex; } protected int ancestorOrSelfContentPaneIndexOf(IFigure figure) { if (contentPanes == null) return -1; do { int index = contentPaneIndexOf(figure); if (index >= 0) return index; figure = figure.getParent(); } while (figure != this); return -1; } protected int contentPaneIndexOf(IFigure contentPane) { for (int i=0; i<contentPanes.length; i++) if (contentPanes[i] == contentPane) return i; return -1; } public void clickFoldingToggle(final int toggleIndex) { ButtonModel model = getFoldingToggle(toggleIndex).getModel(); model.setSelected(!model.isSelected()); for (int i = toggleIndexOfContentPane.length-1; i >= 0; i--) if (toggleIndexOfContentPane[i] == toggleIndex) { toggleVisibility(i); break; } } // public void add(IFigure figure, Object constraint, int index) { // super.add(figure, constraint, index); // for (IFigure f : contentPanes) // if (f == null) // return; // // for (int toggleIndex=0; toggleIndex<foldingToggles.size(); toggleIndex++) { // ButtonModel model = getFoldingToggle(toggleIndex).getModel(); // if (!model.isSelected()) // toggleLayout(toggleIndex); // } // } public Toggle createFoldingToggle(int paneIndexOrTag, int... paneIndexes) { return createFoldingToggle(new EntityToggle(), paneIndexOrTag, paneIndexes); } public Toggle createFoldingToggle(Toggle toggle, final int paneIndexOrTag, int... paneIndexes) { toggle.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { new AnimableRunnable() { public void doRun() { toggleVisibility(paneIndexOrTag); } }.syncExec(); } }); createActionableFoldingToggle(toggle, paneIndexes); bindFoldingToggle(foldingToggles.size()-1, paneIndexOrTag); return toggle; } public Toggle createActionableFoldingToggle(Toggle toggle, int... paneIndexes) { if (foldingToggles == Collections.EMPTY_LIST) { foldingToggles = new ArrayList<Toggle>(); addLayoutListener(LayoutAnimator.getDefault()); } foldingToggles.add(toggle); bindFoldingToggle(foldingToggles.size()-1, paneIndexes); return toggle; } protected void toggleVisibility(int paneIndexOrTag) { IFigure contentPane = getContentPane(paneIndexOrTag); contentPane.setVisible(!contentPane.isVisible()); } public void initContentPanes(int size) { contentPanes = new IEntityFigure[size]; } public IEntityFigure createContentPane(int paneIndex) { return createContentPane(paneIndex, ViewportTracking.NONE); } public IEntityFigure createContentPane(int paneIndex, Border border) { IEntityFigure contentPane = createContentPane(paneIndex); contentPane.setBorder(border); return contentPane; } public IEntityFigure createContentPane(int paneIndex, ViewportTracking viewportTracking) { MonoLayout monoLayout = new MonoLayout().withInheritedAlignment(); if (viewportTracking.isHorizontal()) monoLayout.withMajorAutoresizeWeight(1.0f); if (viewportTracking.isVertical()) monoLayout.withMinorAutoresizeWeight(1.0f); return createContentPane(paneIndex, new EntityFigure(monoLayout) { public ITabularLayoutServer getTabularLayoutServer() { return getParent() instanceof IEntityFigure ? ((IEntityFigure) getParent()).getTabularLayoutServer() : null; } public ITabularLayoutClient getTabularLayoutClient() { return ((IEntityFigure) getChildren().get(0)).getTabularLayoutClient(); } }.withViewportTracking(viewportTracking)); } public IEntityFigure createContentPane(int paneIndex, IEntityFigure figure) { return contentPanes[paneIndex] = figure; } public IFigure createNestedContentPanes(int firstPaneIndex, IEntityFigure figure) { for (int i=0; i<figure.getContentPanesSize(); i++) contentPanes[firstPaneIndex+i] = figure.getContentPane(i); if (figure instanceof IFoldableFigure) { if (foldingToggles == Collections.EMPTY_LIST) foldingToggles = new ArrayList<Toggle>(); foldingToggles.addAll(((IFoldableFigure) figure).getFoldingToggles()); } return figure; } public int getContentPanesSize() { return contentPanes != null ? contentPanes.length : 1; } public IEntityFigure getContentPane(int paneIndex) { return contentPanes != null ? contentPanes[paneIndex] : this; } public <F extends IEntityFigure> F addWithPlaceHolder(F child) { IEntityFigure stackedFigure = new EntityFigure(new StackLayout()); stackedFigure.add(LabelFactory.createEmptyLabel()); stackedFigure.add(child); add(stackedFigure); return child; } }