Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions packages/app-android/app/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,25 @@ TextView.no-underline {
margin-right: var(--safeAreaInsetRight, 0) !important;
}

/* Adwaita floating action button (the main Assemble / Run / … button). */
/* Adwaita floating action button (the main Assemble / Run / … button): a
`Gtk.Button` carrying `Adw.ButtonContent`. `height: auto` overrides the fixed 38
`.adw-button` sets — the FAB sizes to its icon+label plus this padding, as the old
hand-built StackLayout did. */
.adw-fab {
background-color: #3584e4;
border-radius: 9999;
padding: 10 18 10 18;
margin: 16;
height: auto;
android-elevation: 0;
}

.adw-fab-label {
/* `Adw.ButtonContent`'s label defaults to Adwaita's dark button text and only turns
white for `.suggested-action` or dark mode (`.adw-button-content-label` /
`.ns-dark .adw-button-content-label` in the theme) — the FAB's accent background
needs it white unconditionally, like the old `.adw-fab-label` did. */
.adw-fab .adw-button-content-label {
color: #ffffff;
font-weight: 700;
margin-left: 8;
vertical-align: middle;
}

.ns-dark .adw-fab {
Expand Down
6 changes: 6 additions & 0 deletions packages/app-android/app/gtk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// XML door for `Gtk.*` widgets — `<gtk:Button xmlns:gtk="~/gtk" />` resolves through
// this barrel, the same way `~/widgets/index` resolves `<w:SourceView>`. A plain XML
// app (no Angular/Vue) has no `registerElement` global to register widgets through,
// so `@gjsify/adwaita-nativescript`'s own convention is an app-local barrel per
// namespace that re-exports the package's `/gtk` (and `/adw`) subpath.
export * from "@gjsify/adwaita-nativescript/gtk";
52 changes: 25 additions & 27 deletions packages/app-android/app/widgets/adw-main-button.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Label, StackLayout } from "@nativescript/core";
import { localize as _ } from "@nativescript/localize";
import { Gtk, attachRowPressFeedback } from "@gjsify/adwaita-nativescript";
import { Adw, Gtk, GTK_BUTTON_CLICKED } from "@gjsify/adwaita-nativescript";
import {
systemRunSymbolic,
mediaPlaybackStartSymbolic,
Expand Down Expand Up @@ -31,39 +30,38 @@ const MODES: Partial<Record<MainButtonState, MainButtonMode>> = {
};

/**
* Adwaita-styled floating action button: a pill holding a white symbolic icon +
* label on the accent background. It is stateless w.r.t. the simulator — the shell
* computes the MainButtonState and calls setState(); a tap invokes
* onAction(currentAction). Replaces the Material `MainButton`/`Fab` widget.
* Adwaita-styled floating action button: a `Gtk.Button` holding an `Adw.ButtonContent`
* (white symbolic icon + label) on the accent `.adw-fab` pill background. It is
* stateless w.r.t. the simulator — the shell computes the MainButtonState and calls
* setState(); a tap invokes onAction(currentAction). Replaces the Material
* `MainButton`/`Fab` widget.
*/
export class AdwMainButton extends StackLayout {
export class AdwMainButton extends Gtk.Button {
/** Invoked on tap with the current mode's action. Wired by the shell. */
public onAction: ((action: MainButtonAction) => void) | null = null;

private readonly _icon: Gtk.Image;
private readonly _label: Label;
// Not `_content`: `Gtk.Button` already declares a private field of that name
// (its own single-child slot), and TypeScript refuses two private declarations
// of the same name across a base/subclass pair.
private readonly _buttonContent: Adw.ButtonContent;
private _state: MainButtonState = MainButtonState.ASSEMBLE;

constructor() {
super();
this.orientation = "horizontal";
this.className = "adw-fab";
// `add_css_class`, not a `className` assignment: the button's constructor already
// put `adw-button` there, and a raw overwrite would drop it — worse, it would come
// back on the next `styleClasses`/`add_css_class` call, which rebuilds `className`
// from the tracked list and has no idea `adw-fab` was ever there.
this.add_css_class("adw-fab");

const icon = new Gtk.Image();
icon.iconColor = "#ffffff"; // pinned white on the accent pill, both schemes
icon.verticalAlignment = "middle";
this._icon = icon;
this.addChild(icon);
// Icon+label IS `Adw.ButtonContent`. `Gtk.Button` already wires the press-darken
// (`attachRowPressFeedback`, in its own constructor) — the only app-specific parts
// left are the MainButtonState machine below and the `.adw-fab` pill styling.
const buttonContent = new Adw.ButtonContent({ iconColor: "#ffffff" }); // pinned white on the accent pill, both schemes
this._buttonContent = buttonContent;
this.child = buttonContent;

const label = new Label();
label.className = "adw-fab-label";
label.verticalAlignment = "middle";
this._label = label;
this.addChild(label);

// Adwaita buttons darken on press; NS only auto-applies that to `Button`.
attachRowPressFeedback(this);
this.addEventListener("tap", () => {
this.addEventListener(GTK_BUTTON_CLICKED, () => {
const mode = MODES[this._state];
if (mode && this.onAction) this.onAction(mode.action);
});
Expand All @@ -83,7 +81,7 @@ export class AdwMainButton extends StackLayout {
return;
}
this.visibility = "visible";
this._icon.iconName = mode.icon;
this._label.text = _(mode.label);
this._buttonContent.iconName = mode.icon;
this._buttonContent.label = _(mode.label);
}
}
28 changes: 14 additions & 14 deletions packages/app-android/app/widgets/game-console/gamepad.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Button } from "@nativescript/core";
import { GridLayout, Builder } from "@nativescript/core";
import { Gtk } from "@gjsify/adwaita-nativescript";
import type { GamepadKey, GamepadEventMap, GamepadWidget } from "@learn6502/common-ui";
import { getGamepadKeyCode, getGamepadKeyChar } from "@learn6502/common-ui";
import { EventDispatcher } from "@learn6502/core";
Expand All @@ -12,12 +12,12 @@ export class Gamepad extends GridLayout implements GamepadWidget {
readonly events = new EventDispatcher<GamepadEventMap>();

// Button references
private buttonUp: Button | null = null;
private buttonDown: Button | null = null;
private buttonLeft: Button | null = null;
private buttonRight: Button | null = null;
private buttonA: Button | null = null;
private buttonB: Button | null = null;
private buttonUp: Gtk.Button | null = null;
private buttonDown: Gtk.Button | null = null;
private buttonLeft: Gtk.Button | null = null;
private buttonRight: Gtk.Button | null = null;
private buttonA: Gtk.Button | null = null;
private buttonB: Gtk.Button | null = null;

constructor() {
super();
Expand All @@ -30,12 +30,12 @@ export class Gamepad extends GridLayout implements GamepadWidget {

this.addChild(componentView);

this.buttonUp = componentView.getViewById<Button>("buttonUp");
this.buttonDown = componentView.getViewById<Button>("buttonDown");
this.buttonLeft = componentView.getViewById<Button>("buttonLeft");
this.buttonRight = componentView.getViewById<Button>("buttonRight");
this.buttonA = componentView.getViewById<Button>("buttonA");
this.buttonB = componentView.getViewById<Button>("buttonB");
this.buttonUp = componentView.getViewById<Gtk.Button>("buttonUp");
this.buttonDown = componentView.getViewById<Gtk.Button>("buttonDown");
this.buttonLeft = componentView.getViewById<Gtk.Button>("buttonLeft");
this.buttonRight = componentView.getViewById<Gtk.Button>("buttonRight");
this.buttonA = componentView.getViewById<Gtk.Button>("buttonA");
this.buttonB = componentView.getViewById<Gtk.Button>("buttonB");
this.buttonUp?.on("tap", () => this.press("Up"));
this.buttonDown?.on("tap", () => this.press("Down"));
this.buttonLeft?.on("tap", () => this.press("Left"));
Expand All @@ -59,7 +59,7 @@ export class Gamepad extends GridLayout implements GamepadWidget {
}

private applyPressEffectToButton(keyName: GamepadKey): void {
let button: Button | null = null;
let button: Gtk.Button | null = null;

switch (keyName) {
case "Up":
Expand Down
14 changes: 7 additions & 7 deletions packages/app-android/app/widgets/game-console/gamepad.xml
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
<GridLayout xmlns="http://schemas.nativescript.org/tns.xsd" columns="auto,auto" rows="auto" loaded="onLoaded">
<GridLayout xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:gtk="~/gtk" columns="auto,auto" rows="auto" loaded="onLoaded">
<!-- D-Pad Column -->
<GridLayout rows="auto, auto, auto" columns="auto, auto, auto" col="0" row="0" verticalAlignment="bottom" horizontalAlignment="left" marginRight="30">
<!-- Row 1 -->
<Button id="buttonUp" text="▲" row="0" col="1" class="gamepad-button dpad-button"/>
<gtk:Button id="buttonUp" label="▲" row="0" col="1" styleClasses="gamepad-button dpad-button"/>

<!-- Row 2 -->
<Button id="buttonLeft" text="◀" row="1" col="0" class="gamepad-button dpad-button"/>
<gtk:Button id="buttonLeft" label="◀" row="1" col="0" styleClasses="gamepad-button dpad-button"/>
<!-- Center Placeholder (optional) -->
<!-- <Label text=" " row="1" col="1" class="gamepad-button dpad-center"/> -->
<Button id="buttonRight" text="▶" row="1" col="2" class="gamepad-button dpad-button"/>
<gtk:Button id="buttonRight" label="▶" row="1" col="2" styleClasses="gamepad-button dpad-button"/>

<!-- Row 3 -->
<Button id="buttonDown" text="▼" row="2" col="1" class="gamepad-button dpad-button"/>
<gtk:Button id="buttonDown" label="▼" row="2" col="1" styleClasses="gamepad-button dpad-button"/>
</GridLayout>

<!-- A/B Buttons Column -->
<GridLayout rows="auto, auto" columns="auto" col="1" row="0" verticalAlignment="bottom" horizontalAlignment="right">
<Button id="buttonB" text="B" row="0" col="0" class="gamepad-button action-button B-button" marginBottom="20"/>
<Button id="buttonA" text="A" row="1" col="0" class="gamepad-button action-button A-button"/>
<gtk:Button id="buttonB" label="B" row="0" col="0" styleClasses="gamepad-button action-button B-button" marginBottom="20"/>
<gtk:Button id="buttonA" label="A" row="1" col="0" styleClasses="gamepad-button action-button A-button"/>
</GridLayout>
</GridLayout>
Loading