Skip to content

Commit 834e33b

Browse files
committed
fix #1090 Add ToggleButton and ToggleButtonGroup componentsAdd ToggleButton and ToggleButtonGroup components
1 parent e4bd998 commit 834e33b

File tree

14 files changed

+739
-68
lines changed

14 files changed

+739
-68
lines changed

domino-ui-shared/src/main/java/org/dominokit/domino/ui/style/BooleanCssClass.java

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.dominokit.domino.ui.style;
1818

1919
import elemental2.dom.Element;
20+
import java.util.function.Supplier;
2021
import org.dominokit.domino.ui.IsElement;
2122

2223
/**
@@ -30,7 +31,7 @@
3031
public class BooleanCssClass implements CssClass {
3132

3233
private CssClass cssClass;
33-
private boolean addRemove;
34+
private Supplier<Boolean> addRemove;
3435

3536
/**
3637
* Creates an instance with a specified {@link CssClass} and a condition flag.
@@ -43,6 +44,17 @@ public class BooleanCssClass implements CssClass {
4344
public static BooleanCssClass of(CssClass cssClass, boolean addRemove) {
4445
return new BooleanCssClass(cssClass, addRemove);
4546
}
47+
/**
48+
* Creates an instance with a specified {@link CssClass} and a condition flag.
49+
*
50+
* @param cssClass The CSS class to be conditionally applied or removed.
51+
* @param addRemove Condition flag to determine if the class should be applied (true) or removed
52+
* (false).
53+
* @return A new instance of {@code BooleanCssClass}.
54+
*/
55+
public static BooleanCssClass of(CssClass cssClass, Supplier<Boolean> addRemove) {
56+
return new BooleanCssClass(cssClass, addRemove);
57+
}
4658

