Skip to content

Commit

Permalink
Initial infrastructure for keyboard focus and events.
Browse files Browse the repository at this point in the history
  • Loading branch information
io7m committed Apr 1, 2024
1 parent 13f5475 commit d22e426
Show file tree
Hide file tree
Showing 40 changed files with 389 additions and 433 deletions.
24 changes: 23 additions & 1 deletion com.io7m.jsycamore.api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@
<includePluginDependencies>true</includePluginDependencies>
<mainClass>com.io7m.jsycamore.generation.SyKeycodeGenerationMain</mainClass>
<arguments>
<argument>${project.build.directory}/generated-sources/annotations/com/io7m/jsycamore/api/keyboard/SyKeyCode.java</argument>
<argument>
${project.build.directory}/generated-sources/keycodes/com/io7m/jsycamore/api/keyboard/SyKeyCode.java
</argument>
</arguments>
</configuration>
</execution>
Expand All @@ -92,6 +94,26 @@
</dependency>
</dependencies>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>
${project.build.directory}/generated-sources/keycodes
</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.io7m.jorchard.core.JOTreeNodeReadableType;
import com.io7m.jsycamore.api.active.SyActiveReadableType;
import com.io7m.jsycamore.api.bounded.SyBoundedReadableType;
import com.io7m.jsycamore.api.keyboard.SyKeyboardFocusableReadableType;
import com.io7m.jsycamore.api.mouse.SyMouseFocusAcceptingReadableType;
import com.io7m.jsycamore.api.screens.SyScreenType;
import com.io7m.jsycamore.api.spaces.SySpaceParentRelativeType;
Expand All @@ -40,6 +41,7 @@
public interface SyComponentReadableType
extends SyActiveReadableType,
SyVisibleReadableType,
SyKeyboardFocusableReadableType,
SyMouseFocusAcceptingReadableType,
SyBoundedReadableType<SySpaceParentRelativeType>,
SyThemeableReadableType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.io7m.jsycamore.api.active.SyActiveType;
import com.io7m.jsycamore.api.bounded.SyBoundedType;
import com.io7m.jsycamore.api.events.SyEventReceiverType;
import com.io7m.jsycamore.api.keyboard.SyKeyboardFocusableType;
import com.io7m.jsycamore.api.layout.SyLayoutContextType;
import com.io7m.jsycamore.api.mouse.SyMouseFocusAcceptingType;
import com.io7m.jsycamore.api.spaces.SySpaceParentRelativeType;
Expand All @@ -45,6 +46,7 @@ public interface SyComponentType
SyVisibleType,
SyActiveType,
SyEventReceiverType,
SyKeyboardFocusableType,
SyMouseFocusAcceptingType,
SyBoundedType<SySpaceParentRelativeType>,
SyThemeableType
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright © 2023 Mark Raynsford <code@io7m.com> https://www.io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/


package com.io7m.jsycamore.api.keyboard;

/**
* A specification of how keyboard focus may traverse a component.
*/

