io.github.interacto.jfx.binding.KeysBinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of interacto-javafx Show documentation
Show all versions of interacto-javafx Show documentation
The JavaFX implementation of the Interacto library
The newest version!
/*
* Interacto
* Copyright (C) 2020 Arnaud Blouin
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package io.github.interacto.jfx.binding;
import io.github.interacto.command.Command;
import io.github.interacto.jfx.binding.api.KeyInteractionBinder;
import io.github.interacto.jfx.binding.api.KeyInteractionCmdBinder;
import io.github.interacto.jfx.binding.api.LogLevel;
import io.github.interacto.jfx.instrument.JfxInstrument;
import io.github.interacto.jfx.interaction.help.HelpAnimation;
import io.github.interacto.jfx.interaction.library.KeysData;
import io.github.interacto.jfx.interaction.library.KeysPressed;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
/**
* The base binding builder to create bindings between a keys pressure interaction and a given command.
* @param The type of the command to produce.
* @param The type of the widget to bind.
* @author Arnaud Blouin
*/
abstract class KeysBinder extends Binder implements
KeyInteractionBinder, KeyInteractionCmdBinder {
Collection codes;
final Predicate checkCode;
boolean shift;
boolean ctrl;
boolean alt;
boolean shortcut;
boolean meta;
KeysBinder(final JfxInstrument instrument, final BindingsObserver observer) {
this(null, null, null, Collections.emptyList(),
instrument, false, null, Collections.emptyList(), EnumSet.noneOf(LogLevel.class),
null, false, null, null, null, Collections.emptyList(), null, null, null, observer, false);
}
KeysBinder(final BiConsumer initCmd, final Predicate whenPredicate, final Function cmdProducer,
final List widgets, final JfxInstrument instrument, final boolean async,
final BiConsumer onEnd, final List> additionalWidgets, final EnumSet logLevels,
final HelpAnimation helpAnimation, final boolean withHelp, final DoubleProperty progressProp, final StringProperty msgProp, final Button cancel,
final Collection keyCodes, final BiConsumer hadNoEffectFct, final BiConsumer hadEffectsFct,
final BiConsumer cannotExecFct, final BindingsObserver observer, final boolean consumeEvents) {
super(initCmd, whenPredicate, cmdProducer, widgets, KeysPressed::new, instrument, async, onEnd, additionalWidgets, logLevels, helpAnimation,
withHelp, progressProp, msgProp, cancel, hadNoEffectFct, hadEffectsFct, cannotExecFct, observer, consumeEvents);
setUpKeys(keyCodes);
checkCode = i -> isCodeChecked(i) && (checkConditions == null || checkConditions.test(i));
}
private boolean isCodeChecked(final KeysData data) {
final List keys = data.getKeyCodes();
return (codes.isEmpty() || codes.size() == keys.size() && keys.containsAll(codes)) && isModifiersChecks(data);
}
private boolean isModifiersChecks(final KeysData data) {
return meta == data.isMetaDown()
&& alt == data.isAltDown()
&& (!shortcut || data.isShortcutDown())
&& shift == data.isShiftDown()
&& ctrl == data.isCtrlDown();
}
private void setUpKeys(final Collection keys) {
final var isMac = System.getProperty("os.name").startsWith("Mac");
codes = keys
.stream()
.filter(key -> !key.isModifierKey() && key != KeyCode.SHORTCUT)
.collect(Collectors.toUnmodifiableSet());
shortcut = keys.contains(KeyCode.SHORTCUT);
meta = keys.contains(KeyCode.META) || keys.contains(KeyCode.COMMAND) || (shortcut && isMac);
shift = keys.contains(KeyCode.SHIFT);
ctrl = keys.contains(KeyCode.CONTROL) || (shortcut && !isMac);
alt = keys.contains(KeyCode.ALT);
}
@Override
protected abstract KeysBinder duplicate();
@Override
public KeysBinder with(final KeyCode... keyCodes) {
final KeysBinder dup = duplicate();
dup.setUpKeys(Arrays.asList(keyCodes));
return dup;
}
@Override
public KeysBinder on(final W... widget) {
return (KeysBinder) super.on(widget);
}
@Override
public KeysBinder on(final ObservableList widgets) {
return (KeysBinder) super.on(widgets);
}
@Override
public KeysBinder first(final Consumer initCmdFct) {
return (KeysBinder) super.first(initCmdFct);
}
@Override
public KeysBinder first(final BiConsumer initCmdFct) {
return (KeysBinder) super.first(initCmdFct);
}
@Override
public KeysBinder when(final Predicate checkCmd) {
return (KeysBinder) super.when(checkCmd);
}
@Override
public KeysBinder when(final BooleanSupplier checkCmd) {
return when(i -> checkCmd.getAsBoolean());
}
@Override
public KeysBinder consume() {
return (KeysBinder) super.consume();
}
@Override
public KeysBinder async(final Button cancel, final DoubleProperty progressProp, final StringProperty msgProp) {
return (KeysBinder) super.async(cancel, progressProp, msgProp);
}
@Override
public KeysBinder ifHadEffects(final BiConsumer hadEffectsFct) {
return (KeysBinder) super.ifHadEffects(hadEffectsFct);
}
@Override
public KeysBinder ifHadNoEffect(final BiConsumer noEffectFct) {
return (KeysBinder) super.ifHadNoEffect(noEffectFct);
}
@Override
public KeysBinder end(final Consumer onEnd) {
return (KeysBinder) super.end(onEnd);
}
@Override
public KeysBinder end(final Runnable endFct) {
return (KeysBinder) super.end(endFct);
}
@Override
public KeysBinder end(final BiConsumer onEndFct) {
return (KeysBinder) super.end(onEndFct);
}
@Override
public KeysBinder log(final LogLevel... level) {
return (KeysBinder) super.log(level);
}
@Override
public KeysBinder help(final HelpAnimation animation) {
return (KeysBinder) super.help(animation);
}
@Override
public KeysBinder help(final Pane helpPane) {
return (KeysBinder) super.help(helpPane);
}
@Override
public KeysBinder toProduce(final Supplier cmdCreation) {
return (KeysBinder) super.toProduce(cmdCreation);
}
@Override
public KeysBinder toProduce(final Function cmdCreation) {
return (KeysBinder) super.toProduce(cmdCreation);
}
}