/*******************************************************************************
* Copyright (c) 2009, 2014 Angelo Zerr and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
* Brian de Alwis (MTI) - Performance tweaks (Bug 430829)
*******************************************************************************/
package org.eclipse.e4.ui.css.swt.dom;
import java.util.ArrayList;
import java.util.Collections;
import org.eclipse.e4.ui.css.core.dom.ArrayNodeList;
import org.eclipse.e4.ui.css.core.dom.CSSStylableElement;
import org.eclipse.e4.ui.css.core.dom.ChildVisibilityAwareElement;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.swt.helpers.CSSSWTColorHelper;
import org.eclipse.e4.ui.internal.css.swt.ICTabRendering;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Widget;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* {@link CSSStylableElement} implementation which wrap SWT {@link CTabFolder}.
*
*/
public class CTabFolderElement extends CompositeElement implements ChildVisibilityAwareElement {
private final static String BACKGROUND_SET_BY_TAB_RENDERER = "bgSetByTabRenderer"; //$NON-NLS-1$
private SelectionListener selectionListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
applyStyles(getWidget(), true);
}
};
public CTabFolderElement(CTabFolder tabFolder, CSSEngine engine) {
super(tabFolder, engine);
}
@Override
public void initialize() {
super.initialize();
((CTabFolder) getControl()).addSelectionListener(selectionListener);
}
@Override
public void dispose() {
CTabFolder ctf = (CTabFolder) getControl();
if (ctf != null && !ctf.isDisposed()) {
ctf.removeSelectionListener(selectionListener);
}
super.dispose();
}
/**
* Compute static pseudo instances.
*
*/
@Override
protected void computeStaticPseudoInstances() {
super.computeStaticPseudoInstances();
// it's CTabFolder. Set selected as static pseudo instance.
// because this widget define methods
// CTabFolder#setSelectionBackground (Color color)
// which set background Color when a CTabItem is selected.
super.addStaticPseudoInstance("selected");
}
@Override
public Node item(int index) {
Widget widget = getWidget();
// retrieve the child control or child item depending on the
// index
CTabFolder folder = (CTabFolder) widget;
int length = folder.getChildren().length;
if (index >= length) {
Widget w = folder.getItem(index - length);
return getElement(w);
} else {
Widget w = folder.getChildren()[index];
return getElement(w);
}
}
@Override
public int getLength() {
Widget widget = getWidget();
int childCount = 0;
if (widget instanceof Composite) {
childCount = ((Composite) widget).getChildren().length;
if (widget instanceof CTabFolder) {
// if it's a CTabFolder, include the child items in the count
childCount += ((CTabFolder) widget).getItemCount();
}
}
return childCount;
}
@Override
public void reset() {
CTabFolder folder = (CTabFolder) getWidget();
folder.setSelectionBackground((Color) null);
folder.setSelectionForeground((Color) null);
folder.setSelectionBackground((Image) null);
folder.setBackground(null, null);
resetChildrenBackground(folder);
if (folder.getRenderer() instanceof ICTabRendering) {
ICTabRendering renderer = (ICTabRendering) folder
.getRenderer();
folder.setRenderer(null);
renderer.setSelectedTabFill(null);
renderer.setTabOutline(null);
renderer.setInnerKeyline(null);
renderer.setOuterKeyline(null);
renderer.setShadowColor(null);
}
super.reset();
}
@Override
public NodeList getVisibleChildNodes() {
// CTabFolder#getChildren() exposes the "tab controls" (the toolbars and
// the top-right area), as well as the composites used to host the
// CTabItem contents. We need to expose both the CTabItems but
// just the composite of the active CTabItem
CTabFolder folder = (CTabFolder) getWidget();
ArrayList<Widget> visible = new ArrayList<Widget>();
if (folder.getTopRight() != null) {
visible.add(folder.getTopRight());
}
Collections.addAll(visible, folder.getItems());
int selected = folder.getSelectionIndex();
// if (selected < 0 && folder.getItemCount() > 0) {
// selected = 0;
// }
if (selected >= 0) {
CTabItem item = folder.getItem(selected);
// If item.getControl() is not yet set, we pretend it doesn't exist
if (item.getControl() != null) {
visible.add(item.getControl());
}
}
return new ArrayNodeList(visible, engine);
}
private void resetChildrenBackground(Composite composite) {
for (Control control : composite.getChildren()) {
resetChildBackground(control);
if (control instanceof Composite) {
resetChildrenBackground((Composite) control);
}
}
}
private void resetChildBackground(Control control) {
Color backgroundSetByRenderer = (Color) control
.getData(BACKGROUND_SET_BY_TAB_RENDERER);
if (backgroundSetByRenderer != null) {
if (control.getBackground() == backgroundSetByRenderer) {
control.setBackground(null);
}
control.setData(BACKGROUND_SET_BY_TAB_RENDERER, null);
}
}
public static void setBackgroundOverriddenDuringRenderering(
Composite composite, Color background) {
CSSSWTColorHelper.setBackground(composite, background);
composite.setData(BACKGROUND_SET_BY_TAB_RENDERER, background);
for (Control control : composite.getChildren()) {
if (!CompositeElement.hasBackgroundOverriddenByCSS(control)) {
CSSSWTColorHelper.setBackground(control, background);
control.setData(BACKGROUND_SET_BY_TAB_RENDERER, background);
}
}
}
}