diff --git a/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/Draw2dTestSuite.java b/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/Draw2dTestSuite.java index 876e5bec1..a251c733a 100644 --- a/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/Draw2dTestSuite.java +++ b/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/Draw2dTestSuite.java @@ -43,6 +43,7 @@ PrecisionPointTest.class, PrecisionRectangleTest.class, ThumbnailTest.class, + FigurePaintingTest.class, FigureUtilitiesTest.class, RectangleTest.class, ColorConstantTest.class, diff --git a/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/FigurePaintingTest.java b/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/FigurePaintingTest.java new file mode 100644 index 000000000..0e1b5ecd6 --- /dev/null +++ b/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/FigurePaintingTest.java @@ -0,0 +1,342 @@ +/******************************************************************************* + * Copyright (c) 2011, 2023 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.draw2d.test; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.widgets.Display; + +import org.eclipse.draw2d.ColorConstants; +import org.eclipse.draw2d.Figure; +import org.eclipse.draw2d.LineBorder; +import org.eclipse.draw2d.geometry.Dimension; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.draw2d.test.utils.TestFigure; +import org.eclipse.draw2d.test.utils.TestLogger; + +import org.junit.Before; +import org.junit.Test; + +@SuppressWarnings("nls") +public class FigurePaintingTest extends BaseTestCase { + private TestLogger expectedLogger; + private TestLogger actualLogger; + private Figure testFigure; + + @Before + public void setUp() { + expectedLogger = new TestLogger(); + actualLogger = new TestLogger(); + testFigure = new TestFigure(actualLogger); + } + + @Test + public void test_repaint() throws Exception { + testFigure.setBounds(new Rectangle(10, 11, 50, 78)); + actualLogger.clear(); + // + // check repaint from figure fully + testFigure.repaint(); + expectedLogger.log("repaint(10, 11, 50, 78)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint from invisible figure + testFigure.setVisible(false); + actualLogger.clear(); + // + testFigure.repaint(); + actualLogger.assertEmpty(); + } + + @Test + public void test_add() throws Exception { + // + // check reset state during add child figure with empty bounds + testFigure.add(new Figure()); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check reset state during add(Figure) child figure with not empty bounds + Figure testChildFigure = new Figure(); + testChildFigure.setBounds(new Rectangle(1, 2, 3, 4)); + testFigure.add(testChildFigure); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(1, 2, 3, 4)"); + actualLogger.assertEquals(expectedLogger); + } + + @Test + public void test_remove() throws Exception { + testFigure.setBounds(new Rectangle(10, 11, 50, 78)); + actualLogger.clear(); + // + Figure testChildFigure = new Figure(); + testChildFigure.setBounds(new Rectangle(21, 17, 25, 24)); + testFigure.add(testChildFigure); + testFigure.add(new Figure()); + actualLogger.clear(); + // + // check reset state during remove child figure + testFigure.remove(testChildFigure); + expectedLogger.log("repaint(21, 17, 25, 24)"); + expectedLogger.log("invalidate()"); + actualLogger.assertEquals(expectedLogger); + // + // check reset state during remove all children figures + testFigure.removeAll(); + expectedLogger.log("repaint(0, 0, 0, 0)"); + expectedLogger.log("invalidate()"); + actualLogger.assertEquals(expectedLogger); + // + // check no reset state during remove if not childrens + testFigure.removeAll(); + actualLogger.assertEmpty(); + } + + @Test + public void test_bounds() throws Exception { + // check reset state during setBounds() + testFigure.setBounds(new Rectangle(1, 2, 3, 4)); + expectedLogger.log("erase()"); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(1, 2, 3, 4)"); + actualLogger.assertEquals(expectedLogger); + // + // check no reset state during setBounds() if bounds not change + testFigure.setBounds(new Rectangle(1, 2, 3, 4)); + actualLogger.assertEmpty(); + // + // check no reset state during setSize(int, int) if bounds not change + testFigure.setSize(3, 4); + actualLogger.assertEmpty(); + // + // check reset state during setSize(int, int) + testFigure.setSize(1, 5); + expectedLogger.log("erase()"); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(1, 2, 1, 5)"); + actualLogger.assertEquals(expectedLogger); + // + // check reset state during setSize(Dimension) + testFigure.setSize(new Dimension(11, 12)); + expectedLogger.log("erase()"); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(1, 2, 11, 12)"); + actualLogger.assertEquals(expectedLogger); + // + // check no reset state during setSize(Dimension) if bounds not change + testFigure.setSize(new Dimension(11, 12)); + actualLogger.assertEmpty(); + // + // check no reset state during setLocation(Point) if bounds not change + testFigure.setLocation(new Point(1, 2)); + actualLogger.assertEmpty(); + // + // check reset state during setLocation(Point) + testFigure.setLocation(new Point(3, 7)); + expectedLogger.log("erase()"); + expectedLogger.log("repaint(3, 7, 11, 12)"); + actualLogger.assertEquals(expectedLogger); + // + // check reset state during setLocation(Point) + testFigure.setLocation(new Point()); + expectedLogger.log("erase()"); + expectedLogger.log("repaint(0, 0, 11, 12)"); + actualLogger.assertEquals(expectedLogger); + // + // check no reset state during setLocation(Point) if bounds not change + testFigure.setLocation(new Point()); + actualLogger.assertEmpty(); + } + + @Test + public void test_border() throws Exception { + // check repaint during setBorder() + LineBorder border = new LineBorder(); + testFigure.setBorder(border); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint during setBorder() if border not change + testFigure.setBorder(border); + actualLogger.assertEmpty(); + // + // check repaint during setBorder() + testFigure.setBorder(new LineBorder(7)); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check repaint during setBorder() + testFigure.setBorder(null); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint during setBorder() if border not change + testFigure.setBorder(null); + actualLogger.assertEmpty(); + } + + @Test + public void test_background() throws Exception { + // check repaint during setBackgroundColor() + testFigure.setBackgroundColor(ColorConstants.red); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint during setBackgroundColor() if color not change + testFigure.setBackgroundColor(ColorConstants.red); + actualLogger.assertEmpty(); + // + // check repaint during setBackgroundColor() + testFigure.setBackgroundColor(ColorConstants.green); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check repaint during setBackgroundColor() + testFigure.setBackgroundColor(null); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint during setBackgroundColor() if color not change + testFigure.setBackgroundColor(null); + actualLogger.assertEmpty(); + } + + @Test + public void test_foreground() throws Exception { + // check repaint during setForegroundColor() + testFigure.setForegroundColor(ColorConstants.red); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint during setForegroundColor() if color not change + testFigure.setForegroundColor(ColorConstants.red); + actualLogger.assertEmpty(); + // + // check repaint during setForegroundColor() + testFigure.setForegroundColor(ColorConstants.green); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check repaint during setForegroundColor() + testFigure.setForegroundColor(null); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint during setForegroundColor() if color not change + testFigure.setForegroundColor(null); + actualLogger.assertEmpty(); + } + + @Test + public void test_font() throws Exception { + // check reset state during setFont() + testFigure.setFont(new Font(null, "Courier New", 12, SWT.BOLD)); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check reset state during setFont() + testFigure.setFont(Display.getCurrent().getSystemFont()); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no reset state during setFont() if font not change + testFigure.setFont(Display.getCurrent().getSystemFont()); + actualLogger.assertEmpty(); + // + // check reset state during setFont() + testFigure.setFont(null); + expectedLogger.log("invalidate()"); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no reset state during setFont() if font not change + testFigure.setFont(null); + actualLogger.assertEmpty(); + } + + @Test + public void test_cursor() throws Exception { + // check invoke updateCursor() during setCursor() + testFigure.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_HELP)); + expectedLogger.log("updateCursor()"); + actualLogger.assertEquals(expectedLogger); + // + // check invoke updateCursor() during setCursor() + testFigure.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_CROSS)); + expectedLogger.log("updateCursor()"); + actualLogger.assertEquals(expectedLogger); + // + // check not invoke updateCursor() during setCursor() if cursor not change + testFigure.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_CROSS)); + actualLogger.assertEmpty(); + // + // check invoke updateCursor() during setCursor() + testFigure.setCursor(null); + expectedLogger.log("updateCursor()"); + actualLogger.assertEquals(expectedLogger); + // + // check not invoke updateCursor() during setCursor() if cursor not change + testFigure.setCursor(null); + actualLogger.assertEmpty(); + } + + @Test + public void test_opaque() throws Exception { + // check repaint during setOpaque() + testFigure.setOpaque(true); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint during setOpaque() if opaque not change + testFigure.setOpaque(true); + actualLogger.assertEmpty(); + // + // check repaint during setOpaque() + testFigure.setOpaque(false); + expectedLogger.log("repaint(0, 0, 0, 0)"); + actualLogger.assertEquals(expectedLogger); + // + // check no repaint during setOpaque() if opaque not change + testFigure.setOpaque(false); + actualLogger.assertEmpty(); + } + + @Test + public void test_visible() throws Exception { + // check reset state during setVisible() + testFigure.setVisible(false); + expectedLogger.log("erase()"); + expectedLogger.log("invalidate()"); + actualLogger.assertEquals(expectedLogger); + // + // check no reset state during setVisible() if visible not change + testFigure.setVisible(false); + actualLogger.assertEmpty(); + // + // check reset state during setVisible() + testFigure.setVisible(true); + expectedLogger.log("repaint(0, 0, 0, 0)"); + expectedLogger.log("invalidate()"); + actualLogger.assertEquals(expectedLogger); + // + // check no reset state during setVisible() if visible not change + testFigure.setVisible(true); + actualLogger.assertEmpty(); + } +} \ No newline at end of file diff --git a/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/utils/TestFigure.java b/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/utils/TestFigure.java new file mode 100644 index 000000000..3289baeed --- /dev/null +++ b/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/utils/TestFigure.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2011, 2023 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.draw2d.test.utils; + +import org.eclipse.draw2d.DeferredUpdateManager; +import org.eclipse.draw2d.EventDispatcher; +import org.eclipse.draw2d.Figure; +import org.eclipse.draw2d.IFigure; +import org.eclipse.draw2d.SWTEventDispatcher; +import org.eclipse.draw2d.UpdateManager; + +@SuppressWarnings("nls") +public class TestFigure extends Figure { + private final UpdateManager updateManager; + private final EventDispatcher eventDispatcher; + private final TestLogger logger; + + public TestFigure(TestLogger logger) { + this.logger = logger; + this.updateManager = new DeferredUpdateManager() { + @Override + public void addDirtyRegion(IFigure figure, int x, int y, int w, int h) { + logger.log("repaint(" + x + ", " + y + ", " + w + ", " + h + ")"); + } + }; + this.eventDispatcher = new SWTEventDispatcher() { + @Override + public void updateCursor() { + logger.log("updateCursor()"); + } + }; + } + + @Override + public void invalidate() { + logger.log("invalidate()"); + } + + @Override + public void erase() { + logger.log("erase()"); + } + + @Override + public UpdateManager getUpdateManager() { + return updateManager; + } + + @Override + public EventDispatcher internalGetEventDispatcher() { + return eventDispatcher; + } +} diff --git a/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/utils/TestLogger.java b/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/utils/TestLogger.java new file mode 100644 index 000000000..e9c1f3a88 --- /dev/null +++ b/org.eclipse.draw2d.tests/src/org/eclipse/draw2d/test/utils/TestLogger.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2011, 2023 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.draw2d.test.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; + +/** + * Helper class for logging into test cases. + */ +public class TestLogger extends Assert { + private final List events = new ArrayList<>(); + + /** + * Removes all logged events. + */ + public void clear() { + events.clear(); + } + + /** + * Asserts that this {@link TestLogger} has no events. + */ + public void assertEmpty() { + assertTrue(events.isEmpty()); + } + + /** + * Asserts that this {@link TestLogger} contains same events as in expected one. + */ + public void assertEquals(TestLogger expectedLogger) { + assertEquals(expectedLogger, this); + } + + /** + * Asserts that two objects are equal. If they are not an AssertionFailedError + * is thrown. + */ + public static void assertEquals(TestLogger expectedLogger, TestLogger actualLoogger) { + assertEquals(expectedLogger.events, actualLoogger.events); + expectedLogger.clear(); + actualLoogger.clear(); + } + + /** + * Logs new event. + */ + public void log(String message) { + events.add(message); + } +} \ No newline at end of file diff --git a/org.eclipse.draw2d/src/org/eclipse/draw2d/Figure.java b/org.eclipse.draw2d/src/org/eclipse/draw2d/Figure.java index 46235908b..3d06ea344 100644 --- a/org.eclipse.draw2d/src/org/eclipse/draw2d/Figure.java +++ b/org.eclipse.draw2d/src/org/eclipse/draw2d/Figure.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2023 IBM Corporation 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 @@ -18,6 +18,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Objects; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; @@ -1515,8 +1516,9 @@ public void revalidate() { public void setBackgroundColor(Color bg) { // Set background color to bg unless in high contrast mode. // In that case, get the color from system - if (bgColor != null && bgColor.equals(bg)) + if (Objects.equals(bgColor, bg)) { return; + } Display display = Display.getCurrent(); if (display == null) { display = Display.getDefault(); @@ -1538,9 +1540,11 @@ public void setBackgroundColor(Color bg) { */ @Override public void setBorder(Border border) { - this.border = border; - revalidate(); - repaint(); + if (this.border != border) { + this.border = border; + revalidate(); + repaint(); + } } /** @@ -1713,8 +1717,9 @@ public void setFont(Font f) { public void setForegroundColor(Color fg) { // Set foreground color to fg unless in high contrast mode. // In that case, get the color from system - if (fgColor != null && fgColor.equals(fg)) + if (Objects.equals(fgColor, fg)) { return; + } Display display = Display.getCurrent(); if (display == null) { display = Display.getDefault();