4759
/**
4860
* Creates an instance with a specified {@link HasCssClass} and a condition flag. This method
@@ -57,6 +69,19 @@ public static BooleanCssClass of(HasCssClass cssClass, boolean addRemove) {
5769
return new BooleanCssClass(cssClass.getCssClass(), addRemove);
5870
}
5971

72+
/**
73+
* Creates an instance with a specified {@link HasCssClass} and a condition flag. This method
74+
* extracts the {@link CssClass} from the provided {@link HasCssClass}.
75+
*
76+
* @param cssClass The object implementing {@link HasCssClass} whose CSS class will be extracted.
77+
* @param addRemove Condition flag to determine if the class should be applied (true) or removed
78+
* (false).
79+
* @return A new instance of {@code BooleanCssClass}.
80+
*/
81+
public static BooleanCssClass of(HasCssClass cssClass, Supplier<Boolean> addRemove) {
82+
return new BooleanCssClass(cssClass.getCssClass(), addRemove);
83+
}
84+
6085
/**
6186
* Creates an instance with a specified CSS class string and a condition flag.
6287
*
@@ -70,6 +95,19 @@ public static BooleanCssClass of(String cssClass, boolean addRemove) {
7095
return new BooleanCssClass(() -> cssClass, addRemove);
7196
}
7297

98+
/**
99+
* Creates an instance with a specified CSS class string and a condition flag.
100+
*
101+
* @param cssClass The string representation of the CSS class to be conditionally applied or
102+
* removed.
103+
* @param addRemove Condition flag to determine if the class should be applied (true) or removed
104+
* (false).
105+
* @return A new instance of {@code BooleanCssClass}.
106+
*/
107+
public static BooleanCssClass of(String cssClass, Supplier<Boolean> addRemove) {
108+
return new BooleanCssClass(() -> cssClass, addRemove);
109+
}
110+
73111
/**
74112
* Creates an instance with a specified {@link CssClass} and sets the condition flag to true
75113
* (class will be applied by default).
@@ -112,6 +150,17 @@ public static BooleanCssClass of(String cssClass) {
112150
* (false).
113151
*/
114152
public BooleanCssClass(CssClass cssClass, boolean addRemove) {
153+
this(cssClass, () -> addRemove);
154+
}
155+
156+
/**
157+
* Initializes the {@code BooleanCssClass} with a provided {@link CssClass} and a condition flag.
158+
*
159+
* @param cssClass The CSS class to be managed.
160+
* @param addRemove Condition flag to determine if the class should be applied (true) or removed
161+
* (false).
162+
*/
163+
public BooleanCssClass(CssClass cssClass, Supplier<Boolean> addRemove) {
115164
this.cssClass = cssClass;
116165
this.addRemove = addRemove;
117166
}
@@ -133,7 +182,7 @@ public BooleanCssClass(CssClass cssClass) {
133182
*/
134183
@Override
135184
public void apply(Element element) {
136-
apply(element, addRemove);
185+
apply(element, addRemove.get());
137186
}
138187

139188
/**

domino-ui/src/main/java/org/dominokit/domino/ui/button/BaseButton.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ protected BaseButton() {
6262
.appendChild(bodyElement = div().addCss(dui_button_body));
6363
textElement = LazyChild.of(span().addCss(dui_button_text), bodyElement);
6464
init((B) this);
65+
prepare();
6566
}
6667

68+
protected void prepare() {}
69+
6770
/**
6871
* createButtonElement.
6972
*

domino-ui/src/main/java/org/dominokit/domino/ui/button/ButtonStyles.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@ public interface ButtonStyles {
4040

4141
/** Constant <code>dui_top_scroller</code> */
4242
CssClass dui_top_scroller = () -> "dui-top-scroller";
43+
44+
CssClass dui_toggle_button = () -> "dui-toggle-button";
4345
}
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
/*
2+
* Copyright © 2019 Dominokit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.dominokit.domino.ui.button;
17+
18+
import static java.util.Objects.isNull;
19+
import static java.util.Objects.nonNull;
20+
import static org.dominokit.domino.ui.button.ButtonStyles.dui_toggle_button;
21+
import static org.dominokit.domino.ui.style.ColorsCss.dui_bg_primary;
22+
import static org.dominokit.domino.ui.style.ColorsCss.dui_fg_white;
23+
import static org.dominokit.domino.ui.utils.Domino.button;
24+
25+
import elemental2.dom.HTMLButtonElement;
26+
import java.util.HashSet;
27+
import java.util.Set;
28+
import org.dominokit.domino.ui.elements.ButtonElement;
29+
import org.dominokit.domino.ui.icons.Icon;
30+
import org.dominokit.domino.ui.style.BooleanCssClass;
31+
import org.dominokit.domino.ui.style.CompositeCssClass;
32+
import org.dominokit.domino.ui.style.CssClass;
33+
import org.dominokit.domino.ui.utils.HasChangeListeners;
34+
import org.dominokit.domino.ui.utils.IsToggleGroup;
35+
import org.dominokit.domino.ui.utils.IsToggleItem;
36+
37+
public class ToggleButton extends BaseButton<HTMLButtonElement, ToggleButton>
38+
implements HasChangeListeners<ToggleButton, Boolean>, IsToggleItem<ToggleButton> {
39+
40+
private CssClass toggleCssClass = CompositeCssClass.of(dui_bg_primary, dui_fg_white);
41+
private CssClass untoggledCssClass = CssClass.NONE;
42+
private boolean changeListenersPaused;
43+
private Set<ChangeListener<? super Boolean>> changeListeners;
44+
private boolean state = false;
45+
private IsToggleGroup<ToggleButton> group;
46+
private String key;
47+
48+
/** Creates an empty button */
49+
public ToggleButton() {}
50+
51+
/**
52+
* create a Button with a text.
53+
*
54+
* @param text String, the button text
55+
*/
56+
public ToggleButton(String text) {
57+
super(text);
58+
}
59+
60+
/**
61+
* Creates a Button with an icon
62+
*
63+
* @param icon The button icon
64+
*/
65+
public ToggleButton(Icon<?> icon) {
66+
super(icon);
67+
}
68+
69+
/**
70+
* Creates button with text and icon
71+
*
72+
* @param text The button text
73+
* @param icon The button icon
74+
*/
75+
public ToggleButton(String text, Icon<?> icon) {
76+
super(text, icon);
77+
}
78+
79+
/**
80+
* Factory method to create empty button
81+
*
82+
* @return new Button instance
83+
*/
84+
public static ToggleButton create() {
85+
return new ToggleButton();
86+
}
87+
88+
/**
89+
* Factory method to create a button with a text.
90+
*
91+
* @param text The button text
92+
* @return new Button instance
93+
*/
94+
public static ToggleButton create(String text) {
95+
return new ToggleButton(text);
96+
}
97+
98+
/**
99+
* Factory method to create a button with an icon.
100+
*
101+
* @param icon the button icon
102+
* @return new Button instance
103+
*/
104+
public static ToggleButton create(Icon<?> icon) {
105+
return new ToggleButton(icon);
106+
}
107+
108+
/**
109+
* Factory method to create button with a text and icon.
110+
*
111+
* @param text a {@link java.lang.String} object
112+
* @param icon the button icon
113+
* @return new Button instance
114+
*/
115+
public static ToggleButton create(String text, Icon<?> icon) {
116+
return new ToggleButton(text, icon);
117+
}
118+
119+
/**
120+
* Factory method to create button with a text and icon.
121+
*
122+
* @param icon the button icon
123+
* @param text a {@link java.lang.String} object
124+
* @return new Button instance
125+
*/
126+
public static ToggleButton create(Icon<?> icon, String text) {
127+
return new ToggleButton(text, icon);
128+
}
129+
130+
@Override
131+
protected void prepare() {
132+
addCss(dui_toggle_button);
133+
this.addClickListener(
134+
evt -> {
135+
boolean state = isToggled();
136+
if (nonNull(group) && (!group.isMultipleToggle() && state)) {
137+
return;
138+
}
139+
setToggle(!isToggled());
140+
});
141+
}
142+
143+
public ToggleButton setToggle(boolean toggle, boolean silent) {
144+
withPauseChangeListenersToggle(silent, toggleButton -> updateToggle(toggle, true));
145+
return this;
146+
}
147+
148+
ToggleButton updateToggle(boolean toggle, boolean notifyParent) {
149+
boolean oldState = this.state;
150+
this.state = toggle;
151+
if (toggle) {
152+
untoggledCssClass = CompositeCssClass.of(this);
153+
}
154+
addCss(BooleanCssClass.of(toggleCssClass, toggle));
155+
if (!toggle) {
156+
addCss(untoggledCssClass);
157+
}
158+
if (this.state != oldState) {
159+
withPauseChangeListenersToggle(
160+
isChangeListenersPaused(), toggleButton -> triggerChangeListeners(oldState, this.state));
161+
if (nonNull(group) && notifyParent) {
162+
this.group.onItemToggle(this);
163+
}
164+
}
165+
return this;
166+
}
167+
168+
public boolean isToggled() {
169+
return this.state;
170+
}
171+
172+
/** @dominokit-site-ignore {@inheritDoc} */
173+
@Override
174+
protected ButtonElement createButtonElement() {
175+
return button();
176+
}
177+
178+
@Override
179+
public ToggleButton pauseChangeListeners() {
180+
this.changeListenersPaused = true;
181+
return this;
182+
}
183+
184+
@Override
185+
public ToggleButton resumeChangeListeners() {
186+
this.changeListenersPaused = false;
187+
return this;
188+
}
189+
190+
@Override
191+
public ToggleButton togglePauseChangeListeners(boolean toggle) {
192+
this.changeListenersPaused = toggle;
193+
return this;
194+
}
195+
196+
@Override
197+
public Set<ChangeListener<? super Boolean>> getChangeListeners() {
198+
if (isNull(this.changeListeners)) {
199+
this.changeListeners = new HashSet<>();
200+
}
201+
return this.changeListeners;
202+
}
203+
204+
@Override
205+
public boolean isChangeListenersPaused() {
206+
return this.changeListenersPaused;
207+
}
208+
209+
@Override
210+
public ToggleButton triggerChangeListeners(Boolean oldValue, Boolean newValue) {
211+
if (!isChangeListenersPaused()) {
212+
getChangeListeners()
213+
.forEach(changeListener -> changeListener.onValueChanged(oldValue, newValue));
214+
}
215+
return this;
216+
}
217+
218+
@Override
219+
public ToggleButton bindTo(IsToggleGroup<ToggleButton> toggleGroup) {
220+
this.group = toggleGroup;
221+
return this;
222+
}
223+
224+
@Override
225+
public ToggleButton toggle() {
226+
return setToggle(!isToggled());
227+
}
228+
229+
@Override
230+
public ToggleButton toggle(boolean silent) {
231+
return setToggle(!isToggled(), silent);
232+
}
233+
234+
@Override
235+
public ToggleButton setToggle(boolean value) {
236+
return setToggle(value, isChangeListenersPaused());
237+
}
238+
239+
@Override
240+
public ToggleButton setKey(String key) {
241+
this.key = key;
242+
return this;
243+
}
244+
245+
@Override
246+
public String getKey() {
247+
return this.key;
248+
}
249+
250+
public CssClass getToggleCssClass() {
251+
return toggleCssClass;
252+
}
253+
254+
public ToggleButton setToggleCssClass(CssClass toggleCssClass) {
255+
if (isNull(toggleCssClass)) {
256+
this.toggleCssClass = CssClass.NONE;
257+
} else {
258+
this.toggleCssClass = toggleCssClass;
259+
}
260+
return this;
261+
}
262+
263+
public boolean getValue() {
264+
return state;
265+
}
266+
}

0 commit comments

Comments
 (0)