From 9240bf0953b5038d4ecc19812f5a32cef3af3211 Mon Sep 17 00:00:00 2001 From: Matt Weaver Date: Fri, 10 Jan 2014 15:57:52 -0700 Subject: [PATCH 1/6] looking good --- .../widgets/buttons/SquareButtonExample.java | 115 +++++++-------- .../buttons/SquareButtonGroupIntegTest.java | 28 ++++ .../swt/widgets/buttons/SquareButton.java | 133 ++++++++++++++---- .../widgets/buttons/SquareButtonGroup.java | 68 +++++++++ .../buttons/SquareButtonGroupTest.java | 64 +++++++++ 5 files changed, 321 insertions(+), 87 deletions(-) create mode 100644 src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java create mode 100644 src/main/java/com/readytalk/swt/widgets/buttons/SquareButtonGroup.java create mode 100644 src/test/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupTest.java diff --git a/src/examples/java/com/readytalk/examples/swt/widgets/buttons/SquareButtonExample.java b/src/examples/java/com/readytalk/examples/swt/widgets/buttons/SquareButtonExample.java index 1cc82de..a004ae6 100644 --- a/src/examples/java/com/readytalk/examples/swt/widgets/buttons/SquareButtonExample.java +++ b/src/examples/java/com/readytalk/examples/swt/widgets/buttons/SquareButtonExample.java @@ -4,6 +4,7 @@ import com.readytalk.examples.swt.SwtBlingExample; import com.readytalk.swt.util.ColorFactory; import com.readytalk.swt.widgets.buttons.SquareButton; +import com.readytalk.swt.widgets.buttons.SquareButtonGroup; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -134,7 +135,7 @@ public void run(Display display, final Shell shell) { .setHoverColors(BUTTON_HOVER_COLOR_GROUP) .setDefaultColors(BUTTON_DEFAULT_COLOR_GROUP) .setClickedColors(FUN_BUTTON_CLICK_COLOR_GROUP) - .setDefaultMouseClickAndReturnKeyHandler(new SquareButton.DefaultButtonClickHandler() { + .setDefaultMouseClickAndReturnKeyHandler(new SquareButton.ButtonClickHandler() { @Override public void clicked() { openTestDialog(shell); @@ -168,7 +169,7 @@ public void clicked() { .setDefaultColors(FUN_BUTTON_DEFAULT_COLOR_GROUP) .setSelectedColors(FUN_BUTTON_SELECTED_COLOR_GROUP) .setClickedColors(FUN_BUTTON_CLICK_COLOR_GROUP) - .setDefaultMouseClickAndReturnKeyHandler(new SquareButton.DefaultButtonClickHandler() { + .setDefaultMouseClickAndReturnKeyHandler(new SquareButton.ButtonClickHandler() { @Override public void clicked() { openTestDialog(shell); @@ -190,7 +191,7 @@ public void clicked() { .setDefaultColors(MORE_FUN_BUTTON_DEFAULT_COLOR_GROUP) .setClickedColors(FUN_BUTTON_CLICK_COLOR_GROUP) .setSelectedColors(MORE_FUN_BUTTON_SELECTED_COLOR_GROUP) - .setDefaultMouseClickAndReturnKeyHandler(new SquareButton.DefaultButtonClickHandler() { + .setDefaultMouseClickAndReturnKeyHandler(new SquareButton.ButtonClickHandler() { @Override public void clicked() { openTestDialog(shell); @@ -260,59 +261,61 @@ public void clicked() { formData.right = new FormAttachment(90); bigButtonTwo.setLayoutData(formData); - bigButtonOne.addMouseListener(new MouseAdapter() { - @Override - public void mouseUp(MouseEvent e) { - if(bigButtonTwo.isToggled()) { - bigButtonTwo.setToggled(false); - } - } - }); - - bigButtonOne.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent keyEvent) { - switch (keyEvent.character) { - case ' ': - case '\r': - case '\n': - if(bigButtonTwo.isToggled()) { - bigButtonTwo.setToggled(false); - } - break; - default: - break; - } - } - }); - - bigButtonTwo.addMouseListener(new MouseAdapter() { - @Override - public void mouseUp(MouseEvent e) { - if(bigButtonOne.isToggled()) { - bigButtonOne.setToggled(false); - } - } - }); - - bigButtonTwo.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent keyEvent) { - switch (keyEvent.character) { - case ' ': - case '\r': - case '\n': - if(bigButtonOne.isToggled()) { - bigButtonOne.setToggled(false); - } - break; - default: - break; - } - } - }); - - bigButtonOne.setToggled(true); + SquareButtonGroup group = new SquareButtonGroup(bigButtonOne, bigButtonTwo); + +// bigButtonOne.addMouseListener(new MouseAdapter() { +// @Override +// public void mouseUp(MouseEvent e) { +// if(bigButtonTwo.isToggled()) { +// bigButtonTwo.setToggled(false); +// } +// } +// }); +// +// bigButtonOne.addKeyListener(new KeyAdapter() { +// @Override +// public void keyPressed(KeyEvent keyEvent) { +// switch (keyEvent.character) { +// case ' ': +// case '\r': +// case '\n': +// if(bigButtonTwo.isToggled()) { +// bigButtonTwo.setToggled(false); +// } +// break; +// default: +// break; +// } +// } +// }); +// +// bigButtonTwo.addMouseListener(new MouseAdapter() { +// @Override +// public void mouseUp(MouseEvent e) { +// if(bigButtonOne.isToggled()) { +// bigButtonOne.setToggled(false); +// } +// } +// }); +// +// bigButtonTwo.addKeyListener(new KeyAdapter() { +// @Override +// public void keyPressed(KeyEvent keyEvent) { +// switch (keyEvent.character) { +// case ' ': +// case '\r': +// case '\n': +// if(bigButtonOne.isToggled()) { +// bigButtonOne.setToggled(false); +// } +// break; +// default: +// break; +// } +// } +// }); + +// bigButtonOne.setToggled(true); // shell.setSize(1200, 200); topGroup.pack(); diff --git a/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java b/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java new file mode 100644 index 0000000..8c380d5 --- /dev/null +++ b/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java @@ -0,0 +1,28 @@ +package com.readytalk.swt.widgets.buttons; + +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Before; + +public class SquareButtonGroupIntegTest { + + private Display display; + private Shell shell; + + private SquareButton toggleOne, toggleTwo, toggleThree, nonToggled; + + @Before + public void setUp() { + display = Display.getDefault(); + shell = new Shell(display); + + shell.open(); + } + + @After + public void tearDown() { + shell.close(); + display.dispose(); + } +} diff --git a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java index 04d79e0..8f68e0f 100644 --- a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java +++ b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java @@ -29,6 +29,8 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.TypedListener; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Logger; /** @@ -264,15 +266,7 @@ public void handleEvent(Event e) { } void doButtonClickedColor() { - if(toggleable) { - if(toggled) { - SquareButton.this.setNormalColor(); - toggled = false; - } else { - SquareButton.this.setClickedColor(); - toggled = true; - } - } else { + if(!toggleable){ SquareButton.this.setClickedColor(); } } @@ -473,7 +467,7 @@ protected void paintControl(PaintEvent paintEvent) { if (roundedCorners) { gc.drawRoundRectangle(buttonRectangle.x + (bw - 1), buttonRectangle.y + (bw - 1), buttonRectangle.width - bw, buttonRectangle.height - 4, arcWidth, arcHeight); } else { - gc.drawRectangle(buttonRectangle.x, buttonRectangle.y, buttonRectangle.width - bw, buttonRectangle.height - 1); + gc.drawRectangle(buttonRectangle.x, buttonRectangle.y, buttonRectangle.width - bw, buttonRectangle.height - 3); } // dotted line selection border around the text, if any @@ -716,7 +710,7 @@ protected ContentOriginSet getContentsOrigin(Rectangle rectangle) { * |_________________________| */ imageY = (verticallyCenterContents) ? rectangle.height/2 - heightOfContents/2 : innerMarginHeight; - textY = imageY + imageSize.y + imagePadding; + textY = imageY + imageSize.y + ((image != null) ? imagePadding : 0); // anchor width based on the image only if the image is wider, probably not likely but possible if(imageWider) { @@ -1290,7 +1284,98 @@ protected Point getTextOrigin() { } } - public static interface DefaultButtonClickHandler { + private List strategies = new ArrayList(); + private DefaultButtonClickHandler strategyHandler; + + private DefaultButtonClickHandler defaultToggleClickHandler = new DefaultButtonClickHandler(this) { + @Override + void clicked() { + if(!disableDefaultToggleClickHandler && isToggleable()) { + if(toggled) { + setNormalColor(); + toggled = false; + } else { + setClickedColor(); + toggled = true; + } + } + } + }; + + private boolean disableDefaultToggleClickHandler; + + void setDisableDefaultToggleClickHandler(boolean disableDefaultToggleClickHandler) { + this.disableDefaultToggleClickHandler = disableDefaultToggleClickHandler; + } + + public void addStrategy(ButtonClickStrategy strategy) { + strategies.add(strategy); + addStrategyHandler(); + } + + public void clearStrategies() { + strategies.clear(); + } + + public void removeStrategy(ButtonClickStrategy strategy) { + strategies.remove(strategy); + } + + void addStrategyHandler() { + if(strategyHandler == null) { + strategyHandler = new DefaultButtonClickHandler(this) { + @Override + void clicked() { + for(ButtonClickStrategy strategy : strategies) { + boolean validStrategy = strategy.isStrategyValid(); + if(validStrategy) { + strategy.executeStrategy(); + } + } + } + }; + } + } + + static interface ButtonClickStrategy { + + /** + * Do whatever button logic you want to do here. + * + * @return whether or not this button click should be allowed + */ + boolean isStrategyValid(); + void executeStrategy(); + } + + public static abstract class DefaultButtonClickHandler { + + public DefaultButtonClickHandler(final SquareButton button) { + button.addMouseListener(new MouseAdapter() { + @Override + public void mouseUp(MouseEvent e) { + clicked(); + } + }); + button.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent keyEvent) { + switch (keyEvent.character) { + case ' ': + case '\r': + case '\n': + clicked(); + break; + default: + break; + } + } + }); + } + abstract void clicked(); + } + + public static interface ButtonClickHandler { void clicked(); } @@ -1320,7 +1405,7 @@ public static class SquareButtonBuilder { protected SquareButtonColorGroup inactiveColors; protected String accessibilityName; protected boolean toggleable; - protected DefaultButtonClickHandler defaultMouseClickAndReturnKeyHandler; + protected ButtonClickHandler defaultMouseClickAndReturnKeyHandler; public SquareButtonBuilder setParent(Composite parent) { this.parent = parent; @@ -1423,7 +1508,7 @@ public SquareButtonBuilder setToggleable(boolean toggleable) { return this; } - public SquareButtonBuilder setDefaultMouseClickAndReturnKeyHandler(DefaultButtonClickHandler defaultMouseClickAndReturnKeyHandler) { + public SquareButtonBuilder setDefaultMouseClickAndReturnKeyHandler(ButtonClickHandler defaultMouseClickAndReturnKeyHandler) { this.defaultMouseClickAndReturnKeyHandler = defaultMouseClickAndReturnKeyHandler; return this; } @@ -1511,26 +1596,12 @@ public SquareButton build() throws IllegalArgumentException { } if(defaultMouseClickAndReturnKeyHandler != null) { - button.addMouseListener(new MouseAdapter() { + DefaultButtonClickHandler handler = new DefaultButtonClickHandler(button) { @Override - public void mouseUp(MouseEvent e) { + void clicked() { defaultMouseClickAndReturnKeyHandler.clicked(); } - }); - button.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent keyEvent) { - switch (keyEvent.character) { - case ' ': - case '\r': - case '\n': - defaultMouseClickAndReturnKeyHandler.clicked(); - break; - default: - break; - } - } - }); + }; } return button; diff --git a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButtonGroup.java b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButtonGroup.java new file mode 100644 index 0000000..1f76bee --- /dev/null +++ b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButtonGroup.java @@ -0,0 +1,68 @@ +package com.readytalk.swt.widgets.buttons; + +import java.util.ArrayList; +import java.util.List; + +/** + * Currently this is primarily used for square buttons used like a toggle. It does nothing for layouts, but acts as a point of control. + */ +public class SquareButtonGroup { + private List buttons; + private List toggleableButtons; + private SquareButton currentlyToggledButton; + + public SquareButtonGroup(SquareButton ... buttons) { + this.buttons = new ArrayList(); + this.toggleableButtons = new ArrayList(); + for(SquareButton button : buttons) { + addButton(button); + } + } + + /** + * Internal method, will return true if the button is toggleable. + * + * @param button + * @return + */ + boolean addButton(SquareButton button) { + boolean toggleable = false; + buttons.add(button); + if(button.isToggleable()) { + button.setDisableDefaultToggleClickHandler(true); + toggleableButtons.add(button); + injectStrategy(button); + if(currentlyToggledButton == null) { + currentlyToggledButton = button; + button.setToggled(true); + } + toggleable = true; + } + return toggleable; + } + + void injectStrategy(final SquareButton button) { + button.addStrategy(new SquareButton.ButtonClickStrategy() { + @Override + public boolean isStrategyValid() { + boolean test = (currentlyToggledButton != button); + return test; + } + + @Override + public void executeStrategy() { + button.setToggled(true); + currentlyToggledButton = button; + for(SquareButton otherButton : toggleableButtons) { + if(currentlyToggledButton == otherButton) { + continue; + } + if(otherButton.isToggleable()) { + otherButton.setToggled(false); + } + } + } + }); + } + +} diff --git a/src/test/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupTest.java b/src/test/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupTest.java new file mode 100644 index 0000000..da91240 --- /dev/null +++ b/src/test/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupTest.java @@ -0,0 +1,64 @@ +package com.readytalk.swt.widgets.buttons; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; + +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; + +/** + */ +public class SquareButtonGroupTest { + + @Mock + private SquareButton topButton; + + @Mock + private SquareButton middleButton; + + @Mock + private SquareButton bottomButton; + + private FauxToggleable topToggleable, middleToggleable, bottomToggleable; + + @Before + public void setup() { + + topToggleable = new FauxToggleable(); + middleToggleable = new FauxToggleable(); + bottomToggleable = new FauxToggleable(); + +// doNothing().when(topButton).setToggleable(anyBoolean()).thenCallRealMethod(); + when(topButton.isToggleable()).thenCallRealMethod(); + + } + + @Test + public void testMembership() { + + } + + + + private class FauxToggleable { + boolean toggleable, toggled; + + private boolean isToggleable() { + return toggleable; + } + + private void setToggleable(boolean toggleable) { + this.toggleable = toggleable; + } + + private boolean isToggled() { + return toggled; + } + + private void setToggled(boolean toggled) { + this.toggled = toggled; + } + } +} From 4c90a57d38a23fb3625fe94b2728f7155a5f8aac Mon Sep 17 00:00:00 2001 From: Matt Weaver Date: Tue, 21 Jan 2014 16:02:39 -0700 Subject: [PATCH 2/6] there we go --- .../widgets/buttons/SquareButtonExample.java | 57 +------------------ .../buttons/SquareButtonGroupIntegTest.java | 49 ++++++++++++++++ 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/src/examples/java/com/readytalk/examples/swt/widgets/buttons/SquareButtonExample.java b/src/examples/java/com/readytalk/examples/swt/widgets/buttons/SquareButtonExample.java index a004ae6..ce3ff7e 100644 --- a/src/examples/java/com/readytalk/examples/swt/widgets/buttons/SquareButtonExample.java +++ b/src/examples/java/com/readytalk/examples/swt/widgets/buttons/SquareButtonExample.java @@ -261,62 +261,7 @@ public void clicked() { formData.right = new FormAttachment(90); bigButtonTwo.setLayoutData(formData); - SquareButtonGroup group = new SquareButtonGroup(bigButtonOne, bigButtonTwo); - -// bigButtonOne.addMouseListener(new MouseAdapter() { -// @Override -// public void mouseUp(MouseEvent e) { -// if(bigButtonTwo.isToggled()) { -// bigButtonTwo.setToggled(false); -// } -// } -// }); -// -// bigButtonOne.addKeyListener(new KeyAdapter() { -// @Override -// public void keyPressed(KeyEvent keyEvent) { -// switch (keyEvent.character) { -// case ' ': -// case '\r': -// case '\n': -// if(bigButtonTwo.isToggled()) { -// bigButtonTwo.setToggled(false); -// } -// break; -// default: -// break; -// } -// } -// }); -// -// bigButtonTwo.addMouseListener(new MouseAdapter() { -// @Override -// public void mouseUp(MouseEvent e) { -// if(bigButtonOne.isToggled()) { -// bigButtonOne.setToggled(false); -// } -// } -// }); -// -// bigButtonTwo.addKeyListener(new KeyAdapter() { -// @Override -// public void keyPressed(KeyEvent keyEvent) { -// switch (keyEvent.character) { -// case ' ': -// case '\r': -// case '\n': -// if(bigButtonOne.isToggled()) { -// bigButtonOne.setToggled(false); -// } -// break; -// default: -// break; -// } -// } -// }); - -// bigButtonOne.setToggled(true); -// shell.setSize(1200, 200); + new SquareButtonGroup(bigButtonOne, bigButtonTwo); topGroup.pack(); leftComposite.pack(); diff --git a/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java b/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java index 8c380d5..a972ae2 100644 --- a/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java +++ b/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java @@ -1,9 +1,14 @@ package com.readytalk.swt.widgets.buttons; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Shell; import org.junit.After; +import org.junit.Assert; import org.junit.Before; +import org.junit.Test; public class SquareButtonGroupIntegTest { @@ -16,10 +21,54 @@ public class SquareButtonGroupIntegTest { public void setUp() { display = Display.getDefault(); shell = new Shell(display); + shell.setLayout(new FillLayout()); + + + SquareButton.SquareButtonBuilder builder = new SquareButton.SquareButtonBuilder(); + builder.setParent(shell) + .setText("one") + .setToggleable(true); + toggleOne = builder.build(); + + builder = new SquareButton.SquareButtonBuilder(); + builder.setParent(shell) + .setText("two") + .setToggleable(true); + toggleTwo = builder.build(); + + builder = new SquareButton.SquareButtonBuilder(); + builder.setParent(shell) + .setText("three") + .setToggleable(true); + toggleThree = builder.build(); + + builder = new SquareButton.SquareButtonBuilder(); + builder.setParent(shell) + .setText("non toggle"); + nonToggled = builder.build(); + + new SquareButtonGroup(toggleOne, toggleTwo, toggleThree, nonToggled); shell.open(); } + @Test + public void testDefaultToggle() { + Assert.assertTrue(toggleOne.isToggled()); + Assert.assertFalse(toggleTwo.isToggled()); + Assert.assertFalse(toggleThree.isToggled()); + Assert.assertFalse(nonToggled.isToggled()); + } + + @Test + public void testBasicToggle() { + toggleTwo.notifyListeners(SWT.MouseDown, new Event()); + Assert.assertFalse(toggleOne.isToggled()); + Assert.assertTrue(toggleTwo.isToggled()); + Assert.assertFalse(toggleThree.isToggled()); + Assert.assertFalse(nonToggled.isToggled()); + } + @After public void tearDown() { shell.close(); From 6e753177d974bc31d1a6160223b8e74cb00936f3 Mon Sep 17 00:00:00 2001 From: Matt Weaver Date: Tue, 21 Jan 2014 16:11:30 -0700 Subject: [PATCH 3/6] oops, forgot to delete this --- .../buttons/SquareButtonGroupTest.java | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 src/test/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupTest.java diff --git a/src/test/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupTest.java b/src/test/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupTest.java deleted file mode 100644 index da91240..0000000 --- a/src/test/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.readytalk.swt.widgets.buttons; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; - -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.doNothing; - -/** - */ -public class SquareButtonGroupTest { - - @Mock - private SquareButton topButton; - - @Mock - private SquareButton middleButton; - - @Mock - private SquareButton bottomButton; - - private FauxToggleable topToggleable, middleToggleable, bottomToggleable; - - @Before - public void setup() { - - topToggleable = new FauxToggleable(); - middleToggleable = new FauxToggleable(); - bottomToggleable = new FauxToggleable(); - -// doNothing().when(topButton).setToggleable(anyBoolean()).thenCallRealMethod(); - when(topButton.isToggleable()).thenCallRealMethod(); - - } - - @Test - public void testMembership() { - - } - - - - private class FauxToggleable { - boolean toggleable, toggled; - - private boolean isToggleable() { - return toggleable; - } - - private void setToggleable(boolean toggleable) { - this.toggleable = toggleable; - } - - private boolean isToggled() { - return toggled; - } - - private void setToggled(boolean toggled) { - this.toggled = toggled; - } - } -} From 544e254dcad2848ba4b2885fe4220bed7227b270 Mon Sep 17 00:00:00 2001 From: Matt Weaver Date: Tue, 21 Jan 2014 16:35:52 -0700 Subject: [PATCH 4/6] fixed the tests... --- .../buttons/SquareButtonGroupIntegTest.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java b/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java index a972ae2..7267f73 100644 --- a/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java +++ b/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java @@ -1,6 +1,7 @@ package com.readytalk.swt.widgets.buttons; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; @@ -62,7 +63,22 @@ public void testDefaultToggle() { @Test public void testBasicToggle() { - toggleTwo.notifyListeners(SWT.MouseDown, new Event()); + toggleTwo.notifyListeners(SWT.MouseUp, new Event()); + Assert.assertFalse(toggleOne.isToggled()); + Assert.assertTrue(toggleTwo.isToggled()); + Assert.assertFalse(toggleThree.isToggled()); + Assert.assertFalse(nonToggled.isToggled()); + } + + @Test + public void testDoubleToggle() { + toggleTwo.notifyListeners(SWT.MouseUp, new Event()); + Assert.assertFalse(toggleOne.isToggled()); + Assert.assertTrue(toggleTwo.isToggled()); + Assert.assertFalse(toggleThree.isToggled()); + Assert.assertFalse(nonToggled.isToggled()); + + toggleTwo.notifyListeners(SWT.MouseUp, new Event()); Assert.assertFalse(toggleOne.isToggled()); Assert.assertTrue(toggleTwo.isToggled()); Assert.assertFalse(toggleThree.isToggled()); From 99de81c60d6d01df3864bad3f641472bb36d6824 Mon Sep 17 00:00:00 2001 From: Matt Weaver Date: Tue, 21 Jan 2014 16:47:18 -0700 Subject: [PATCH 5/6] SO ANGRY --- .../java/com/readytalk/swt/widgets/buttons/SquareButton.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java index 8f68e0f..bbc59af 100644 --- a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java +++ b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java @@ -1596,7 +1596,7 @@ public SquareButton build() throws IllegalArgumentException { } if(defaultMouseClickAndReturnKeyHandler != null) { - DefaultButtonClickHandler handler = new DefaultButtonClickHandler(button) { + new DefaultButtonClickHandler(button) { @Override void clicked() { defaultMouseClickAndReturnKeyHandler.clicked(); From dccdabad0a200811aa9139a3ffe142f7af1b9ddf Mon Sep 17 00:00:00 2001 From: Matt Weaver Date: Tue, 21 Jan 2014 17:32:19 -0700 Subject: [PATCH 6/6] added a way to force selected easily and integ tests for it, as well as some jovadocs --- .../buttons/SquareButtonGroupIntegTest.java | 13 ++- .../swt/widgets/buttons/SquareButton.java | 31 +++++-- .../widgets/buttons/SquareButtonGroup.java | 81 ++++++++++++++----- 3 files changed, 96 insertions(+), 29 deletions(-) diff --git a/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java b/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java index 7267f73..06ea2bf 100644 --- a/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java +++ b/src/integTest/java/com/readytalk/swt/widgets/buttons/SquareButtonGroupIntegTest.java @@ -18,6 +18,8 @@ public class SquareButtonGroupIntegTest { private SquareButton toggleOne, toggleTwo, toggleThree, nonToggled; + private SquareButtonGroup group; + @Before public void setUp() { display = Display.getDefault(); @@ -48,7 +50,7 @@ public void setUp() { .setText("non toggle"); nonToggled = builder.build(); - new SquareButtonGroup(toggleOne, toggleTwo, toggleThree, nonToggled); + group = new SquareButtonGroup(toggleOne, toggleTwo, toggleThree, nonToggled); shell.open(); } @@ -85,6 +87,15 @@ public void testDoubleToggle() { Assert.assertFalse(nonToggled.isToggled()); } + @Test + public void testForcedSelection() { + group.setCurrentlyToggledButton(toggleThree); + Assert.assertFalse(toggleOne.isToggled()); + Assert.assertFalse(toggleTwo.isToggled()); + Assert.assertTrue(toggleThree.isToggled()); + Assert.assertFalse(nonToggled.isToggled()); + } + @After public void tearDown() { shell.close(); diff --git a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java index bbc59af..2782df1 100644 --- a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java +++ b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButton.java @@ -1221,6 +1221,12 @@ public boolean isToggled() { return toggled; } + /** + * Setting toggle states explicitly may work against what you might be trying to do, if using a SquareButtonGroup. If not + * it will work as expected. + * + * @param toggled + */ public void setToggled(boolean toggled) { this.toggled = toggled; if(toggleable) { @@ -1308,6 +1314,12 @@ void setDisableDefaultToggleClickHandler(boolean disableDefaultToggleClickHandle this.disableDefaultToggleClickHandler = disableDefaultToggleClickHandler; } + /** + * Strategies are more likely to be used in SquareButtonGroup implementations, but you can feel free to add + * any and they will all be evaluated and applied individually. + * + * @param strategy + */ public void addStrategy(ButtonClickStrategy strategy) { strategies.add(strategy); addStrategyHandler(); @@ -1321,17 +1333,21 @@ public void removeStrategy(ButtonClickStrategy strategy) { strategies.remove(strategy); } + void executeStrategies() { + for(ButtonClickStrategy strategy : strategies) { + boolean validStrategy = strategy.isStrategyValid(); + if(validStrategy) { + strategy.executeStrategy(); + } + } + } + void addStrategyHandler() { if(strategyHandler == null) { strategyHandler = new DefaultButtonClickHandler(this) { @Override void clicked() { - for(ButtonClickStrategy strategy : strategies) { - boolean validStrategy = strategy.isStrategyValid(); - if(validStrategy) { - strategy.executeStrategy(); - } - } + executeStrategies(); } }; } @@ -1348,6 +1364,9 @@ static interface ButtonClickStrategy { void executeStrategy(); } + /** + * Use this instead of using an explicit mouse adapter, unless you have other reason to. + */ public static abstract class DefaultButtonClickHandler { public DefaultButtonClickHandler(final SquareButton button) { diff --git a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButtonGroup.java b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButtonGroup.java index 1f76bee..34864e9 100644 --- a/src/main/java/com/readytalk/swt/widgets/buttons/SquareButtonGroup.java +++ b/src/main/java/com/readytalk/swt/widgets/buttons/SquareButtonGroup.java @@ -11,6 +11,12 @@ public class SquareButtonGroup { private List toggleableButtons; private SquareButton currentlyToggledButton; + /** + * You can add any SquareButtons to a SquareButtonGroup. If they are toggleable then the group will + * link them together so they can act like radio buttons. The first button in the list will be set on by default. + * + * @param buttons + */ public SquareButtonGroup(SquareButton ... buttons) { this.buttons = new ArrayList(); this.toggleableButtons = new ArrayList(); @@ -19,6 +25,30 @@ public SquareButtonGroup(SquareButton ... buttons) { } } + /** + * Call this to explicitly pick which button is toggled in the group. + * + * @param button + */ + public void setCurrentlyToggledButton(SquareButton button) { + setCurrentlyToggledButton(button, true); + } + + private void setCurrentlyToggledButton(SquareButton button, boolean simulateClick) { + if(simulateClick) { + if(isStrategyValid(button)) { + executeStrategy(button); + } + } else { + currentlyToggledButton = button; + button.setToggled(true); + } + } + + public SquareButton getCurrentlyToggledButton() { + return currentlyToggledButton; + } + /** * Internal method, will return true if the button is toggleable. * @@ -33,8 +63,7 @@ boolean addButton(SquareButton button) { toggleableButtons.add(button); injectStrategy(button); if(currentlyToggledButton == null) { - currentlyToggledButton = button; - button.setToggled(true); + setCurrentlyToggledButton(button, false); } toggleable = true; } @@ -42,27 +71,35 @@ boolean addButton(SquareButton button) { } void injectStrategy(final SquareButton button) { - button.addStrategy(new SquareButton.ButtonClickStrategy() { - @Override - public boolean isStrategyValid() { - boolean test = (currentlyToggledButton != button); - return test; - } + button.addStrategy(new SquareButton.ButtonClickStrategy() { + @Override + public boolean isStrategyValid() { + return SquareButtonGroup.this.isStrategyValid(button); + } + + @Override + public void executeStrategy() { + SquareButtonGroup.this.executeStrategy(button); + } + }); + } - @Override - public void executeStrategy() { - button.setToggled(true); - currentlyToggledButton = button; - for(SquareButton otherButton : toggleableButtons) { - if(currentlyToggledButton == otherButton) { - continue; - } - if(otherButton.isToggleable()) { - otherButton.setToggled(false); - } - } - } - }); + boolean isStrategyValid(SquareButton button) { + return (currentlyToggledButton != button); + } + + + void executeStrategy(SquareButton button) { + button.setToggled(true); + currentlyToggledButton = button; + for(SquareButton otherButton : toggleableButtons) { + if(currentlyToggledButton == otherButton) { + continue; + } + if(otherButton.isToggleable()) { + otherButton.setToggled(false); + } + } } }