Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,58 @@

import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;


/**
* Add SWT filter to the {@link Display} to apply styles when SWT widget is
* resized or showed.
* Applies styles to the widgets of a {@link Display} when they are skinned, and
* to a {@link CTabFolder} page skipped while hidden once it is the selected
* tab's page.
*/
public class CSSSWTApplyStylesListener {
CSSEngine engine;
public CSSSWTApplyStylesListener(Display display, final CSSEngine engine) {
this.engine = engine;
display.addListener(SWT.Skin, event -> {
if (engine != null) {
engine.applyStyles(event.widget, false);
if (engine == null) {
return;
}
engine.applyStyles(event.widget, false);
if (event.widget instanceof Control control && control.getParent() instanceof CTabFolder folder
&& !isPageOfSelectedTab(folder, control)) {
// the folder exposes only the selected page, so the engine skipped this one
styleWhenItBecomesThePage(folder, control);
}
});
}

/**
* Styles the control once it is the selected tab's page, which attaching it
* to its item (a resize) or selecting its tab (a show) makes it.
*/
private void styleWhenItBecomesThePage(CTabFolder folder, Control control) {
Listener listener = new Listener() {
@Override
public void handleEvent(Event event) {
if (!isPageOfSelectedTab(folder, control)) {
return;
}
control.removeListener(SWT.Show, this);
control.removeListener(SWT.Resize, this);
engine.applyStyles(control, true);
}
};
control.addListener(SWT.Show, listener);
control.addListener(SWT.Resize, listener);
}

private static boolean isPageOfSelectedTab(CTabFolder folder, Control control) {
int selected = folder.getSelectionIndex();
return selected >= 0 && folder.getItem(selected).getControl() == control;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@
import static org.eclipse.e4.ui.tests.css.swt.CssSwtEngine.WHITE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.IOException;
import java.io.StringReader;

import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.swt.dom.WidgetElement;
import org.eclipse.e4.ui.css.swt.engine.CSSSWTEngineImpl;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
Expand Down Expand Up @@ -190,17 +195,6 @@ void testBorderVisible() {
assertEquals(false, folderToTest.getBorderVisible());
assertEquals("false", css.getEngine().retrieveCSSProperty(folderToTest, "border-visible", null));
}
@Test
void testSimple() {
CTabFolder folderToTest = createTestCTabFolder("CTabFolder { swt-simple: true}");
assertEquals(true, folderToTest.getSimple());
assertEquals("true", css.getEngine().retrieveCSSProperty(folderToTest, "swt-simple", null));
folderToTest.getShell().close();
folderToTest = createTestCTabFolder("CTabFolder { swt-simple: false}");
// Curved tabs are no longer supported, so getSimple() always returns true
assertEquals(true, folderToTest.getSimple());
assertEquals("true", css.getEngine().retrieveCSSProperty(folderToTest, "swt-simple", null));
}

@Test
void testMaximizeVisible() {
Expand Down Expand Up @@ -356,4 +350,64 @@ void testMinimumCharacters() {
assertEquals(1, folderToTest.getMinimumCharacters());
assertEquals("1", css.getEngine().retrieveCSSProperty(folderToTest, "swt-tab-text-minimum-characters", null));
}

@Test
void testPageSelectedProgrammaticallyAfterSkinningIsStyled() throws IOException {
Display display = css.getDisplay();
CSSEngine engine = new CSSSWTEngineImpl(display, true);
engine.setErrorHandler(e -> fail(e.getMessage()));
// the class selector keeps this engine's skin listener off other tests' widgets
engine.parseStyleSheet(new StringReader(".tabPage { background-color: #FF0000 }"));

Shell shell = new Shell(display, SWT.SHELL_TRIM);
shell.setLayout(new FillLayout());
CTabFolder folderToTest = new CTabFolder(shell, SWT.NONE);
CTabItem tab1 = new CTabItem(folderToTest, SWT.NONE);
tab1.setText("A TAB ITEM");
// no selection yet, so the folder hides the page from the engine
Composite page = new Composite(folderToTest, SWT.NONE);
WidgetElement.setCSSClass(page, "tabPage");
tab1.setControl(page);
spinEventLoop(display); // the skin pass skips the hidden page

folderToTest.setSelection(0); // programmatic, so no selection event

spinEventLoop(display);

assertEquals(RED, page.getBackground().getRGB());
}

@Test
void testPageAttachedToItsItemAfterSkinningIsStyled() throws IOException {
Display display = css.getDisplay();
CSSEngine engine = new CSSSWTEngineImpl(display, true);
engine.setErrorHandler(e -> fail(e.getMessage()));
engine.parseStyleSheet(new StringReader(".tabPage { background-color: #FF0000 }"));

Shell shell = new Shell(display, SWT.SHELL_TRIM);
shell.setLayout(new FillLayout());
CTabFolder folderToTest = new CTabFolder(shell, SWT.NONE);
CTabItem tab1 = new CTabItem(folderToTest, SWT.NONE);
tab1.setText("A TAB ITEM");
folderToTest.setSelection(0);
shell.setSize(400, 300);
shell.layout(true, true);

Composite page = new Composite(folderToTest, SWT.NONE);
WidgetElement.setCSSClass(page, "tabPage");
// skinned before it is attached, as a Search dialog page is
spinEventLoop(display);

tab1.setControl(page); // already visible, so no show event either

spinEventLoop(display);

assertEquals(RED, page.getBackground().getRGB());
}

private static void spinEventLoop(Display display) {
while (display.readAndDispatch()) {
// deliver pending skin and show events
}
}
}
Loading