public enum SyKeyboardFocusBehavior
{
/**
* The component can directly receive focus, and will pass focus to its
* children if the focus traversal is continued.
*/

RECEIVES_FOCUS_AND_CONTINUES_TRAVERSAL,

/**
* The component can directly receive focus, but will not pass focus to its
* children if the focus traversal is continued.
*/

RECEIVES_FOCUS_AND_STOPS_TRAVERSAL,

/**
* The component cannot directly receive focus, but will pass focus to its
* children if the focus traversal is continued.
*/

IGNORES_FOCUS_AND_CONTINUES_TRAVERSAL,

/**
* The component cannot directly receive focus, and will not pass focus to its
* children if the focus traversal is continued.
*/

IGNORES_FOCUS_AND_STOPS_TRAVERSAL;

/**
* @return {@code true} if this behavior implies that a component will
* receive focus
*/

public boolean receivesFocus()
{
return switch (this) {
case RECEIVES_FOCUS_AND_CONTINUES_TRAVERSAL -> true;
case RECEIVES_FOCUS_AND_STOPS_TRAVERSAL -> true;
case IGNORES_FOCUS_AND_CONTINUES_TRAVERSAL -> false;
case IGNORES_FOCUS_AND_STOPS_TRAVERSAL -> false;
};
}

/**
* @return {@code true} if this behavior implies that a component will pass
* focus to its children
*/

public boolean continuesFocusTraversal()
{
return switch (this) {
case RECEIVES_FOCUS_AND_CONTINUES_TRAVERSAL -> true;
case RECEIVES_FOCUS_AND_STOPS_TRAVERSAL -> false;
case IGNORES_FOCUS_AND_CONTINUES_TRAVERSAL -> true;
case IGNORES_FOCUS_AND_STOPS_TRAVERSAL -> false;
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright © 2023 Mark Raynsford <code@io7m.com> https://www.io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/


package com.io7m.jsycamore.api.keyboard;

import com.io7m.jattribute.core.AttributeReadableType;

/**
* The readable interface to objects that involve keyboard focus.
*/

public interface SyKeyboardFocusableReadableType
{
/**
* @return The keyboard focus behavior
*/

AttributeReadableType<SyKeyboardFocusBehavior> keyboardFocusBehavior();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright © 2023 Mark Raynsford <code@io7m.com> https://www.io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/


package com.io7m.jsycamore.api.keyboard;

import com.io7m.jattribute.core.AttributeType;

/**
* The interface to objects that involve keyboard focus.
*/

public interface SyKeyboardFocusableType
extends SyKeyboardFocusableReadableType
{
@Override
AttributeType<SyKeyboardFocusBehavior> keyboardFocusBehavior();
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.io7m.jsycamore.api.components.SyComponentType;
import com.io7m.jsycamore.api.events.SyEventConsumed;
import com.io7m.jsycamore.api.events.SyEventInputType;
import com.io7m.jsycamore.api.keyboard.SyKeyboardFocusBehavior;
import com.io7m.jsycamore.api.mouse.SyMouseEventOnNoLongerOver;
import com.io7m.jsycamore.api.mouse.SyMouseEventOnOver;
import com.io7m.jsycamore.api.screens.SyScreenType;
Expand Down Expand Up @@ -71,6 +72,7 @@ public abstract class SyComponentAbstract implements SyComponentType
private volatile boolean mouseOver;
private volatile boolean mouseAcceptQuery = true;
private Optional<SyWindowType> window;
private final AttributeType<SyKeyboardFocusBehavior> focusBehavior;

/**
* A convenient abstract implementation of a component, to make it easier to
Expand All @@ -81,12 +83,14 @@ public abstract class SyComponentAbstract implements SyComponentType
* @param inNodeDetachCheck A function that returns {@code true} if this
* component should be allowed to be detached from
* the parent component
* @param inFocusBehavior The default focus behavior
*/

protected SyComponentAbstract(
final SyScreenType inScreen,
final List<SyThemeClassNameType> inThemeClassesExtra,
final BooleanSupplier inNodeDetachCheck)
final BooleanSupplier inNodeDetachCheck,
final SyKeyboardFocusBehavior inFocusBehavior)
{
this.screen =
Objects.requireNonNull(inScreen, "inScreen");
Expand All @@ -112,14 +116,17 @@ protected SyComponentAbstract(
JOTreeNode.createWithDetachCheck(this, inNodeDetachCheck);
this.window =
Optional.empty();
this.focusBehavior =
attributes.create(inFocusBehavior);
}

@ConvenienceConstructor
protected SyComponentAbstract(
final SyScreenType inScreen,
final List<SyThemeClassNameType> inThemeClassesExtra)
final List<SyThemeClassNameType> inThemeClassesExtra,
final SyKeyboardFocusBehavior inFocusBehavior)
{
this(inScreen, inThemeClassesExtra, () -> true);
this(inScreen, inThemeClassesExtra, () -> true, inFocusBehavior);
}

@SuppressWarnings("unchecked")
Expand All @@ -143,6 +150,12 @@ private static boolean isOverlappingComponent(
return false;
}

@Override
public final AttributeType<SyKeyboardFocusBehavior> keyboardFocusBehavior()
{
return this.focusBehavior;
}

@Override
public final SyScreenType screen()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.io7m.jsycamore.api.components.SyImageViewType;
import com.io7m.jsycamore.api.events.SyEventConsumed;
import com.io7m.jsycamore.api.events.SyEventInputType;
import com.io7m.jsycamore.api.keyboard.SyKeyboardFocusBehavior;
import com.io7m.jsycamore.api.screens.SyScreenType;
import com.io7m.jsycamore.api.themes.SyThemeClassNameType;

Expand Down Expand Up @@ -50,7 +51,11 @@ public SyImageView(
final SyScreenType inScreen,
final List<SyThemeClassNameType> inThemeClassesExtra)
{
super(inScreen, inThemeClassesExtra);
super(
inScreen,
inThemeClassesExtra,
SyKeyboardFocusBehavior.IGNORES_FOCUS_AND_STOPS_TRAVERSAL
);
final var attributes = SyComponentAttributes.get();
this.imageURI = attributes.create(Optional.empty());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.io7m.jsycamore.api.components.SyContainerType;
import com.io7m.jsycamore.api.events.SyEventConsumed;
import com.io7m.jsycamore.api.events.SyEventInputType;
import com.io7m.jsycamore.api.keyboard.SyKeyboardFocusBehavior;
import com.io7m.jsycamore.api.screens.SyScreenType;
import com.io7m.jsycamore.api.themes.SyThemeClassNameType;

Expand All @@ -38,7 +39,12 @@ protected SyLayoutAbstract(
final SyScreenType inScreen,
final List<SyThemeClassNameType> inThemeClassesExtra)
{
super(inScreen, inThemeClassesExtra);
super(
inScreen,
inThemeClassesExtra,
() -> true,
SyKeyboardFocusBehavior.IGNORES_FOCUS_AND_CONTINUES_TRAVERSAL
);
this.setMouseQueryAccepting(false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.io7m.jsycamore.api.components.SyConstraints;
import com.io7m.jsycamore.api.events.SyEventConsumed;
import com.io7m.jsycamore.api.events.SyEventInputType;
import com.io7m.jsycamore.api.keyboard.SyKeyboardFocusBehavior;
import com.io7m.jsycamore.api.layout.SyLayoutContextType;
import com.io7m.jsycamore.api.menus.SyMenuItemAtomType;
import com.io7m.jsycamore.api.menus.SyMenuItemSeparatorType;
Expand Down Expand Up @@ -77,7 +78,11 @@ public SyMenu(
final SyScreenType screen,
final List<SyThemeClassNameType> themeClasses)
{
super(screen, themeClasses);
super(
screen,
themeClasses,
SyKeyboardFocusBehavior.IGNORES_FOCUS_AND_STOPS_TRAVERSAL
);

this.items = List.of();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.io7m.jsycamore.api.events.SyEventConsumed;
import com.io7m.jsycamore.api.events.SyEventInputType;
import com.io7m.jsycamore.api.keyboard.SyKeyEventType;
import com.io7m.jsycamore.api.keyboard.SyKeyboardFocusBehavior;
import com.io7m.jsycamore.api.layout.SyLayoutContextType;
import com.io7m.jsycamore.api.menus.SyMenuBarItemType;
import com.io7m.jsycamore.api.menus.SyMenuBarType;
Expand Down Expand Up @@ -78,7 +79,11 @@ public SyMenuBar(
final SyScreenType screen,
final List<SyThemeClassNameType> themeClasses)
{
super(screen, themeClasses);
super(
screen,
themeClasses,
SyKeyboardFocusBehavior.IGNORES_FOCUS_AND_STOPS_TRAVERSAL
);

this.menuBarItems = List.of();
this.menuSelected = null;
Expand Down Expand Up @@ -212,7 +217,11 @@ private static final class SyMenuBarItem
final SyMenuType inMenu,
final SyText inName)
{
super(inMenuBar.screen(), List.of());
super(
inMenuBar.screen(),
List.of(),
SyKeyboardFocusBehavior.IGNORES_FOCUS_AND_STOPS_TRAVERSAL
);

this.menuBar =
Objects.requireNonNull(inMenuBar, "inMenuBar");
Expand Down

0 comments on commit d22e426

Please sign in to comment.