Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.beans.binding; 027 028import java.lang.ref.WeakReference; 029 030import javafx.beans.InvalidationListener; 031import javafx.beans.Observable; 032import javafx.beans.value.ObservableBooleanValue; 033import javafx.beans.value.ObservableDoubleValue; 034import javafx.beans.value.ObservableFloatValue; 035import javafx.beans.value.ObservableLongValue; 036import javafx.beans.value.ObservableNumberValue; 037import javafx.beans.value.ObservableObjectValue; 038import javafx.beans.value.ObservableStringValue; 039import javafx.beans.value.ObservableValue; 040import javafx.collections.FXCollections; 041import javafx.collections.ObservableList; 042 043import com.sun.javafx.binding.DoubleConstant; 044import com.sun.javafx.binding.FloatConstant; 045import com.sun.javafx.binding.IntegerConstant; 046import com.sun.javafx.binding.Logging; 047import com.sun.javafx.binding.LongConstant; 048import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection; 049 050/** 051 * Starting point for a binding that calculates a ternary expression. 052 * <p> 053 * A ternary expression has the basic form 054 * {@code new When(cond).then(value1).otherwise(value2);}. The expression 055 * {@code cond} needs to be a {@link javafx.beans.value.ObservableBooleanValue}. 056 * Based on the value of {@code cond}, the binding contains the value of 057 * {@code value1} (if {@code cond.getValue() == true}) or {@code value2} (if 058 * {@code cond.getValue() == false}). The values {@code value1} and 059 * {@code value2} have to be of the same type. They can be constant values or 060 * implementations of {@link javafx.beans.value.ObservableValue}. 061 */ 062public class When { 063 private final ObservableBooleanValue condition; 064 065 /** 066 * The constructor of {@code When}. 067 * 068 * @param condition 069 * the condition of the ternary expression 070 */ 071 public When(final ObservableBooleanValue condition) { 072 if (condition == null) { 073 throw new NullPointerException("Condition must be specified."); 074 } 075 this.condition = condition; 076 } 077 078 private static class WhenListener implements InvalidationListener { 079 080 private final ObservableBooleanValue condition; 081 private final ObservableValue<?> thenValue; 082 private final ObservableValue<?> otherwiseValue; 083 private final WeakReference<Binding<?>> ref; 084 085 private WhenListener(Binding<?> binding, ObservableBooleanValue condition, ObservableValue<?> thenValue, ObservableValue<?> otherwiseValue) { 086 this.ref = new WeakReference<Binding<?>>(binding); 087 this.condition = condition; 088 this.thenValue = thenValue; 089 this.otherwiseValue = otherwiseValue; 090 } 091 092 @Override 093 public void invalidated(Observable observable) { 094 final Binding<?> binding = ref.get(); 095 if (binding == null) { 096 condition.removeListener(this); 097 if (thenValue != null) { 098 thenValue.removeListener(this); 099 } 100 if (otherwiseValue != null) { 101 otherwiseValue.removeListener(this); 102 } 103 } else { 104 // short-circuit invalidation. This Binding becomes 105 // only invalid if the condition changes or the 106 // active branch. 107 if (condition.equals(observable) || (binding.isValid() && (condition.get() == observable.equals(thenValue)))) { 108 binding.invalidate(); 109 } 110 } 111 } 112 113 } 114 115 private static NumberBinding createNumberCondition( 116 final ObservableBooleanValue condition, 117 final ObservableNumberValue thenValue, 118 final ObservableNumberValue otherwiseValue) { 119 if ((thenValue instanceof ObservableDoubleValue) || (otherwiseValue instanceof ObservableDoubleValue)) { 120 return new DoubleBinding() { 121 final InvalidationListener observer = new WhenListener(this, condition, thenValue, otherwiseValue); 122 { 123 condition.addListener(observer); 124 thenValue.addListener(observer); 125 otherwiseValue.addListener(observer); 126 } 127 128 @Override 129 public void dispose() { 130 condition.removeListener(observer); 131 thenValue.removeListener(observer); 132 otherwiseValue.removeListener(observer); 133 } 134 135 @Override 136 protected double computeValue() { 137 final boolean conditionValue = condition.get(); 138 Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue); 139 return conditionValue ? thenValue.doubleValue() : otherwiseValue.doubleValue(); 140 } 141 142 @Override 143 @ReturnsUnmodifiableCollection 144 public ObservableList<ObservableValue<?>> getDependencies() { 145 return FXCollections.unmodifiableObservableList( 146 FXCollections.<ObservableValue<?>> observableArrayList(condition, thenValue, otherwiseValue)); 147 } 148 }; 149 } else if ((thenValue instanceof ObservableFloatValue) || (otherwiseValue instanceof ObservableFloatValue)) { 150 return new FloatBinding() { 151 final InvalidationListener observer = new WhenListener(this, condition, thenValue, otherwiseValue); 152 { 153 condition.addListener(observer); 154 thenValue.addListener(observer); 155 otherwiseValue.addListener(observer); 156 } 157 158 @Override 159 public void dispose() { 160 condition.removeListener(observer); 161 thenValue.removeListener(observer); 162 otherwiseValue.removeListener(observer); 163 } 164 165 @Override 166 protected float computeValue() { 167 final boolean conditionValue = condition.get(); 168 Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue); 169 return conditionValue ? thenValue.floatValue() : otherwiseValue.floatValue(); 170 } 171 172 @Override 173 @ReturnsUnmodifiableCollection 174 public ObservableList<ObservableValue<?>> getDependencies() { 175 return FXCollections.unmodifiableObservableList( 176 FXCollections.<ObservableValue<?>> observableArrayList(condition, thenValue, otherwiseValue)); 177 } 178 }; 179 } else if ((thenValue instanceof ObservableLongValue) || (otherwiseValue instanceof ObservableLongValue)) { 180 return new LongBinding() { 181 final InvalidationListener observer = new WhenListener(this, condition, thenValue, otherwiseValue); 182 { 183 condition.addListener(observer); 184 thenValue.addListener(observer); 185 otherwiseValue.addListener(observer); 186 } 187 188 @Override 189 public void dispose() { 190 condition.removeListener(observer); 191 thenValue.removeListener(observer); 192 otherwiseValue.removeListener(observer); 193 } 194 195 @Override 196 protected long computeValue() { 197 final boolean conditionValue = condition.get(); 198 Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue); 199 return conditionValue ? thenValue.longValue() : otherwiseValue.longValue(); 200 } 201 202 @Override 203 @ReturnsUnmodifiableCollection 204 public ObservableList<ObservableValue<?>> getDependencies() { 205 return FXCollections.unmodifiableObservableList( 206 FXCollections.<ObservableValue<?>> observableArrayList(condition, thenValue, otherwiseValue)); 207 } 208 }; 209 } else { 210 return new IntegerBinding() { 211 final InvalidationListener observer = new WhenListener(this, condition, thenValue, otherwiseValue); 212 { 213 condition.addListener(observer); 214 thenValue.addListener(observer); 215 otherwiseValue.addListener(observer); 216 } 217 218 @Override 219 public void dispose() { 220 condition.removeListener(observer); 221 thenValue.removeListener(observer); 222 otherwiseValue.removeListener(observer); 223 } 224 225 @Override 226 protected int computeValue() { 227 final boolean conditionValue = condition.get(); 228 Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue); 229 return conditionValue ? thenValue.intValue(): otherwiseValue.intValue(); 230 } 231 232 @Override 233 @ReturnsUnmodifiableCollection 234 public ObservableList<ObservableValue<?>> getDependencies() { 235 return FXCollections.unmodifiableObservableList( 236 FXCollections.<ObservableValue<?>> observableArrayList(condition, thenValue, otherwiseValue)); 237 } 238 }; 239 } 240 } 241 242 /** 243 * If-then-else expression returning a number. 244 */ 245 public class NumberConditionBuilder { 246 247 private ObservableNumberValue thenValue; 248 249 private NumberConditionBuilder(final ObservableNumberValue thenValue) { 250 this.thenValue = thenValue; 251 } 252 253 /** 254 * Defines the {@link javafx.beans.value.ObservableNumberValue} which 255 * value is returned by the ternary expression if the condition is 256 * {@code false}. 257 * 258 * @param otherwiseValue 259 * the value 260 * @return the complete {@link DoubleBinding} 261 */ 262 public NumberBinding otherwise(ObservableNumberValue otherwiseValue) { 263 if (otherwiseValue == null) { 264 throw new NullPointerException("Value needs to be specified"); 265 } 266 return When.createNumberCondition(condition, thenValue, otherwiseValue); 267 } 268 269 /** 270 * Defines a constant value of the ternary expression, that is returned 271 * if the condition is {@code false}. 272 * 273 * @param otherwiseValue 274 * the value 275 * @return the complete {@link DoubleBinding} 276 */ 277 public DoubleBinding otherwise(double otherwiseValue) { 278 return (DoubleBinding) otherwise(DoubleConstant.valueOf(otherwiseValue)); 279 } 280 281 /** 282 * Defines a constant value of the ternary expression, that is returned 283 * if the condition is {@code false}. 284 * 285 * @param otherwiseValue 286 * the value 287 * @return the complete {@link NumberBinding} 288 */ 289 public NumberBinding otherwise(float otherwiseValue) { 290 return otherwise(FloatConstant.valueOf(otherwiseValue)); 291 } 292 293 /** 294 * Defines a constant value of the ternary expression, that is returned 295 * if the condition is {@code false}. 296 * 297 * @param otherwiseValue 298 * the value 299 * @return the complete {@link NumberBinding} 300 */ 301 public NumberBinding otherwise(long otherwiseValue) { 302 return otherwise(LongConstant.valueOf(otherwiseValue)); 303 } 304 305 /** 306 * Defines a constant value of the ternary expression, that is returned 307 * if the condition is {@code false}. 308 * 309 * @param otherwiseValue 310 * the value 311 * @return the complete {@link NumberBinding} 312 */ 313 public NumberBinding otherwise(int otherwiseValue) { 314 return otherwise(IntegerConstant.valueOf(otherwiseValue)); 315 } 316 } 317 318 /** 319 * Defines the {@link javafx.beans.value.ObservableNumberValue} which value 320 * is returned by the ternary expression if the condition is {@code true}. 321 * 322 * @param thenValue 323 * the value 324 * @return the intermediate result which still requires the otherwise-branch 325 */ 326 public NumberConditionBuilder then(final ObservableNumberValue thenValue) { 327 if (thenValue == null) { 328 throw new NullPointerException("Value needs to be specified"); 329 } 330 return new NumberConditionBuilder(thenValue); 331 } 332 333 /** 334 * Defines a constant value of the ternary expression, that is returned if 335 * the condition is {@code true}. 336 * 337 * @param thenValue 338 * the value 339 * @return the intermediate result which still requires the otherwise-branch 340 */ 341 public NumberConditionBuilder then(double thenValue) { 342 return new NumberConditionBuilder(DoubleConstant.valueOf(thenValue)); 343 } 344 345 /** 346 * Defines a constant value of the ternary expression, that is returned if 347 * the condition is {@code true}. 348 * 349 * @param thenValue 350 * the value 351 * @return the intermediate result which still requires the otherwise-branch 352 */ 353 public NumberConditionBuilder then(float thenValue) { 354 return new NumberConditionBuilder(FloatConstant.valueOf(thenValue)); 355 } 356 357 /** 358 * Defines a constant value of the ternary expression, that is returned if 359 * the condition is {@code true}. 360 * 361 * @param thenValue 362 * the value 363 * @return the intermediate result which still requires the otherwise-branch 364 */ 365 public NumberConditionBuilder then(long thenValue) { 366 return new NumberConditionBuilder(LongConstant.valueOf(thenValue)); 367 } 368 369 /** 370 * Defines a constant value of the ternary expression, that is returned if 371 * the condition is {@code true}. 372 * 373 * @param thenValue 374 * the value 375 * @return the intermediate result which still requires the otherwise-branch 376 */ 377 public NumberConditionBuilder then(int thenValue) { 378 return new NumberConditionBuilder(IntegerConstant.valueOf(thenValue)); 379 } 380 381 /** 382 * If-then-else expression returning Boolean. 383 */ 384 private class BooleanCondition extends BooleanBinding { 385 private final ObservableBooleanValue trueResult; 386 private final boolean trueResultValue; 387 388 private final ObservableBooleanValue falseResult; 389 private final boolean falseResultValue; 390 391 private final InvalidationListener observer; 392 393 private BooleanCondition(final ObservableBooleanValue then, final ObservableBooleanValue otherwise) { 394 this.trueResult = then; 395 this.trueResultValue = false; 396 this.falseResult = otherwise; 397 this.falseResultValue = false; 398 this.observer = new WhenListener(this, condition, then, otherwise); 399 condition.addListener(observer); 400 then.addListener(observer); 401 otherwise.addListener(observer); 402 } 403 404 private BooleanCondition(final boolean then, final ObservableBooleanValue otherwise) { 405 this.trueResult = null; 406 this.trueResultValue = then; 407 this.falseResult = otherwise; 408 this.falseResultValue = false; 409 this.observer = new WhenListener(this, condition, null, otherwise); 410 condition.addListener(observer); 411 otherwise.addListener(observer); 412 } 413 414 private BooleanCondition(final ObservableBooleanValue then, final boolean otherwise) { 415 this.trueResult = then; 416 this.trueResultValue = false; 417 this.falseResult = null; 418 this.falseResultValue = otherwise; 419 this.observer = new WhenListener(this, condition, then, null); 420 condition.addListener(observer); 421 then.addListener(observer); 422 } 423 424 private BooleanCondition(final boolean then, final boolean otherwise) { 425 this.trueResult = null; 426 this.trueResultValue = then; 427 this.falseResult = null; 428 this.falseResultValue = otherwise; 429 this.observer = null; 430 super.bind(condition); 431 } 432 433 @Override 434 protected boolean computeValue() { 435 final boolean conditionValue = condition.get(); 436 Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue); 437 return conditionValue ? (trueResult != null ? trueResult.get() : trueResultValue) 438 : (falseResult != null ? falseResult.get() : falseResultValue); 439 } 440 441 @Override 442 public void dispose() { 443 if (observer == null) { 444 super.unbind(condition); 445 } else { 446 condition.removeListener(observer); 447 if (trueResult != null) { 448 trueResult.removeListener(observer); 449 } 450 if (falseResult != null) { 451 falseResult.removeListener(observer); 452 } 453 } 454 } 455 456 @Override 457 @ReturnsUnmodifiableCollection 458 public ObservableList<ObservableValue<?>> getDependencies() { 459 assert condition != null; 460 final ObservableList<ObservableValue<?>> seq = FXCollections.<ObservableValue<?>> observableArrayList(condition); 461 if (trueResult != null) { 462 seq.add(trueResult); 463 } 464 if (falseResult != null) { 465 seq.add(falseResult); 466 } 467 return FXCollections.unmodifiableObservableList(seq); 468 } 469 } 470 471 /** 472 * An intermediate class needed while assembling the ternary expression. It 473 * should not be used in another context. 474 */ 475 public class BooleanConditionBuilder { 476 477 private ObservableBooleanValue trueResult; 478 private boolean trueResultValue; 479 480 private BooleanConditionBuilder(final ObservableBooleanValue thenValue) { 481 this.trueResult = thenValue; 482 } 483 484 private BooleanConditionBuilder(final boolean thenValue) { 485 this.trueResultValue = thenValue; 486 } 487 488 /** 489 * Defines the {@link javafx.beans.value.ObservableBooleanValue} which 490 * value is returned by the ternary expression if the condition is 491 * {@code false}. 492 * 493 * @param otherwiseValue 494 * the value 495 * @return the complete {@link BooleanBinding} 496 */ 497 public BooleanBinding otherwise(final ObservableBooleanValue otherwiseValue) { 498 if (otherwiseValue == null) { 499 throw new NullPointerException("Value needs to be specified"); 500 } 501 if (trueResult != null) 502 return new BooleanCondition(trueResult, otherwiseValue); 503 else 504 return new BooleanCondition(trueResultValue, otherwiseValue); 505 } 506 507 /** 508 * Defines a constant value of the ternary expression, that is returned 509 * if the condition is {@code false}. 510 * 511 * @param otherwiseValue 512 * the value 513 * @return the complete {@link BooleanBinding} 514 */ 515 public BooleanBinding otherwise(final boolean otherwiseValue) { 516 if (trueResult != null) 517 return new BooleanCondition(trueResult, otherwiseValue); 518 else 519 return new BooleanCondition(trueResultValue, otherwiseValue); 520 } 521 } 522 523 /** 524 * Defines the {@link javafx.beans.value.ObservableBooleanValue} which value 525 * is returned by the ternary expression if the condition is {@code true}. 526 * 527 * @param thenValue 528 * the value 529 * @return the intermediate result which still requires the otherwise-branch 530 */ 531 public BooleanConditionBuilder then(final ObservableBooleanValue thenValue) { 532 if (thenValue == null) { 533 throw new NullPointerException("Value needs to be specified"); 534 } 535 return new BooleanConditionBuilder(thenValue); 536 } 537 538 /** 539 * Defines a constant value of the ternary expression, that is returned if 540 * the condition is {@code true}. 541 * 542 * @param thenValue 543 * the value 544 * @return the intermediate result which still requires the otherwise-branch 545 */ 546 public BooleanConditionBuilder then(final boolean thenValue) { 547 return new BooleanConditionBuilder(thenValue); 548 } 549 550 /** 551 * If-then-else expression returning String. 552 */ 553 private class StringCondition extends StringBinding { 554 555 private final ObservableStringValue trueResult; 556 private final String trueResultValue; 557 558 private final ObservableStringValue falseResult; 559 private final String falseResultValue; 560 561 private final InvalidationListener observer; 562 563 private StringCondition(final ObservableStringValue then, final ObservableStringValue otherwise) { 564 this.trueResult = then; 565 this.trueResultValue = ""; 566 this.falseResult = otherwise; 567 this.falseResultValue = ""; 568 this.observer = new WhenListener(this, condition, then, otherwise); 569 condition.addListener(observer); 570 then.addListener(observer); 571 otherwise.addListener(observer); 572 } 573 574 private StringCondition(final String then, final ObservableStringValue otherwise) { 575 this.trueResult = null; 576 this.trueResultValue = then; 577 this.falseResult = otherwise; 578 this.falseResultValue = ""; 579 this.observer = new WhenListener(this, condition, null, otherwise); 580 condition.addListener(observer); 581 otherwise.addListener(observer); 582 } 583 584 private StringCondition(final ObservableStringValue then, final String otherwise) { 585 this.trueResult = then; 586 this.trueResultValue = ""; 587 this.falseResult = null; 588 this.falseResultValue = otherwise; 589 this.observer = new WhenListener(this, condition, then, null); 590 condition.addListener(observer); 591 then.addListener(observer); 592 } 593 594 private StringCondition(final String then, final String otherwise) { 595 this.trueResult = null; 596 this.trueResultValue = then; 597 this.falseResult = null; 598 this.falseResultValue = otherwise; 599 this.observer = null; 600 super.bind(condition); 601 } 602 603 @Override 604 protected String computeValue() { 605 final boolean conditionValue = condition.get(); 606 Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue); 607 return conditionValue ? (trueResult != null ? trueResult.get() : trueResultValue) 608 : (falseResult != null ? falseResult.get() : falseResultValue); 609 } 610 611 @Override 612 public void dispose() { 613 if (observer == null) { 614 super.unbind(condition); 615 } else { 616 condition.removeListener(observer); 617 if (trueResult != null) { 618 trueResult.removeListener(observer); 619 } 620 if (falseResult != null) { 621 falseResult.removeListener(observer); 622 } 623 } 624 } 625 626 627 @Override 628 @ReturnsUnmodifiableCollection 629 public ObservableList<ObservableValue<?>> getDependencies() { 630 assert condition != null; 631 final ObservableList<ObservableValue<?>> seq = FXCollections.<ObservableValue<?>> observableArrayList(condition); 632 if (trueResult != null) { 633 seq.add(trueResult); 634 } 635 if (falseResult != null) { 636 seq.add(falseResult); 637 } 638 return FXCollections.unmodifiableObservableList(seq); 639 } 640 } 641 642 /** 643 * An intermediate class needed while assembling the ternary expression. It 644 * should not be used in another context. 645 */ 646 public class StringConditionBuilder { 647 648 private ObservableStringValue trueResult; 649 private String trueResultValue; 650 651 private StringConditionBuilder(final ObservableStringValue thenValue) { 652 this.trueResult = thenValue; 653 } 654 655 private StringConditionBuilder(final String thenValue) { 656 this.trueResultValue = thenValue; 657 } 658 659 /** 660 * Defines the {@link javafx.beans.value.ObservableStringValue} which 661 * value is returned by the ternary expression if the condition is 662 * {@code false}. 663 * 664 * @param otherwiseValue 665 * the value 666 * @return the complete {@link StringBinding} 667 */ 668 public StringBinding otherwise(final ObservableStringValue otherwiseValue) { 669 if (trueResult != null) 670 return new StringCondition(trueResult, otherwiseValue); 671 else 672 return new StringCondition(trueResultValue, otherwiseValue); 673 } 674 675 /** 676 * Defines a constant value of the ternary expression, that is returned 677 * if the condition is {@code false}. 678 * 679 * @param otherwiseValue 680 * the value 681 * @return the complete {@link StringBinding} 682 */ 683 public StringBinding otherwise(final String otherwiseValue) { 684 if (trueResult != null) 685 return new StringCondition(trueResult, otherwiseValue); 686 else 687 return new StringCondition(trueResultValue, otherwiseValue); 688 } 689 } 690 691 /** 692 * Defines the {@link javafx.beans.value.ObservableStringValue} which value 693 * is returned by the ternary expression if the condition is {@code true}. 694 * 695 * @param thenValue 696 * the value 697 * @return the intermediate result which still requires the otherwise-branch 698 */ 699 public StringConditionBuilder then(final ObservableStringValue thenValue) { 700 if (thenValue == null) { 701 throw new NullPointerException("Value needs to be specified"); 702 } 703 return new StringConditionBuilder(thenValue); 704 } 705 706 /** 707 * Defines a constant value of the ternary expression, that is returned if 708 * the condition is {@code true}. 709 * 710 * @param thenValue 711 * the value 712 * @return the intermediate result which still requires the otherwise-branch 713 */ 714 public StringConditionBuilder then(final String thenValue) { 715 return new StringConditionBuilder(thenValue); 716 } 717 718 /** 719 * If-then-else expression returning general objects. 720 */ 721 private class ObjectCondition<T> extends ObjectBinding<T> { 722 723 private final ObservableObjectValue<T> trueResult; 724 private final T trueResultValue; 725 726 private final ObservableObjectValue<T> falseResult; 727 private final T falseResultValue; 728 729 private final InvalidationListener observer; 730 731 private ObjectCondition(final ObservableObjectValue<T> then, final ObservableObjectValue<T> otherwise) { 732 this.trueResult = then; 733 this.trueResultValue = null; 734 this.falseResult = otherwise; 735 this.falseResultValue = null; 736 this.observer = new WhenListener(this, condition, then, otherwise); 737 condition.addListener(observer); 738 then.addListener(observer); 739 otherwise.addListener(observer); 740 } 741 742 private ObjectCondition(final T then, final ObservableObjectValue<T> otherwise) { 743 this.trueResult = null; 744 this.trueResultValue = then; 745 this.falseResult = otherwise; 746 this.falseResultValue = null; 747 this.observer = new WhenListener(this, condition, null, otherwise); 748 condition.addListener(observer); 749 otherwise.addListener(observer); 750 } 751 752 private ObjectCondition(final ObservableObjectValue<T> then, final T otherwise) { 753 this.trueResult = then; 754 this.trueResultValue = null; 755 this.falseResult = null; 756 this.falseResultValue = otherwise; 757 this.observer = new WhenListener(this, condition, then, null); 758 condition.addListener(observer); 759 then.addListener(observer); 760 } 761 762 private ObjectCondition(final T then, final T otherwise) { 763 this.trueResult = null; 764 this.trueResultValue = then; 765 this.falseResult = null; 766 this.falseResultValue = otherwise; 767 this.observer = null; 768 super.bind(condition); 769 } 770 771 @Override 772 protected T computeValue() { 773 final boolean conditionValue = condition.get(); 774 Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue); 775 return conditionValue ? (trueResult != null ? trueResult.get() : trueResultValue) 776 : (falseResult != null ? falseResult.get() : falseResultValue); 777 } 778 779 @Override 780 public void dispose() { 781 if (observer == null) { 782 super.unbind(condition); 783 } else { 784 condition.removeListener(observer); 785 if (trueResult != null) { 786 trueResult.removeListener(observer); 787 } 788 if (falseResult != null) { 789 falseResult.removeListener(observer); 790 } 791 } 792 } 793 794 795 @Override 796 @ReturnsUnmodifiableCollection 797 public ObservableList<ObservableValue<?>> getDependencies() { 798 assert condition != null; 799 final ObservableList<ObservableValue<?>> seq = FXCollections.<ObservableValue<?>> observableArrayList(condition); 800 if (trueResult != null) { 801 seq.add(trueResult); 802 } 803 if (falseResult != null) { 804 seq.add(falseResult); 805 } 806 return FXCollections.unmodifiableObservableList(seq); 807 } 808 } 809 810 /** 811 * An intermediate class needed while assembling the ternary expression. It 812 * should not be used in another context. 813 */ 814 public class ObjectConditionBuilder<T> { 815 816 private ObservableObjectValue<T> trueResult; 817 private T trueResultValue; 818 819 private ObjectConditionBuilder(final ObservableObjectValue<T> thenValue) { 820 this.trueResult = thenValue; 821 } 822 823 private ObjectConditionBuilder(final T thenValue) { 824 this.trueResultValue = thenValue; 825 } 826 827 /** 828 * Defines the {@link javafx.beans.value.ObservableObjectValue} which 829 * value is returned by the ternary expression if the condition is 830 * {@code false}. 831 * 832 * @param otherwiseValue 833 * the value 834 * @return the complete {@link ObjectBinding} 835 */ 836 public ObjectBinding<T> otherwise(final ObservableObjectValue<T> otherwiseValue) { 837 if (otherwiseValue == null) { 838 throw new NullPointerException("Value needs to be specified"); 839 } 840 if (trueResult != null) 841 return new ObjectCondition<T>(trueResult, otherwiseValue); 842 else 843 return new ObjectCondition<T>(trueResultValue, otherwiseValue); 844 } 845 846 /** 847 * Defines a constant value of the ternary expression, that is returned 848 * if the condition is {@code false}. 849 * 850 * @param otherwiseValue 851 * the value 852 * @return the complete {@link ObjectBinding} 853 */ 854 public ObjectBinding<T> otherwise(final T otherwiseValue) { 855 if (trueResult != null) 856 return new ObjectCondition<T>(trueResult, otherwiseValue); 857 else 858 return new ObjectCondition<T>(trueResultValue, otherwiseValue); 859 } 860 } 861 862 /** 863 * Defines the {@link javafx.beans.value.ObservableObjectValue} which value 864 * is returned by the ternary expression if the condition is {@code true}. 865 * 866 * @param thenValue 867 * the value 868 * @return the intermediate result which still requires the otherwise-branch 869 */ 870 public <T> ObjectConditionBuilder<T> then(final ObservableObjectValue<T> thenValue) { 871 if (thenValue == null) { 872 throw new NullPointerException("Value needs to be specified"); 873 } 874 return new ObjectConditionBuilder<T>(thenValue); 875 } 876 877 /** 878 * Defines a constant value of the ternary expression, that is returned if 879 * the condition is {@code true}. 880 * 881 * @param thenValue 882 * the value 883 * @return the intermediate result which still requires the otherwise-branch 884 */ 885 public <T> ObjectConditionBuilder<T> then(final T thenValue) { 886 return new ObjectConditionBuilder<T>(thenValue); 887 } 888 889}