Screen rotation dialog

This commit is contained in:
David Carley
2022-07-16 19:02:38 -07:00
parent fc4bf1cba3
commit f0bb9079d4
10 changed files with 163 additions and 36 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "bbctrl",
"version": "1.0.10b2",
"version": "1.0.10b4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "bbctrl",
"version": "1.0.10b2",
"version": "1.0.10b4",
"license": "GPL-3.0+",
"dependencies": {
"browserify": "^17.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "bbctrl",
"version": "1.0.10b2",
"version": "1.0.10b4",
"homepage": "https://onefinitycnc.com/",
"repository": "https://github.com/OneFinityCNC/onefinity",
"license": "GPL-3.0+",

View File

@@ -21,5 +21,11 @@ module.exports = {
this.$dispatch('config-changed');
return false;
}
},
methods: {
showScreenRotationDialog: function () {
SvelteComponents.showDialog("ScreenRotation");
}
}
}

View File

@@ -4,16 +4,14 @@ script#settings-view-template(type="text/x-template")
.pure-form.pure-form-aligned
fieldset
h2 Units
h2 Screen
.pure-control-group
label(for="units") units
select(name="units", v-model="display_units")
option(value="METRIC") METRIC
option(value="IMPERIAL") IMPERIAL
label(for="screen-rotation")
button.pure-button(name="screen-rotation", @click="showScreenRotationDialog") Change Screen Rotation
fieldset
h2 Probe Dimensions
templated-input(v-for="templ in template.probe", :name="$key",
templated-input(v-for="templ in template.probe", v-if="$key !== 'probe-diameter'", :name="$key"
:model.sync="config.probe[$key]", :template="templ")
fieldset

View File

@@ -1,4 +1,5 @@
import os
import re
import json
import tornado
import sockjs.tornado
@@ -349,6 +350,46 @@ class JogHandler(bbctrl.APIHandler):
self.get_ctrl().mach.jog(self.json)
displayRotatePattern = re.compile(r'display_rotate\s*=\s*(\d)')
transformationMatrixPattern = re.compile(
r'(\n)(\s+)(MatchIsTouchscreen.*?\n)(\s+Option\s+\"TransformationMatrix\".*?\n)(.*?EndSection)', re.DOTALL)
matchIsTouchscreenPattern = re.compile(
r'(\n)(\s+)(MatchIsTouchscreen.*?\n)(.*?EndSection)', re.DOTALL)
class ScreenRotationHandler(bbctrl.APIHandler):
@gen.coroutine
def get(self):
with open("/boot/config.txt", 'rt') as config:
lines = config.readlines()
for line in lines:
if line.startswith('display_rotate'):
self.write_json({
'rotated': int(displayRotatePattern.search(line).group(1)) != 0
})
return
self.write_json({'rotated': False})
return
@gen.coroutine
def put_ok(self):
rotated = self.json['rotated']
subprocess.Popen(
['/usr/local/bin/edit-boot-config', 'display_rotate={}'.format(2 if rotated else 0)])
with open("/usr/share/X11/xorg.conf.d/40-libinput.conf", 'rt') as config:
text = config.read()
text = transformationMatrixPattern.sub(r'\1\2\3\5', text)
if rotated:
text = matchIsTouchscreenPattern.sub(r'\1\2\3\2Option "TransformationMatrix" "-1 0 1 0 -1 1 0 0 1"\1\4', text)
with open("/usr/share/X11/xorg.conf.d/40-libinput.conf", 'wt') as config:
config.write(text)
subprocess.run('reboot')
# Base class for Web Socket connections
class ClientConnection(object):
def __init__(self, app):
@@ -484,6 +525,7 @@ class Web(tornado.web.Application):
(r'/api/modbus/write', ModbusWriteHandler),
(r'/api/jog', JogHandler),
(r'/api/video', bbctrl.VideoHandler),
(r'/api/screen-rotation', ScreenRotationHandler),
(r'/(.*)', StaticFileHandler,
{'path': bbctrl.get_resource('http/'),
'default_filename': 'index.html'}),

View File

@@ -88,7 +88,7 @@
<Label>Cancel</Label>
</Button>
<Button defaultAction on:click={onConfirm} disabled={hostname.length === 0}>
<Label>Confirm</Label>
<Label>Confirm & Reboot</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -1,31 +1,48 @@
<script lang="ts" context="module">
import { writable } from "svelte/store";
import HomeMachineDialog from "$dialogs/HomeMachineDialog.svelte";
import ProbeDialog from "$dialogs/ProbeDialog.svelte";
import {
HomeMachineProps,
ProbeProps,
type HomeMachinePropsType,
type ProbePropsType,
} from "$dialogs/DialogProps";
import ScreenRotationDialog from "$dialogs/ScreenRotationDialog.svelte";
const HomeMachineDialogProps = writable<HomeMachineDialogPropsType>();
type HomeMachineDialogPropsType = {
open: boolean;
home: () => void;
};
const ProbeDialogProps = writable<ProbeDialogPropsType>();
type ProbeDialogPropsType = {
open: boolean;
probeType: "xyz" | "z";
};
const ScreenRotationDialogProps = writable<ProbeDialogPropsType>();
type ScreenRotationDialogPropsType = {
open: boolean;
};
export function showDialog(
dialog: "HomeMachine",
props: Omit<HomeMachinePropsType, "open">
props: Omit<HomeMachineDialogPropsType, "open">
);
export function showDialog(
dialog: "Probe",
props: Omit<ProbePropsType, "open">
props: Omit<ProbeDialogPropsType, "open">
);
export function showDialog(dialog: string, props: any) {
switch (dialog) {
case "HomeMachine":
HomeMachineProps.set({ ...props, open: true });
HomeMachineDialogProps.set({ ...props, open: true });
break;
case "Probe":
ProbeProps.set({ ...props, open: true });
ProbeDialogProps.set({ ...props, open: true });
break;
case "ScreenRotation":
ScreenRotationDialogProps.set({ ...props, open: true });
break;
default:
@@ -34,5 +51,6 @@
}
</script>
<HomeMachineDialog {...$HomeMachineProps} />
<ProbeDialog {...$ProbeProps} />
<HomeMachineDialog {...$HomeMachineDialogProps} />
<ProbeDialog {...$ProbeDialogProps} />
<ScreenRotationDialog {...$ScreenRotationDialogProps} />

View File

@@ -1,13 +0,0 @@
import { writable } from "svelte/store";
export const HomeMachineProps = writable<HomeMachinePropsType>();
export type HomeMachinePropsType = {
open: boolean,
home: () => void
}
export const ProbeProps = writable<ProbePropsType>();
export type ProbePropsType = {
open: boolean,
probeType: "xyz" | "z"
};

View File

@@ -0,0 +1,76 @@
<script type="ts">
import Dialog, { Title, Content, Actions } from "@smui/dialog";
import Button, { Label } from "@smui/button";
import Radio from "@smui/radio";
import FormField from "@smui/form-field";
import MessageDialog from "$dialogs/MessageDialog.svelte";
import * as Api from "$lib/api";
import { onMount } from "svelte";
const options = [
{ value: 0, label: "Normal" },
{ value: 1, label: "Upside-down" },
];
export let open;
let currentValue;
let value;
let rebooting;
onMount(async () => {
const result = await Api.GET("screen-rotation");
currentValue = value = result.rotated ? 1 : 0;
});
async function onConfirm() {
rebooting = true;
await Api.PUT("screen-rotation", { rotated: value === 1 });
}
</script>
<MessageDialog open={rebooting} title="Rebooting">
Rebooting to apply the new screen rotation...
</MessageDialog>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="screen-rotation-title"
aria-describedby="screen-rotation-content"
>
<Title id="screen-rotation-title">Screen Rotation</Title>
<Content id="screen-rotation-content">
{#each options as option}
<FormField>
<Radio bind:group={value} value={option.value} />
<span slot="label">
{option.label}
</span>
</FormField>
{/each}
</Content>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button
defaultAction
disabled={value === currentValue}
on:click={onConfirm}
>
<Label>Confirm & Reboot</Label>
</Button>
</Actions>
</Dialog>
<style lang="scss">
:global {
#screen-rotation-content {
display: flex;
flex-direction: column;
}
}
</style>

View File

@@ -92,7 +92,7 @@
on:click={onConfirm}
disabled={needPassword && (password.length < 8 || password.length > 128)}
>
<Label>{connectOrDisconnect}</Label>
<Label>{connectOrDisconnect} & Reboot</Label>
</Button>
</Actions>
</Dialog>