001package conexp.fx.gui.properties; 002 003/* 004 * #%L 005 * Concept Explorer FX 006 * %% 007 * Copyright (C) 2010 - 2023 Francesco Kriegel 008 * %% 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as 011 * published by the Free Software Foundation, either version 3 of the 012 * License, or (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public 020 * License along with this program. If not, see 021 * <http://www.gnu.org/licenses/gpl-3.0.html>. 022 * #L% 023 */ 024 025import conexp.fx.core.collections.IntPair; 026import javafx.beans.binding.ObjectBinding; 027import javafx.beans.value.ChangeListener; 028import javafx.beans.value.ObservableValue; 029 030public class BoundedIntPairProperty extends SimpleIntPairProperty { 031 032 private final ObjectBinding<IntPair> lowerBound; 033 private final ObjectBinding<IntPair> upperBound; 034 035 public BoundedIntPairProperty( 036 IntPair initialValue, 037 ObjectBinding<IntPair> lowerBound, 038 ObjectBinding<IntPair> upperBound) throws RuntimeException { 039 super(initialValue); 040 if (lowerBound.get().x() > upperBound.get().x() || lowerBound.get().y() > upperBound.get().y() 041 || initialValue.x() < lowerBound.get().x() || initialValue.x() > upperBound.get().x() 042 || initialValue.y() < lowerBound.get().y() || initialValue.y() > upperBound.get().y()) 043 throw new RuntimeException("lower bound is not smaller than upper bound, or initial value is not between them!"); 044 this.lowerBound = lowerBound; 045 this.upperBound = upperBound; 046 lowerBound.addListener(new ChangeListener<IntPair>() { 047 048 @Override 049 public void changed(ObservableValue<? extends IntPair> observable, IntPair oldValue, IntPair newValue) { 050 if (getValue().x() < newValue.x() || getValue().y() < newValue.y()) 051 setValue(truncate(getValue())); 052 } 053 }); 054 upperBound.addListener(new ChangeListener<IntPair>() { 055 056 @Override 057 public void changed(ObservableValue<? extends IntPair> observable, IntPair oldValue, IntPair newValue) { 058 if (getValue().x() > newValue.x() || getValue().y() > newValue.y()) 059 setValue(truncate(getValue())); 060 } 061 }); 062 } 063 064 private final IntPair truncate(final IntPair value) { 065 value.setX(Math.min(Math.max(value.x(), lowerBound.get().x()), upperBound.get().x())); 066 value.setY(Math.min(Math.max(value.y(), lowerBound.get().y()), upperBound.get().y())); 067 return value; 068 } 069 070 @Override 071 public void set(int x, int y) { 072 set(truncate(IntPair.valueOf(x, y))); 073 } 074 075 @Override 076 public void set(IntPair v) { 077 super.set(truncate(v)); 078 } 079 080 @Override 081 public void setValue(IntPair v) { 082 set(truncate(v)); 083 } 084}