Ported live CD wizard to Python
This commit is contained in:
parent
439ea94431
commit
446f7934c8
@ -27,7 +27,7 @@ int main(int argc, char * argv[]) {
|
||||
setuid(1000);
|
||||
toaru_auth_set_vars();
|
||||
|
||||
char * args[] = {"/bin/live-wizard", NULL};
|
||||
char * args[] = {"/bin/wizard.py", NULL};
|
||||
execvp(args[0], args);
|
||||
TRACE("wizard start failed?");
|
||||
}
|
||||
|
@ -1,364 +0,0 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2015 Kevin Lange
|
||||
*
|
||||
* Live CD Welcome Program
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <syscall.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "lib/yutani.h"
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/decorations.h"
|
||||
#include "gui/ttk/ttk.h"
|
||||
|
||||
#include "lib/trace.h"
|
||||
#define TRACE_APP_NAME "live-wizard"
|
||||
|
||||
#define WIZARD_WIDTH 640
|
||||
#define WIZARD_HEIGHT 480
|
||||
|
||||
static yutani_t * yctx;
|
||||
|
||||
static yutani_window_t * win_hints;
|
||||
static gfx_context_t * ctx_hints;
|
||||
|
||||
static yutani_window_t * win_wizard;
|
||||
static gfx_context_t * ctx_wizard;
|
||||
|
||||
static cairo_surface_t * surface_hints;
|
||||
static cairo_surface_t * surface_wizard;
|
||||
|
||||
static cairo_t * cr_hints;
|
||||
static cairo_t * cr_wizard;
|
||||
|
||||
static int should_exit = 0;
|
||||
static int current_frame = 0;
|
||||
|
||||
static int center_x(int x) {
|
||||
return ((int)yctx->display_width - x) / 2;
|
||||
}
|
||||
|
||||
static int center_y(int y) {
|
||||
return ((int)yctx->display_height - y) / 2;
|
||||
}
|
||||
|
||||
static int center_win_x(int x) {
|
||||
return (win_wizard->width - x) / 2;
|
||||
}
|
||||
|
||||
static int button_width = 100;
|
||||
static int button_height = 32;
|
||||
static int button_focused = 0;
|
||||
static void draw_next_button(int is_exit) {
|
||||
if (button_focused == 1) {
|
||||
/* hover */
|
||||
_ttk_draw_button_hover(cr_wizard, center_win_x(button_width), 400, button_width, button_height, is_exit ? "Exit" : "Next");
|
||||
} else if (button_focused == 2) {
|
||||
/* Down */
|
||||
_ttk_draw_button_select(cr_wizard, center_win_x(button_width), 400, button_width, button_height, is_exit ? "Exit" : "Next");
|
||||
} else {
|
||||
/* Something else? */
|
||||
_ttk_draw_button(cr_wizard, center_win_x(button_width), 400, button_width, button_height, is_exit ? "Exit" : "Next");
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_centered_label(int y, int size, char * label) {
|
||||
set_font_face(FONT_SANS_SERIF);
|
||||
set_font_size(size);
|
||||
|
||||
int x = center_win_x(draw_string_width(label));
|
||||
draw_string(ctx_wizard, x, y, rgb(0,0,0), label);
|
||||
}
|
||||
|
||||
static char * LOGO = "/usr/share/logo_login.png";
|
||||
static void draw_logo(void) {
|
||||
sprite_t logo;
|
||||
load_sprite_png(&logo, LOGO);
|
||||
draw_sprite(ctx_wizard, &logo, center_win_x(logo.width), 50);
|
||||
}
|
||||
|
||||
static void draw_arrow(int x, int y, int angle) {
|
||||
|
||||
cairo_save(cr_hints);
|
||||
|
||||
cairo_surface_t * arrow = cairo_image_surface_create_from_png("/usr/share/wizard-arrow.png");
|
||||
int w, h;
|
||||
w = cairo_image_surface_get_width(arrow);
|
||||
h = cairo_image_surface_get_height(arrow);
|
||||
|
||||
cairo_translate(cr_hints, x, y);
|
||||
|
||||
cairo_rotate(cr_hints, (double)angle * M_PI / 179.0);
|
||||
cairo_translate(cr_hints, -w, -h/2);
|
||||
|
||||
cairo_set_source_surface(cr_hints, arrow, 0, 0);
|
||||
cairo_paint(cr_hints);
|
||||
cairo_surface_destroy(arrow);
|
||||
cairo_restore(cr_hints);
|
||||
|
||||
}
|
||||
|
||||
static void redraw(void) {
|
||||
draw_fill(ctx_hints, premultiply(rgba(0,0,0,100)));
|
||||
draw_fill(ctx_wizard, rgb(TTK_BACKGROUND_DEFAULT));
|
||||
|
||||
/* Draw the current tutorial frame */
|
||||
render_decorations(win_wizard, ctx_wizard, "Welcome to とあるOS");
|
||||
switch (current_frame) {
|
||||
case 0:
|
||||
/* Labels for Welcome to とあるOS! */
|
||||
draw_logo();
|
||||
draw_centered_label(100+70, 20, "Welcome to とあるOS!");
|
||||
draw_centered_label(100+88, 12, "This tutorial will guide you through the features");
|
||||
draw_centered_label(100+102,12, "of the operating system, as well as give you a feel");
|
||||
draw_centered_label(100+116,12, "for the UI and design principles.");
|
||||
draw_centered_label(100+180,12, "When you're ready to continue, press \"Next\".");
|
||||
draw_centered_label(120+200,12, "https://github.com/klange/toaruos - http://toaruos.org");
|
||||
draw_centered_label(120+220,12, "とあるOS is free software, released under the terms");
|
||||
draw_centered_label(120+234,12, "of the NCSA/University of Illinois license.");
|
||||
draw_next_button(0);
|
||||
break;
|
||||
case 1:
|
||||
draw_logo();
|
||||
draw_arrow(center_x(WIZARD_WIDTH) + 620, center_y(WIZARD_HEIGHT) - 5, 90);
|
||||
draw_centered_label(100+70,12,"If you wish to exit the tutorial at any time, you can");
|
||||
draw_centered_label(100+84,12,"click the × in the upper right corner of this window.");
|
||||
draw_next_button(0);
|
||||
break;
|
||||
case 2:
|
||||
draw_logo();
|
||||
draw_centered_label(100+70, 12,"As a reminder, とあるOS is a hobby project with few developers.");
|
||||
draw_centered_label(100+84, 12,"As such, do not expect things to work perfectly, or in some cases,");
|
||||
draw_centered_label(100+98, 12,"at all, as the kernel and drivers are very much \"work-in-progress\".");
|
||||
draw_next_button(0);
|
||||
break;
|
||||
case 3:
|
||||
draw_arrow(110, 120, -135);
|
||||
|
||||
cairo_save(cr_hints);
|
||||
cairo_set_operator(cr_hints, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_rgba(cr_hints, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_translate(cr_hints, 70.5, 80.5);
|
||||
cairo_arc(cr_hints, 0, 0, 50, 0, 2 * M_PI);
|
||||
cairo_fill(cr_hints);
|
||||
cairo_restore(cr_hints);
|
||||
|
||||
draw_centered_label(100+10, 12,"とあるOS aims to provide a Unix-like environment.");
|
||||
draw_centered_label(100+24, 12,"You can find familiar command-line tools by opening a terminal.");
|
||||
draw_centered_label(100+38, 12,"Application shortcuts on the desktop are opened with a single click.");
|
||||
draw_centered_label(100+52, 12,"You can also find more graphical applications in the Applications menu.");
|
||||
draw_next_button(0);
|
||||
break;
|
||||
case 4:
|
||||
draw_logo();
|
||||
draw_centered_label(100+70,12,"That's it for now!");
|
||||
draw_centered_label(100+88,12,"You've finished the tutorial.");
|
||||
draw_centered_label(100+102,12,"More guides will be added to this tutorial in the future, but that's");
|
||||
draw_centered_label(100+116,12,"all for now. Press 'Exit' to close the tutorial.");
|
||||
draw_next_button(1);
|
||||
break;
|
||||
default:
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
|
||||
flip(ctx_hints);
|
||||
flip(ctx_wizard);
|
||||
yutani_flip(yctx, win_hints);
|
||||
yutani_flip(yctx, win_wizard);
|
||||
}
|
||||
|
||||
static void do_click_callback(void) {
|
||||
current_frame += 1;
|
||||
redraw();
|
||||
}
|
||||
|
||||
static int previous_buttons = 0;
|
||||
static void do_mouse_stuff(struct yutani_msg_window_mouse_event * me) {
|
||||
if (button_focused == 2) {
|
||||
/* See if we released and are still inside. */
|
||||
if (me->command == YUTANI_MOUSE_EVENT_RAISE || me->command == YUTANI_MOUSE_EVENT_CLICK) {
|
||||
if (!(me->buttons & YUTANI_MOUSE_BUTTON_LEFT)) {
|
||||
if (me->new_x > center_win_x(button_width)
|
||||
&& me->new_x < center_win_x(button_width) + button_width
|
||||
&& me->new_y > 400
|
||||
&& me->new_y < 400 + button_height) {
|
||||
button_focused = 1;
|
||||
do_click_callback();
|
||||
} else {
|
||||
button_focused = 0;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (me->new_x > center_win_x(button_width)
|
||||
&& me->new_x < center_win_x(button_width) + button_width
|
||||
&& me->new_y > 400
|
||||
&& me->new_y < 400 + button_height) {
|
||||
if (!button_focused) {
|
||||
button_focused = 1;
|
||||
redraw();
|
||||
}
|
||||
if (me->command == YUTANI_MOUSE_EVENT_DOWN && (me->buttons & YUTANI_MOUSE_BUTTON_LEFT)) {
|
||||
button_focused = 2;
|
||||
redraw();
|
||||
}
|
||||
} else {
|
||||
if (button_focused) {
|
||||
button_focused = 0;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
previous_buttons = me->buttons;
|
||||
}
|
||||
|
||||
static void resize_finish(int xwidth, int xheight) {
|
||||
yutani_window_resize_accept(yctx, win_hints, xwidth, xheight);
|
||||
|
||||
cairo_destroy(cr_hints);
|
||||
cairo_surface_destroy(surface_hints);
|
||||
|
||||
reinit_graphics_yutani(ctx_hints, win_hints);
|
||||
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, win_hints->width);
|
||||
surface_hints = cairo_image_surface_create_for_data(ctx_hints->backbuffer, CAIRO_FORMAT_ARGB32, win_hints->width, win_hints->height, stride);
|
||||
cr_hints = cairo_create(surface_hints);
|
||||
|
||||
yutani_window_resize_done(yctx, win_hints);
|
||||
|
||||
/* Re-center the wizard */
|
||||
yutani_window_move(yctx, win_wizard, center_x(WIZARD_WIDTH), center_y(WIZARD_HEIGHT));
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
|
||||
TRACE("Opening some windows...");
|
||||
yctx = yutani_init();
|
||||
|
||||
init_decorations();
|
||||
|
||||
win_hints = yutani_window_create_flags(yctx, yctx->display_width, yctx->display_height,
|
||||
YUTANI_WINDOW_FLAG_NO_STEAL_FOCUS | YUTANI_WINDOW_FLAG_DISALLOW_DRAG |
|
||||
YUTANI_WINDOW_FLAG_DISALLOW_RESIZE | YUTANI_WINDOW_FLAG_ALT_ANIMATION);
|
||||
yutani_window_move(yctx, win_hints, 0, 0);
|
||||
yutani_window_update_shape(yctx, win_hints, YUTANI_SHAPE_THRESHOLD_CLEAR);
|
||||
ctx_hints = init_graphics_yutani_double_buffer(win_hints);
|
||||
|
||||
win_wizard = yutani_window_create_flags(yctx, WIZARD_WIDTH, WIZARD_HEIGHT,
|
||||
YUTANI_WINDOW_FLAG_DISALLOW_DRAG | YUTANI_WINDOW_FLAG_DISALLOW_RESIZE);
|
||||
yutani_window_move(yctx, win_wizard, center_x(WIZARD_WIDTH), center_y(WIZARD_HEIGHT));
|
||||
ctx_wizard = init_graphics_yutani_double_buffer(win_wizard);
|
||||
|
||||
int stride;
|
||||
|
||||
stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, win_hints->width);
|
||||
surface_hints = cairo_image_surface_create_for_data(ctx_hints->backbuffer, CAIRO_FORMAT_ARGB32, win_hints->width, win_hints->height, stride);
|
||||
cr_hints = cairo_create(surface_hints);
|
||||
|
||||
stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, win_wizard->width);
|
||||
surface_wizard = cairo_image_surface_create_for_data(ctx_wizard->backbuffer, CAIRO_FORMAT_ARGB32, win_wizard->width, win_wizard->height, stride);
|
||||
cr_wizard = cairo_create(surface_wizard);
|
||||
|
||||
yutani_window_advertise_icon(yctx, win_wizard, "Welcome Tutorial", "live-welcome");
|
||||
|
||||
redraw();
|
||||
|
||||
yutani_focus_window(yctx, win_wizard->wid);
|
||||
|
||||
while (!should_exit) {
|
||||
yutani_msg_t * m = yutani_poll(yctx);
|
||||
|
||||
if (m) {
|
||||
switch (m->type) {
|
||||
case YUTANI_MSG_KEY_EVENT:
|
||||
{
|
||||
struct yutani_msg_key_event * ke = (void*)m->data;
|
||||
if (ke->event.key == 'q' && ke->event.action == KEY_ACTION_DOWN) {
|
||||
should_exit = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
|
||||
{
|
||||
struct yutani_msg_window_focus_change * wf = (void*)m->data;
|
||||
if (wf->wid == win_hints->wid) {
|
||||
yutani_focus_window(yctx, win_wizard->wid);
|
||||
} else if (wf->wid == win_wizard->wid) {
|
||||
win_wizard->focused = wf->focused;
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_WINDOW_MOVE:
|
||||
{
|
||||
struct yutani_msg_window_move * wm = (void*)m->data;
|
||||
if (wm->wid == win_hints->wid) {
|
||||
if (wm->x != 0 || wm->y != 0) {
|
||||
/* force us back to 0,0 */
|
||||
yutani_window_move(yctx, win_hints, 0, 0);
|
||||
}
|
||||
} else if (wm->wid == win_wizard->wid) {
|
||||
if (wm->x != center_x(WIZARD_WIDTH) || wm->y != center_y(WIZARD_HEIGHT)) {
|
||||
yutani_window_move(yctx, win_wizard, center_x(WIZARD_WIDTH), center_y(WIZARD_HEIGHT));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_WELCOME:
|
||||
{
|
||||
struct yutani_msg_welcome * mw = (void*)m->data;
|
||||
|
||||
fprintf(stderr, "ct display_width: %d\ndisplay_height: %d\n", yctx->display_width, yctx->display_height);
|
||||
fprintf(stderr, "mw display_width: %d\ndisplay_height: %d\n", mw->display_width, mw->display_height);
|
||||
yutani_window_resize(yctx, win_hints, mw->display_width, mw->display_height);
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_RESIZE_OFFER:
|
||||
{
|
||||
/* When we request a resize from the display-size-changed, we need
|
||||
* to respond to the offer we'll get from the server to finish it */
|
||||
struct yutani_msg_window_resize * wr = (void*)m->data;
|
||||
if (wr->wid == win_hints->wid) {
|
||||
resize_finish(wr->width, wr->height);
|
||||
} /* Else, ignore resize offers for the main window */
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
|
||||
{
|
||||
struct yutani_msg_window_mouse_event * me = (void*)m->data;
|
||||
if (me->wid != win_wizard->wid) break;
|
||||
int result = decor_handle_event(yctx, m);
|
||||
switch (result) {
|
||||
case DECOR_CLOSE:
|
||||
should_exit = 1;
|
||||
break;
|
||||
default:
|
||||
/* Other actions */
|
||||
do_mouse_stuff(me);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_SESSION_END:
|
||||
should_exit = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(m);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
241
userspace/py/bin/wizard.py
Executable file
241
userspace/py/bin/wizard.py
Executable file
@ -0,0 +1,241 @@
|
||||
#!/usr/bin/python3
|
||||
"""
|
||||
Live CD wizard / tutorial
|
||||
"""
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
|
||||
import cairo
|
||||
|
||||
import yutani
|
||||
import text_region
|
||||
import toaru_fonts
|
||||
|
||||
from button import Button
|
||||
|
||||
class HintHole(object):
|
||||
"""Draws a hole in the hints window."""
|
||||
|
||||
def __init__(self, x, y, radius):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.radius = radius
|
||||
|
||||
def draw(self, ctx):
|
||||
ctx.save();
|
||||
ctx.set_operator(cairo.OPERATOR_SOURCE);
|
||||
ctx.set_source_rgba(0.0, 0.0, 0.0, 0.0);
|
||||
ctx.translate(self.x,self.y)
|
||||
ctx.arc(0, 0, self.radius, 0, 2 * math.pi);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
|
||||
_arrow = cairo.ImageSurface.create_from_png('/usr/share/wizard-arrow.png')
|
||||
|
||||
class HintArrow(object):
|
||||
|
||||
def __init__(self, x, y, angle, wizard_relative=False):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.angle = angle
|
||||
self.wizard_relative = wizard_relative
|
||||
|
||||
def draw(self, ctx):
|
||||
ctx.save()
|
||||
w,h = _arrow.get_width(), _arrow.get_height()
|
||||
|
||||
if self.wizard_relative:
|
||||
ctx.translate((hints.width-window.width)/2+self.x,(hints.height-window.height)/2+self.y)
|
||||
else:
|
||||
ctx.translate(self.x,self.y)
|
||||
ctx.rotate(self.angle * math.pi / 179.0)
|
||||
ctx.translate(-w,-h/2)
|
||||
ctx.set_source_surface(_arrow,0,0)
|
||||
ctx.paint()
|
||||
ctx.restore()
|
||||
|
||||
class HintWindow(yutani.Window):
|
||||
|
||||
def __init__(self):
|
||||
flags = yutani.WindowFlag.FLAG_NO_STEAL_FOCUS | yutani.WindowFlag.FLAG_DISALLOW_DRAG | yutani.WindowFlag.FLAG_DISALLOW_RESIZE | yutani.WindowFlag.FLAG_ALT_ANIMATION
|
||||
super(HintWindow, self).__init__(yutani.yutani_ctx._ptr.contents.display_width, yutani.yutani_ctx._ptr.contents.display_height, doublebuffer=True, flags=flags)
|
||||
self.move(0,0)
|
||||
self.page = 0
|
||||
|
||||
def draw(self):
|
||||
surface = self.get_cairo_surface()
|
||||
ctx = cairo.Context(surface)
|
||||
ctx.rectangle(0,0,self.width,self.height)
|
||||
ctx.set_operator(cairo.OPERATOR_SOURCE)
|
||||
ctx.set_source_rgba(0,0,0,100/255)
|
||||
ctx.fill()
|
||||
|
||||
ctx.set_operator(cairo.OPERATOR_OVER)
|
||||
|
||||
for widget in pages[self.page][1]:
|
||||
widget.draw(ctx)
|
||||
|
||||
self.flip()
|
||||
|
||||
def finish_resize(self, msg):
|
||||
self.resize_accept(msg.width, msg.height)
|
||||
self.reinit()
|
||||
self.draw()
|
||||
self.resize_done()
|
||||
self.flip()
|
||||
|
||||
logo = "/usr/share/logo_login.png"
|
||||
pages = [
|
||||
(f"<img src=\"{logo}\"></img>\n\n<h1>Welcome to とあるOS!</h1>\n\nThis tutorial will guide you through the features of the operating system, as well as give you a feel for the UI and design principles.\n\n\nWhen you're ready to continue, press \"Next\".\n\n<link target=\"\">https://github.com/klange/toaruos</link> - <link target=\"\">http://toaruos.org</link>\n\nとあるOS is free software, released under the terms of the NCSA/University of Illinois license.",[]),
|
||||
(f"<img src=\"{logo}\"></img>\n\nIf you wish to exit the tutorial at any time, you can click the × in the upper right corner of the window.",[HintArrow(620,-5,90,True)]),
|
||||
(f"<img src=\"{logo}\"></img>\n\nAs a reminder, とあるOS is a hobby project with few developers.\nAs such, do not expect things to work perfectly, or in some cases, at all, as the kernel and drivers are very much \"work-in-progress\".",[]),
|
||||
(f"\n\n\n\nとあるOS aims to provide a Unix-like environment. You can find familiar command-line tools by opening a terminal. Application shorctus on the desktop, as well as files in the file browser, are opened with a single click. You can also find more applications in the Applications menu.",[HintHole(70.5,80.5,50),HintArrow(110,120,-135)]),
|
||||
(f"<img src=\"{logo}\"></img>\n\nThat's it for now!\n\nYou've finished the tutorial. More guides will be added to this tutorial in the future, but that's all for now. Press 'Exit' to close the tutorial and get started using the OS.",[]),
|
||||
]
|
||||
|
||||
class WizardWindow(yutani.Window):
|
||||
|
||||
text_offset = 110
|
||||
|
||||
def __init__(self, decorator, title="Welcome to ToaruOS!", icon="star"):
|
||||
flags = yutani.WindowFlag.FLAG_DISALLOW_DRAG | yutani.WindowFlag.FLAG_DISALLOW_RESIZE
|
||||
super(WizardWindow, self).__init__(640,480, title=title, icon=icon, doublebuffer=True, flags=flags)
|
||||
self.center()
|
||||
self.decorator = decorator
|
||||
hpad = 100
|
||||
self.page = 0
|
||||
self.button = Button("Next",self.button_click)
|
||||
self.hover_widget = None
|
||||
self.down_button = None
|
||||
self.tr = text_region.TextRegion(hpad+self.decorator.left_width(),10+self.decorator.top_height(),self.width-self.decorator.width()-hpad*2,self.height-self.decorator.height()-20)
|
||||
self.tr.line_height = 15
|
||||
self.tr.set_alignment(2)
|
||||
self.load_page()
|
||||
|
||||
def button_click(self, button):
|
||||
self.page += 1
|
||||
if self.page >= len(pages):
|
||||
sys.exit(0)
|
||||
self.load_page()
|
||||
|
||||
def load_page(self):
|
||||
self.tr.set_richtext(pages[self.page][0])
|
||||
if self.page == len(pages)-1:
|
||||
self.button.text = "Exit"
|
||||
hints.page = self.page
|
||||
hints.draw()
|
||||
|
||||
def center(self):
|
||||
self.move(int((yutani.yutani_ctx._ptr.contents.display_width-self.width)/2),int((yutani.yutani_ctx._ptr.contents.display_height-self.height)/2))
|
||||
|
||||
def draw(self):
|
||||
surface = self.get_cairo_surface()
|
||||
|
||||
WIDTH, HEIGHT = self.width - self.decorator.width(), self.height - self.decorator.height()
|
||||
|
||||
ctx = cairo.Context(surface)
|
||||
ctx.translate(self.decorator.left_width(), self.decorator.top_height())
|
||||
ctx.rectangle(0,0,WIDTH,HEIGHT)
|
||||
ctx.set_source_rgb(204/255,204/255,204/255)
|
||||
ctx.fill()
|
||||
|
||||
self.tr.draw(self)
|
||||
self.button.draw(self,ctx,int((WIDTH-100)/2),380,100,38)
|
||||
|
||||
self.decorator.render(self)
|
||||
self.flip()
|
||||
|
||||
def mouse_event(self, msg):
|
||||
if d.handle_event(msg) == yutani.Decor.EVENT_CLOSE:
|
||||
window.close()
|
||||
sys.exit(0)
|
||||
x,y = msg.new_x - self.decorator.left_width(), msg.new_y - self.decorator.top_height()
|
||||
w,h = self.width - self.decorator.width(), self.height - self.decorator.height()
|
||||
|
||||
redraw = False
|
||||
|
||||
if self.down_button:
|
||||
if msg.command == yutani.MouseEvent.RAISE or msg.command == yutani.MouseEvent.CLICK:
|
||||
if not (msg.buttons & yutani.MouseButton.BUTTON_LEFT):
|
||||
if x >= self.down_button.x and \
|
||||
x < self.down_button.x + self.down_button.width and \
|
||||
y >= self.down_button.y and \
|
||||
y < self.down_button.y + self.down_button.height:
|
||||
self.down_button.focus_enter()
|
||||
self.down_button.callback(self.down_button)
|
||||
self.down_button = None
|
||||
redraw = True
|
||||
else:
|
||||
self.down_button.focus_leave()
|
||||
self.down_button = None
|
||||
redraw = True
|
||||
else:
|
||||
if x >= self.button.x and x < self.button.x + self.button.width and y >= self.button.y and y < self.button.y + self.button.height:
|
||||
if self.button != self.hover_widget:
|
||||
if self.hover_widget:
|
||||
self.hover_widget.leave()
|
||||
self.button.focus_enter()
|
||||
self.hover_widget = self.button
|
||||
redraw = True
|
||||
if msg.command == yutani.MouseEvent.DOWN:
|
||||
self.button.hilight = 2
|
||||
self.down_button = self.button
|
||||
redraw = True
|
||||
else:
|
||||
if self.hover_widget == self.button:
|
||||
self.button.focus_leave()
|
||||
redraw = True
|
||||
|
||||
if redraw:
|
||||
self.draw()
|
||||
|
||||
def keyboard_event(self, msg):
|
||||
if msg.event.action != 0x01:
|
||||
return # Ignore anything that isn't a key down.
|
||||
if msg.event.key == b"q":
|
||||
self.close()
|
||||
sys.exit(0)
|
||||
if msg.event.key == b' ':
|
||||
self.page += 1
|
||||
if self.page >= len(pages):
|
||||
self.close()
|
||||
sys.exit(0)
|
||||
self.load_page()
|
||||
self.draw()
|
||||
|
||||
if __name__ == '__main__':
|
||||
yctx = yutani.Yutani()
|
||||
d = yutani.Decor()
|
||||
|
||||
hints = HintWindow()
|
||||
hints.draw()
|
||||
|
||||
window = WizardWindow(d)
|
||||
window.draw()
|
||||
|
||||
while 1:
|
||||
# Poll for events.
|
||||
msg = yutani.yutani_ctx.poll()
|
||||
if msg.type == yutani.Message.MSG_SESSION_END:
|
||||
window.close()
|
||||
hints.close()
|
||||
break
|
||||
elif msg.type == yutani.Message.MSG_WELCOME:
|
||||
hints.resize(msg.display_width,msg.display_height)
|
||||
window.center()
|
||||
elif msg.type == yutani.Message.MSG_RESIZE_OFFER:
|
||||
if msg.wid == hints.wid:
|
||||
hints.finish_resize(msg)
|
||||
elif msg.type == yutani.Message.MSG_KEY_EVENT:
|
||||
if msg.wid == window.wid:
|
||||
window.keyboard_event(msg)
|
||||
elif msg.type == yutani.Message.MSG_WINDOW_FOCUS_CHANGE:
|
||||
if msg.wid == hints.wid:
|
||||
yctx.focus_window(window.wid)
|
||||
if msg.wid == window.wid:
|
||||
window.focused = msg.focused
|
||||
window.draw()
|
||||
elif msg.type == yutani.Message.MSG_WINDOW_MOUSE_EVENT:
|
||||
if msg.wid == window.wid:
|
||||
window.mouse_event(msg)
|
Loading…
x
Reference in New Issue
Block a user