mirror of
https://github.com/clockworkpi/Menu.git
synced 2026-03-25 05:12:39 +01:00
gcores ~/apps/Menu branch first commit
This commit is contained in:
@@ -1,699 +0,0 @@
|
||||
|
||||
/*
|
||||
set_callback(on_select void, on_close void, arg void)
|
||||
set_fadeout(fadeout. fadeio)
|
||||
set_ext(ext. char)
|
||||
set_dir(render void, dir_name. char) bool
|
||||
refresh(render void) bool
|
||||
set_mode(mode mode)
|
||||
set_exec_format(format. char)
|
||||
hidden_files(visible bool)
|
||||
cursor_to(name. char) bool
|
||||
goto_parent_dir(render void) bool
|
||||
get_dir_count() size_t
|
||||
get_file_count() size_t
|
||||
get_all_count() size_t
|
||||
get_path() .char
|
||||
close()
|
||||
*/
|
||||
|
||||
class game+, scene+, file_browser {
|
||||
|
||||
inherit game::scene = super;
|
||||
|
||||
private import rt::c, lib::sdl2;
|
||||
|
||||
private alias
|
||||
string = std::string,
|
||||
strings = std::strings,
|
||||
vector = std::vector;
|
||||
|
||||
private alias popup_menu = control::popup_menu;
|
||||
|
||||
enum mode {
|
||||
browse,
|
||||
select,
|
||||
select_file,
|
||||
select_dir,
|
||||
select_image,
|
||||
exec
|
||||
}
|
||||
|
||||
struct file {
|
||||
icon texture;
|
||||
black_font texture;
|
||||
white_font texture;
|
||||
link bool;
|
||||
type uchar;
|
||||
str(NAME_MAX) char;
|
||||
}
|
||||
|
||||
struct file_browser {
|
||||
struct tex {
|
||||
dir texture;
|
||||
reg texture;
|
||||
lnk texture;
|
||||
name texture;
|
||||
image texture;
|
||||
empty texture;
|
||||
}
|
||||
fadeio fadeio;
|
||||
fadeout. fadeio;
|
||||
image_timer delay;
|
||||
input_delay repeat;
|
||||
input_lock norepeat;
|
||||
root string;
|
||||
path string;
|
||||
ext strings;
|
||||
dirs vector<file>;
|
||||
files vector<file>;
|
||||
on_select void;
|
||||
on_close void;
|
||||
arg void;
|
||||
cursor int;
|
||||
start_index int;
|
||||
exec_format string;
|
||||
mode mode;
|
||||
hidden_files bool;
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
memset(this, 0, sizeof(file_browser));
|
||||
constructor(this);
|
||||
}
|
||||
|
||||
func destructor() {
|
||||
destructor(this);
|
||||
}
|
||||
|
||||
define {
|
||||
TOP_HEIGHT = 23;
|
||||
ITEM_HEIGHT = 25;
|
||||
SCROLL_WIDTH = 8;
|
||||
SCROLL_HEIGHT = 80;
|
||||
}
|
||||
|
||||
func init(render void) bool {
|
||||
this.tex.dir->load_file(render,
|
||||
global::make_path("file_browser/dir.png"));
|
||||
this.tex.reg->load_file(render,
|
||||
global::make_path("file_browser/reg.png"));
|
||||
this.tex.lnk->load_file(render,
|
||||
global::make_path("file_browser/lnk.png"));
|
||||
this.tex.empty->init(
|
||||
global::uni_font->create_tex(render, "Empty", 0xff000000));
|
||||
var wnd. window = this->get_window();
|
||||
this.fadeio->init(wnd, 300);
|
||||
this.fadeio->set_texture(wnd->screen_capture2());
|
||||
this.image_timer->init(300);
|
||||
this.input_delay->init(300, -48, 6);
|
||||
this.exec_format->set("%s");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
on_select = lambda(filename. char, arg void) [
|
||||
|
||||
];
|
||||
on_close = lambda(arg void) [
|
||||
|
||||
];
|
||||
*/
|
||||
inline set_callback(on_select void, on_close void, arg void) {
|
||||
this.on_select = on_select;
|
||||
this.on_close = on_close;
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
inline set_fadeout(fadeout. fadeio) {
|
||||
this.fadeout = fadeout;
|
||||
}
|
||||
|
||||
private inline reload_image() {
|
||||
this.tex.image->destroy();
|
||||
this.image_timer->reset();
|
||||
}
|
||||
|
||||
/*
|
||||
slow
|
||||
*/
|
||||
private static func sort(items. vector<file>) {
|
||||
forvar i int = 0, c int = items->count() - 1; i < c; i++ {
|
||||
forvar j int = 0; j < c - i; j++ {
|
||||
var x. file = items->at(j);
|
||||
var y. file = items->at(j + 1);
|
||||
if strcmp(&x.str, &y.str) > 0 {
|
||||
var tmp $file = .x;
|
||||
.x = .y;
|
||||
.y = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func set_ext(ext. char) {
|
||||
this.ext->clear();
|
||||
this.ext->split(ext, ",");
|
||||
}
|
||||
|
||||
private func is_allow_ext(filename. char) bool {
|
||||
if this.ext->empty();
|
||||
return true;
|
||||
var extension. char = strrchr(filename, '.');
|
||||
if extension == null {
|
||||
extension = "?";
|
||||
else
|
||||
extension++;
|
||||
}
|
||||
var count size_t = this.ext->count();
|
||||
while count {
|
||||
if !strcasecmp(this.ext->item(--count), extension);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
func set_dir(render void, dir_name. char, root bool = false) bool {
|
||||
var dir void = opendir(dir_name);
|
||||
if dir == null;
|
||||
return false;
|
||||
this.tex.name->init(
|
||||
global::uni_font->create_tex(render, dir_name, 0xffffffff));
|
||||
this.path->set(dir_name);
|
||||
while this.path->len() > 1 and
|
||||
this.path->ends_with('/');
|
||||
this.path->remove_back();
|
||||
if root;
|
||||
this.root->set(this.path->ptr());
|
||||
this.dirs->clear();
|
||||
this.files->clear();
|
||||
this.cursor = 0;
|
||||
this.start_index = 0;
|
||||
using ent. struct_dirent {
|
||||
while (ent = readdir(dir)) ~= null {
|
||||
var file. file;
|
||||
var link bool = false;
|
||||
if ent.d_type == DT_LNK {
|
||||
var str string;
|
||||
var path. char = realpath(str->format("%s/%s", this.path->ptr(), &ent.d_name), null);
|
||||
if path == null;
|
||||
continue;
|
||||
defer free(path);
|
||||
var st struct_stat;
|
||||
if stat(path, &st);
|
||||
continue;
|
||||
if S_ISDIR(st.st_mode) {
|
||||
ent.d_type = DT_DIR;
|
||||
elseif S_ISREG(st.st_mode);
|
||||
ent.d_type = DT_REG;
|
||||
else
|
||||
ent.d_type = DT_UNKNOWN;
|
||||
}
|
||||
link = true;
|
||||
}
|
||||
if this.hidden_files and ent.d_name[0] == '.' {
|
||||
continue;
|
||||
}
|
||||
if ent.d_type == DT_DIR {
|
||||
if ent.d_name[0] == '.' and !ent.d_name[1] or
|
||||
ent.d_name[1] == '.' and !ent.d_name[2] {
|
||||
file = null;
|
||||
else
|
||||
file = this.dirs->new();
|
||||
file.icon->init(this.tex.dir->get_texture(), false);
|
||||
}
|
||||
elseif ent.d_type == DT_REG;
|
||||
if this->is_allow_ext(&ent.d_name) {
|
||||
file = this.files->new();
|
||||
file.icon->init(this.tex.reg->get_texture(), false);
|
||||
else
|
||||
file = null;
|
||||
}
|
||||
else
|
||||
file = null;
|
||||
}
|
||||
if file ~= null {
|
||||
file.link = link;
|
||||
file.type = ent.d_type;
|
||||
strcpy(&file.str, &ent.d_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
this->sort(&this.dirs);
|
||||
this->sort(&this.files);
|
||||
this->reload_image();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline refresh(render void) bool {
|
||||
return this->set_dir(render, this.path->ptr());
|
||||
}
|
||||
|
||||
inline set_mode(mode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
inline set_exec_format(format. char) {
|
||||
this.exec_format->set(format);
|
||||
}
|
||||
|
||||
inline hidden_files(visible bool) {
|
||||
this.hidden_files = visible;
|
||||
}
|
||||
|
||||
func cursor_to(name. char) bool {
|
||||
forvar index size_t = 0, count size_t = this.dirs->count(); index < count; index++ {
|
||||
if !strcmp(&this.dirs->at(index).str, name) {
|
||||
this.cursor = index;
|
||||
this->update_scroll();
|
||||
this->reload_image();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
forvar index size_t = 0, count size_t = this.files->count(); index < count; index++ {
|
||||
if !strcmp(&this.files->at(index).str, name) {
|
||||
this.cursor = this.dirs->count() + index;
|
||||
this->update_scroll();
|
||||
this->reload_image();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
func goto_parent_dir(render void) bool {
|
||||
if this.path->empty();
|
||||
return false;
|
||||
var path string;
|
||||
path->set(this.path->ptr());
|
||||
while path->ends_with('/');
|
||||
path->remove_back();
|
||||
if path->empty();
|
||||
return true;
|
||||
/*
|
||||
fixme
|
||||
*/
|
||||
if !strcmp(path->ptr(), this.root->ptr()) {
|
||||
this->close();
|
||||
return true;
|
||||
}
|
||||
var slash. char = strrchr(path->ptr(), '/');
|
||||
if slash == null;
|
||||
return false;
|
||||
var cur_dir string;
|
||||
cur_dir->set(slash + 1);
|
||||
if slash == path->ptr() {
|
||||
path->set("/");
|
||||
else
|
||||
path->set(path->ptr(), slash - path->ptr());
|
||||
}
|
||||
if func = this->set_dir(render, path->ptr()) {
|
||||
if !cur_dir->empty() {
|
||||
this->cursor_to(cur_dir->ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline get_dir_count() size_t {
|
||||
return this.dirs->count();
|
||||
}
|
||||
|
||||
inline get_file_count() size_t {
|
||||
return this.files->count();
|
||||
}
|
||||
|
||||
inline get_all_count() size_t {
|
||||
return this.dirs->count() + this.files->count();
|
||||
}
|
||||
|
||||
inline get_path() .char {
|
||||
return this.path->ptr();
|
||||
}
|
||||
|
||||
private func get_selected_file() .file {
|
||||
var cursor int = this.cursor;
|
||||
var dir_count size_t = this.dirs->count();
|
||||
if dir_count and cursor < dir_count {
|
||||
return this.dirs->at(cursor);
|
||||
else
|
||||
if (cursor -= dir_count) < this.files->count();
|
||||
return this.files->at(cursor);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
func close() {
|
||||
if this.on_close ~= null {
|
||||
proto fn(arg void);
|
||||
fn[this.on_close](this.arg);
|
||||
}
|
||||
if this.fadeout ~= null {
|
||||
this.fadeout->set_texture(this->get_window()->screen_capture2());
|
||||
this.fadeout->reset();
|
||||
}
|
||||
this->quit();
|
||||
}
|
||||
|
||||
private func select(filename. char) {
|
||||
if this.on_select ~= null {
|
||||
proto fn(filename. char, arg void);
|
||||
fn[this.on_select](filename, this.arg);
|
||||
}
|
||||
this->close();
|
||||
}
|
||||
|
||||
private func exec(filename. char) {
|
||||
var str string;
|
||||
exec3(this->get_window(), "Please Wait",
|
||||
str->format(this.exec_format->ptr(), filename));
|
||||
}
|
||||
|
||||
private func action(render void) {
|
||||
var file. file = this->get_selected_file();
|
||||
if file ~= null {
|
||||
if file.type == DT_DIR {
|
||||
var new_path string;
|
||||
new_path->set(this.path->ptr());
|
||||
while new_path->ends_with('/');
|
||||
new_path->remove_back();
|
||||
this->set_dir(render,
|
||||
new_path->appendf("/%s", &file.str));
|
||||
elseif file.type == DT_REG;
|
||||
if this.mode == mode.select or
|
||||
this.mode == mode.select_file or
|
||||
this.mode == mode.select_image {
|
||||
var filename string;
|
||||
this->select(filename->format("%s/%s",
|
||||
this->get_path(), &file.str));
|
||||
elseif this.mode == mode.exec;
|
||||
var filename string;
|
||||
this->exec(filename->format("%s/%s",
|
||||
this->get_path(), &file.str));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func show_popup(render void, file. file) {
|
||||
// MENU_COPY
|
||||
// MENU_PASTE
|
||||
define {
|
||||
MENU_REFRESH = 1;
|
||||
MENU_EXECUTE = 2;
|
||||
MENU_SELECT = 3;
|
||||
MENU_LINK = 4;
|
||||
MENU_DELETE = 5;
|
||||
MENU_EXIT = 6;
|
||||
}
|
||||
this->close_popup();
|
||||
var popup. popup_menu = this->create_control<popup_menu>(0, 0);
|
||||
popup->set_callback(
|
||||
lambda(id int, this.file_browser) [
|
||||
if id == MENU_REFRESH {
|
||||
this->refresh(this->get_window()->get_render());
|
||||
elseif id == MENU_EXECUTE;
|
||||
var file. file = this->get_selected_file();
|
||||
if file ~= null {
|
||||
var filename string;
|
||||
this->exec(filename->format("%s/%s",
|
||||
this->get_path(), &file.str));
|
||||
}
|
||||
elseif id == MENU_SELECT;
|
||||
var file. file = this->get_selected_file();
|
||||
if file ~= null {
|
||||
var filename string;
|
||||
this->select(filename->format("%s/%s",
|
||||
this->get_path(), &file.str));
|
||||
}
|
||||
elseif id == MENU_LINK;
|
||||
var file. file = this->get_selected_file();
|
||||
if file ~= null {
|
||||
var parent. scene::main = this->get_window()->get_last_scene();
|
||||
if parent ~= null {
|
||||
if !strcmp(parent->get_name(), "main") {
|
||||
import scene::main;
|
||||
var tile_menu. tile_menu = parent.tile_menu;
|
||||
tile_menu->set_mode(tile_menu::mode.link);
|
||||
var filename string;
|
||||
var link string;
|
||||
link->format(this.exec_format->ptr(),
|
||||
filename->format("%s/%s", this->get_path(), &file.str));
|
||||
tile_menu->set_link(link->ptr());
|
||||
this->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif id == MENU_DELETE;
|
||||
var file. file = this->get_selected_file();
|
||||
if file ~= null {
|
||||
var filename string;
|
||||
system(filename->format("sudo rm -rf \"%s/%s\"",
|
||||
this->get_path(), &file.str));
|
||||
// TODO
|
||||
}
|
||||
elseif id == MENU_EXIT;
|
||||
this->close();
|
||||
}
|
||||
],
|
||||
lambda(this.file_browser) [
|
||||
this->close_popup();
|
||||
], this);
|
||||
popup->add_menu(render, MENU_REFRESH, "Refresh");
|
||||
if file ~= null {
|
||||
if file.type == DT_REG {
|
||||
var filename string;
|
||||
var st struct_stat;
|
||||
if !stat(filename->format("%s/%s", this->get_path(), &file.str), &st) {
|
||||
if st.st_mode & S_IXUSR {
|
||||
popup->add_menu(render, MENU_EXECUTE, "Execute");
|
||||
}
|
||||
}
|
||||
if this.mode == mode.browse or
|
||||
this.mode == mode.exec {
|
||||
popup->add_menu(render, MENU_LINK, "Link");
|
||||
}
|
||||
elseif file.type == DT_DIR;
|
||||
if this.mode == mode.select or
|
||||
this.mode == mode.select_dir {
|
||||
popup->add_menu(render, MENU_SELECT, "Select");
|
||||
}
|
||||
}
|
||||
}
|
||||
// popup->add_menu(render, MENU_DELETE, "Delete");
|
||||
popup->add_menu(render, MENU_EXIT, "Exit");
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
popup->set_pos(
|
||||
(rect.w - popup->get_width()) / 2,
|
||||
(rect.h - popup->get_height()) / 2);
|
||||
this->set_popup(popup);
|
||||
}
|
||||
|
||||
private func update_scroll() {
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
if this.start_index > this.cursor {
|
||||
this.start_index = this.cursor;
|
||||
else
|
||||
var display_count int = (rect.h - TOP_HEIGHT) / ITEM_HEIGHT;
|
||||
var delta int = this.cursor - this.start_index + 1;
|
||||
if display_count < delta;
|
||||
this.start_index += delta - display_count;
|
||||
}
|
||||
}
|
||||
|
||||
func update(render void) {
|
||||
if this->has_popup() {
|
||||
this.super->update(render);
|
||||
else
|
||||
if this.image_timer->do() {
|
||||
if this.mode == mode.select_image {
|
||||
if this.tex.image->get_texture() == null {
|
||||
var file. file = this->get_selected_file();
|
||||
if file ~= null {
|
||||
if file.type == DT_REG {
|
||||
var filename string;
|
||||
this.tex.image->load_file(render,
|
||||
filename->format("%s/%s", this->get_path(), &file.str));
|
||||
}
|
||||
}
|
||||
this.image_timer->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
var state. uint8 = SDL_GetKeyboardState(null);
|
||||
if state[CPI_SCANCODE_UP] {
|
||||
if this.input_delay->do() {
|
||||
if this.cursor {
|
||||
this.cursor--;
|
||||
this->update_scroll();
|
||||
this->reload_image();
|
||||
}
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_DOWN];
|
||||
if this.input_delay->do() {
|
||||
if this.cursor < this->get_all_count() -1 {
|
||||
this.cursor++;
|
||||
this->update_scroll();
|
||||
this->reload_image();
|
||||
}
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_LEFT];
|
||||
if this.input_delay->do() {
|
||||
if this.cursor - 10 < 0 {
|
||||
this.cursor = 0;
|
||||
else
|
||||
this.cursor -= 10;
|
||||
}
|
||||
this->update_scroll();
|
||||
this->reload_image();
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_RIGHT];
|
||||
if this.input_delay->do() {
|
||||
if this.cursor + 10 < this->get_all_count() -1 {
|
||||
this.cursor += 10;
|
||||
else
|
||||
this.cursor = this->get_all_count() -1;
|
||||
}
|
||||
this->update_scroll();
|
||||
this->reload_image();
|
||||
this.input_delay->undo();
|
||||
}
|
||||
else
|
||||
this.input_delay->reset();
|
||||
}
|
||||
if state[CPI_SCANCODE_A] {
|
||||
if this.input_lock->do();
|
||||
this->goto_parent_dir(render);
|
||||
elseif state[CPI_SCANCODE_B];
|
||||
if this.input_lock->do();
|
||||
this->action(render);
|
||||
elseif state[CPI_SCANCODE_MENU];
|
||||
if this.input_lock->do();
|
||||
this->show_popup(render, this->get_selected_file());
|
||||
else
|
||||
this.input_lock->set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func draw_items(render void, items. vector<file>, begin size_t, cursor int, rect. SDL_Rect, x int, y& int) bool {
|
||||
forvar index size_t = begin, count size_t = items->count(); index < count; index++ {
|
||||
var item. file = items->at(index);
|
||||
var sub_rect SDL_Rect;
|
||||
sub_rect.x = 0;
|
||||
sub_rect.y = y;
|
||||
sub_rect.w = rect.w;
|
||||
sub_rect.h = ITEM_HEIGHT;
|
||||
if index + cursor == this.cursor {
|
||||
SDL_SetRenderDrawColor(render, 0x00, 0xa2, 0xe8, 0xff);
|
||||
SDL_RenderFillRect(render, &sub_rect);
|
||||
if item.white_font->get_texture() == null {
|
||||
item.white_font->init(
|
||||
global::uni_font->create_tex(render, &item.str, 0xffffffff));
|
||||
}
|
||||
item.white_font->draw(render, x + item.icon->get_width() + 3,
|
||||
y + (ITEM_HEIGHT - item.white_font->get_height()) / 2);
|
||||
else
|
||||
if (y - TOP_HEIGHT) / ITEM_HEIGHT % 2 {
|
||||
SDL_SetRenderDrawColor(render, 0xe0, 0xe0, 0xe0, 0xff);
|
||||
SDL_RenderFillRect(render, &sub_rect);
|
||||
}
|
||||
if item.black_font->get_texture() == null {
|
||||
item.black_font->init(
|
||||
global::uni_font->create_tex(render, &item.str, 0xff000000));
|
||||
}
|
||||
item.black_font->draw(render, x + item.icon->get_width() + 3,
|
||||
y + (ITEM_HEIGHT - item.black_font->get_height()) / 2);
|
||||
}
|
||||
item.icon->draw(render, x,
|
||||
y + (ITEM_HEIGHT - item.icon->get_height()) / 2);
|
||||
if item.link {
|
||||
this.tex.lnk->draw(render, x,
|
||||
y + (ITEM_HEIGHT - this.tex.lnk->get_height()) / 2);
|
||||
}
|
||||
if (y += ITEM_HEIGHT) > rect.h;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
|
||||
SDL_RenderClear(render);
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
var sub_rect SDL_Rect;
|
||||
sub_rect.x = 0;
|
||||
sub_rect.y = 0;
|
||||
sub_rect.w = rect.w;
|
||||
sub_rect.h = TOP_HEIGHT;
|
||||
SDL_SetRenderDrawColor(render, 0x35, 0x35, 0x35, 0xff);
|
||||
SDL_RenderFillRect(render, &sub_rect);
|
||||
if this.tex.name->get_width() > rect.w {
|
||||
this.tex.name->draw(render,
|
||||
-(this.tex.name->get_width() - rect.w) - 4,
|
||||
(TOP_HEIGHT - this.tex.name->get_height()) / 2);
|
||||
else
|
||||
this.tex.name->draw(render,
|
||||
(rect.w - this.tex.name->get_width()) / 2,
|
||||
(TOP_HEIGHT - this.tex.name->get_height()) / 2);
|
||||
}
|
||||
var file_count int = this->get_all_count();
|
||||
if file_count {
|
||||
var x int = 4;
|
||||
var y int = TOP_HEIGHT;
|
||||
var dir_count size_t = this.dirs->count();
|
||||
if dir_count and this.start_index < dir_count {
|
||||
if this->draw_items(render, &this.dirs, this.start_index, 0, &rect, x, y);
|
||||
this->draw_items(render, &this.files, 0, dir_count, &rect, x, y);
|
||||
else
|
||||
this->draw_items(render, &this.files, this.start_index - dir_count, dir_count, &rect, x, y);
|
||||
}
|
||||
var display_count int = (rect.h - TOP_HEIGHT) / ITEM_HEIGHT;
|
||||
if display_count < file_count {
|
||||
sub_rect.x = rect.w - SCROLL_WIDTH;
|
||||
sub_rect.y = TOP_HEIGHT +
|
||||
int((float(this.start_index) / (file_count - display_count)) *
|
||||
(rect.h - (TOP_HEIGHT + SCROLL_HEIGHT)));
|
||||
sub_rect.w = SCROLL_WIDTH;
|
||||
sub_rect.h = SCROLL_HEIGHT;
|
||||
SDL_SetRenderDrawColor(render, 0x80, 0x80, 0x80, 0xff);
|
||||
SDL_RenderFillRect(render, &sub_rect);
|
||||
}
|
||||
else
|
||||
this.tex.empty->draw(render,
|
||||
(rect.w - this.tex.empty->get_width()) / 2,
|
||||
(rect.h - this.tex.empty->get_height()) / 2);
|
||||
}
|
||||
define {
|
||||
IMAGE_MAX_WIDTH = 80;
|
||||
IMAGE_MAX_HEIGHT = 80;
|
||||
IMAGE_GAP = 15;
|
||||
}
|
||||
if this.tex.image->get_texture() ~= null {
|
||||
var width int = this.tex.image->get_width();
|
||||
var height int = this.tex.image->get_height();
|
||||
if width > IMAGE_MAX_WIDTH;
|
||||
width = IMAGE_MAX_WIDTH;
|
||||
if height > IMAGE_MAX_HEIGHT;
|
||||
height = IMAGE_MAX_HEIGHT;
|
||||
this.tex.image->draw3(render,
|
||||
rect.w - (width + IMAGE_GAP),
|
||||
rect.h - (height + IMAGE_GAP), width, height);
|
||||
}
|
||||
this.super->draw(render);
|
||||
this.fadeio->do();
|
||||
}
|
||||
|
||||
func wake() {
|
||||
this.input_delay->reset(false);
|
||||
this.input_lock->set(true);
|
||||
this.super->wake();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
|
||||
class game+, scene+, intro {
|
||||
|
||||
inherit game::scene = super;
|
||||
|
||||
private import lib::sdl2;
|
||||
|
||||
struct intro {
|
||||
fadeio fadeio;
|
||||
delay delay;
|
||||
logo texture;
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
constructor(this); }
|
||||
func destructor() {
|
||||
destructor(this); }
|
||||
|
||||
func init(render void) bool {
|
||||
this.fadeio->init(this->get_window(), 2000);
|
||||
this.fadeio->set_color(235, 235, 235);
|
||||
this.delay->init(1000);
|
||||
this.logo->load_file(render,
|
||||
global::make_path("logo.png"));
|
||||
return true;
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
SDL_SetRenderDrawColor(render, 235, 235, 235, 0xff);
|
||||
SDL_RenderClear(render);
|
||||
var wnd. window = this->get_window();
|
||||
var rect SDL_Rect = 0;
|
||||
wnd->get_size(&rect.w, &rect.h);
|
||||
this.logo->draw(render,
|
||||
rect.w - (rect.w + this.logo->get_width()) / 2,
|
||||
rect.h - (rect.h + this.logo->get_height()) / 2);
|
||||
if this.fadeio->do() and this.delay->do() {
|
||||
wnd->set_new_scene<scene::main>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,646 +0,0 @@
|
||||
|
||||
/*
|
||||
set_callback(on_done void, on_close void, arg void)
|
||||
set_fadeout(fadeout. fadeio)
|
||||
set_title(render void, title. char)
|
||||
set_text(render void, text. char)
|
||||
get_text() .char
|
||||
close()
|
||||
*/
|
||||
|
||||
class game+, scene+, keybd {
|
||||
|
||||
inherit game::scene = super;
|
||||
|
||||
private import rt::c, std::utf8, lib::sdl2;
|
||||
|
||||
private alias string = std::string;
|
||||
|
||||
private define {
|
||||
BUTTON_COL = 11;
|
||||
BUTTON_ROW = 4;
|
||||
BUTTON_COUNT = BUTTON_COL * BUTTON_ROW;
|
||||
BUTTON_WIDTH = 25;
|
||||
BUTTON_HEIGHT = 23;
|
||||
BUTTON_GAP = 3;
|
||||
}
|
||||
|
||||
private var layout(3, BUTTON_COUNT) char = {
|
||||
|
||||
// 0
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
|
||||
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '_',
|
||||
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ':', '\'',
|
||||
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '=',
|
||||
|
||||
// 1
|
||||
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '+',
|
||||
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '\\',
|
||||
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '"',
|
||||
'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '|',
|
||||
|
||||
// 2
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
|
||||
'~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '_',
|
||||
'(', ')', '[', ']', '{', '}', ':', ';', '\'', '"', '\\',
|
||||
',', '.', '/', '=', '<', '>', '?', '|', '+', '\0', '\0'
|
||||
|
||||
};
|
||||
|
||||
private define {
|
||||
SHIFT = -1;
|
||||
BACKSPACE = -2;
|
||||
SPACE = -3;
|
||||
TAB = -4;
|
||||
RETURN = -5;
|
||||
}
|
||||
|
||||
struct keybd {
|
||||
struct tex {
|
||||
title texture;
|
||||
text texture;
|
||||
}
|
||||
fadeio fadeio;
|
||||
fadeout. fadeio;
|
||||
caret_timer delay;
|
||||
cursor_delay repeat;
|
||||
remove_delay repeat;
|
||||
input_lock norepeat;
|
||||
buf string;
|
||||
on_done void;
|
||||
on_close void;
|
||||
arg void;
|
||||
mode int;
|
||||
lock bool;
|
||||
prev_mode int;
|
||||
prev_lock bool;
|
||||
cursor int;
|
||||
prev_cursor int;
|
||||
start_x int;
|
||||
caret_pos int;
|
||||
caret_x int;
|
||||
draw_caret bool;
|
||||
enable_return bool;
|
||||
enable_shift bool;
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
memset(this, 0, sizeof(keybd));
|
||||
constructor(this);
|
||||
}
|
||||
|
||||
func destructor() {
|
||||
destructor(this);
|
||||
}
|
||||
|
||||
module singleton {
|
||||
|
||||
var initd bool = false;
|
||||
|
||||
var ascii(128) texture;
|
||||
var shift texture;
|
||||
var shift_white texture;
|
||||
var backspace texture;
|
||||
var space texture;
|
||||
var tab texture;
|
||||
var ret texture;
|
||||
|
||||
}
|
||||
|
||||
func init(render void) bool {
|
||||
if !singleton::initd {
|
||||
var str(2) char = 0;
|
||||
forvar c int = 1; c < 128; c++ {
|
||||
str[0] = c;
|
||||
singleton::ascii[c]->init(
|
||||
global::uni_font->create_tex(render, &str, 0xff000000));
|
||||
}
|
||||
singleton::shift->init(
|
||||
global::uni_font->create_tex(render, "Shift", 0xff000000));
|
||||
singleton::shift_white->init(
|
||||
global::uni_font->create_tex(render, "Shift", 0xffffffff));
|
||||
singleton::backspace->init(
|
||||
global::uni_font->create_tex(render, "Back", 0xff000000));
|
||||
singleton::space->init(
|
||||
global::uni_font->create_tex(render, "Space", 0xff000000));
|
||||
singleton::tab->init(
|
||||
global::uni_font->create_tex(render, "Tab", 0xff000000));
|
||||
singleton::ret->init(
|
||||
global::uni_font->create_tex(render, "Return", 0xff000000));
|
||||
singleton::initd = true;
|
||||
}
|
||||
var wnd. window = this->get_window();
|
||||
this.fadeio->init(wnd, 300);
|
||||
this.fadeio->set_texture(wnd->screen_capture2());
|
||||
this.caret_timer->init(450);
|
||||
this.cursor_delay->init(300, -65, 4);
|
||||
this.remove_delay->init(300, -42, 7);
|
||||
this.prev_cursor = -1;
|
||||
this.draw_caret = true;
|
||||
this.enable_shift = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
on_done = lambda(text. char, arg void) [
|
||||
|
||||
];
|
||||
on_close = lambda(arg void) [
|
||||
|
||||
];
|
||||
*/
|
||||
inline set_callback(on_done void, on_close void, arg void) {
|
||||
this.on_done = on_done;
|
||||
this.on_close = on_close;
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
inline set_fadeout(fadeout. fadeio) {
|
||||
this.fadeout = fadeout;
|
||||
}
|
||||
|
||||
func set_title(render void, title. char) {
|
||||
this.tex.title->init(
|
||||
global::uni_font->create_tex(render, title, 0xff000000));
|
||||
}
|
||||
|
||||
private inline update_text(render void) {
|
||||
this.tex.text->init(
|
||||
global::uni_font->create_tex(render, this.buf->ptr(), 0xff000000));
|
||||
}
|
||||
|
||||
private define {
|
||||
TEXT_GAP = 10;
|
||||
}
|
||||
|
||||
private func set_caret(pos int) {
|
||||
this.caret_timer->reset();
|
||||
this.caret_pos = pos;
|
||||
var nul. char = this.buf->ptr(this.caret_pos);
|
||||
var tmp char = .nul;
|
||||
.nul = 0;
|
||||
var caret_x int;
|
||||
if global::uni_font->get_size(this.buf->ptr(), &caret_x, null) {
|
||||
if this.caret_x = caret_x {
|
||||
this.caret_x++;
|
||||
else
|
||||
this.caret_x--;
|
||||
}
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
if this.tex.text->get_width() > (rect.w -= TEXT_GAP) {
|
||||
if this.caret_x < this.start_x {
|
||||
this.start_x = this.caret_x;
|
||||
else
|
||||
if (this.caret_x - this.start_x) > rect.w;
|
||||
this.start_x = this.caret_x - rect.w;
|
||||
}
|
||||
else
|
||||
this.start_x = 0;
|
||||
}
|
||||
else
|
||||
this.start_x = 0;
|
||||
this.caret_x = 0;
|
||||
}
|
||||
.nul = tmp;
|
||||
this.draw_caret = true;
|
||||
}
|
||||
|
||||
func set_text(render void, text. char) {
|
||||
this.buf->set(text);
|
||||
this->update_text(render);
|
||||
this.start_x = 0;
|
||||
this->set_caret(this.buf->len());
|
||||
}
|
||||
|
||||
inline get_text() .char {
|
||||
return this.buf->ptr();
|
||||
}
|
||||
|
||||
private func insert_char(render void, c char) {
|
||||
var buf(2) char;
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
this.buf->insert(this.caret_pos, &buf);
|
||||
this->update_text(render);
|
||||
this->set_caret(this.caret_pos + 1);
|
||||
}
|
||||
|
||||
private func insert(render void, str. char) {
|
||||
this.buf->insert(this.caret_pos, str);
|
||||
this->update_text(render);
|
||||
this->set_caret(this.caret_pos + strlen(str));
|
||||
}
|
||||
|
||||
private func remove(render void) bool {
|
||||
var tail int;
|
||||
var len int = utf8len_s(this.buf->ptr(), this.caret_pos, &tail);
|
||||
if len == -1;
|
||||
return false;
|
||||
if tail {
|
||||
if this.buf->remove(this.caret_pos - tail, tail) {
|
||||
this->update_text(render);
|
||||
this->set_caret(this.caret_pos - tail);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private func toggle_shift() {
|
||||
if this.mode == 0 {
|
||||
this.mode = 1;
|
||||
elseif this.mode == 1;
|
||||
if this.lock {
|
||||
this.mode = 0;
|
||||
this.lock = false;
|
||||
else
|
||||
this.lock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func move_caret(left_right bool) bool {
|
||||
if left_right {
|
||||
var tail int;
|
||||
var len int = utf8len_s(this.buf->ptr(), this.caret_pos, &tail);
|
||||
if len == -1;
|
||||
return false;
|
||||
if tail {
|
||||
this->set_caret(this.caret_pos - tail);
|
||||
}
|
||||
else
|
||||
if this.caret_pos >= this.buf->len();
|
||||
return false;
|
||||
var size int = utf8table[uchar(.this.buf->ptr(this.caret_pos))];
|
||||
if (this.caret_pos + size) > this.buf->len();
|
||||
return false;
|
||||
this->set_caret(this.caret_pos + size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func close() {
|
||||
if this.on_close ~= null {
|
||||
proto fn(arg void);
|
||||
fn[this.on_close](this.arg);
|
||||
}
|
||||
if this.fadeout ~= null {
|
||||
this.fadeout->set_texture(this->get_window()->screen_capture2());
|
||||
this.fadeout->reset();
|
||||
}
|
||||
this->quit();
|
||||
}
|
||||
|
||||
private func done() {
|
||||
if this.on_done ~= null {
|
||||
proto fn(text. char, arg void);
|
||||
fn[this.on_done](this.buf->ptr(), this.arg);
|
||||
}
|
||||
this->close();
|
||||
}
|
||||
|
||||
func update(render void) {
|
||||
if this.caret_timer->do() {
|
||||
this.draw_caret = !this.draw_caret;
|
||||
this.caret_timer->undo();
|
||||
}
|
||||
var state. uint8 = SDL_GetKeyboardState(null);
|
||||
if state[CPI_SCANCODE_LEFT] {
|
||||
if this.cursor_delay->do() {
|
||||
if this.cursor < 0 {
|
||||
this.prev_cursor = -1;
|
||||
if this.cursor == SHIFT {
|
||||
this.cursor = TAB;
|
||||
elseif this.cursor == SPACE;
|
||||
this.cursor = SHIFT;
|
||||
elseif this.cursor == RETURN;
|
||||
this.cursor = SPACE;
|
||||
elseif this.cursor == BACKSPACE;
|
||||
if this.enable_return {
|
||||
this.cursor = RETURN;
|
||||
else
|
||||
this.cursor = SPACE;
|
||||
}
|
||||
else
|
||||
this.cursor = BACKSPACE;
|
||||
}
|
||||
else
|
||||
if this.cursor % BUTTON_COL {
|
||||
this.cursor--;
|
||||
else
|
||||
this.cursor = (this.cursor / BUTTON_COL + 1) * BUTTON_COL - 1;
|
||||
}
|
||||
}
|
||||
this.cursor_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_RIGHT];
|
||||
if this.cursor_delay->do() {
|
||||
if this.cursor < 0 {
|
||||
this.prev_cursor = -1;
|
||||
if this.cursor == TAB {
|
||||
this.cursor = SHIFT;
|
||||
elseif this.cursor == SHIFT;
|
||||
this.cursor = SPACE;
|
||||
elseif this.cursor == SPACE;
|
||||
if this.enable_return {
|
||||
this.cursor = RETURN;
|
||||
else
|
||||
this.cursor = BACKSPACE;
|
||||
}
|
||||
elseif this.cursor == RETURN;
|
||||
this.cursor = BACKSPACE;
|
||||
else
|
||||
this.cursor = TAB;
|
||||
}
|
||||
else
|
||||
if this.cursor % BUTTON_COL == BUTTON_COL - 1 {
|
||||
this.cursor = (this.cursor / BUTTON_COL) * BUTTON_COL;
|
||||
else
|
||||
this.cursor++;
|
||||
}
|
||||
}
|
||||
this.cursor_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_UP];
|
||||
if this.cursor_delay->do() {
|
||||
if this.cursor < 0 {
|
||||
if this.prev_cursor < 0 {
|
||||
if this.cursor == TAB {
|
||||
this.cursor = BUTTON_COUNT - BUTTON_COL;
|
||||
elseif this.cursor == SHIFT;
|
||||
this.cursor = BUTTON_COUNT - (BUTTON_COL - 2);
|
||||
elseif this.cursor == SPACE;
|
||||
this.cursor = BUTTON_COUNT - (BUTTON_COL - 4);
|
||||
elseif this.cursor == RETURN;
|
||||
this.cursor = BUTTON_COUNT - (BUTTON_COL - 7);
|
||||
else
|
||||
this.cursor = BUTTON_COUNT - (BUTTON_COL - 9);
|
||||
}
|
||||
else
|
||||
this.cursor = this.prev_cursor;
|
||||
}
|
||||
else
|
||||
if this.cursor - BUTTON_COL > -1;
|
||||
this.cursor -= BUTTON_COL;
|
||||
}
|
||||
this.cursor_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_DOWN];
|
||||
if this.cursor_delay->do() {
|
||||
if this.cursor > -1 {
|
||||
if this.cursor + BUTTON_COL < BUTTON_COUNT {
|
||||
this.cursor += BUTTON_COL;
|
||||
else
|
||||
this.prev_cursor = this.cursor;
|
||||
var col int = this.cursor % BUTTON_COL;
|
||||
if col >= 0 and col <= 1 {
|
||||
this.cursor = TAB;
|
||||
elseif col >= 2 and col <= 3;
|
||||
this.cursor = SHIFT;
|
||||
elseif col >= 4 and col <= 8;
|
||||
this.cursor = SPACE;
|
||||
if this.enable_return {
|
||||
if col >= 7 and col <= 8;
|
||||
this.cursor = RETURN;
|
||||
}
|
||||
else
|
||||
this.cursor = BACKSPACE;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.cursor_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_A];
|
||||
if this.remove_delay->do() {
|
||||
this->remove(render);
|
||||
this.remove_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_LK1];
|
||||
if this.cursor_delay->do() {
|
||||
this->move_caret(true);
|
||||
this.cursor_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_LK5];
|
||||
if this.cursor_delay->do() {
|
||||
this->move_caret(false);
|
||||
this.cursor_delay->undo();
|
||||
}
|
||||
// CPI_SCANCODE_LK2
|
||||
// CPI_SCANCODE_LK4
|
||||
else
|
||||
this.cursor_delay->reset();
|
||||
this.remove_delay->reset();
|
||||
}
|
||||
if state[CPI_SCANCODE_MENU] {
|
||||
if this.input_lock->do() {
|
||||
this->close();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_SELECT];
|
||||
if this.input_lock->do() {
|
||||
if this.mode == 2 {
|
||||
this.mode = this.prev_mode;
|
||||
this.lock = this.prev_lock;
|
||||
this.enable_shift = true;
|
||||
else
|
||||
this.prev_mode = this.mode;
|
||||
this.prev_lock = this.lock;
|
||||
this.mode = 2;
|
||||
this.lock = false;
|
||||
this.enable_shift = false;
|
||||
}
|
||||
}
|
||||
elseif state[CPI_SCANCODE_START];
|
||||
if this.input_lock->do() {
|
||||
this->done();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_B];
|
||||
if this.input_lock->do() {
|
||||
if this.cursor < 0 {
|
||||
if this.cursor == SHIFT {
|
||||
this->toggle_shift();
|
||||
elseif this.cursor == BACKSPACE;
|
||||
this->remove(render);
|
||||
elseif this.cursor == SPACE;
|
||||
this->insert_char(render, ' ');
|
||||
elseif this.cursor == TAB;
|
||||
this->insert_char(render, '\t');
|
||||
elseif this.cursor == RETURN;
|
||||
this->insert_char(render, '\n');
|
||||
}
|
||||
else
|
||||
var pressed char = layout[this.mode, this.cursor];
|
||||
if pressed {
|
||||
if this.mode == 1 {
|
||||
if !this.lock;
|
||||
this.mode = 0;
|
||||
}
|
||||
this->insert_char(render, pressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif state[CPI_SCANCODE_X];
|
||||
if this.input_lock->do() {
|
||||
this->toggle_shift();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_Y];
|
||||
if this.input_lock->do() {
|
||||
this->insert_char(render, ' ');
|
||||
}
|
||||
elseif state[CPI_SCANCODE_SHIFT_SELECT];
|
||||
if this.input_lock->do() {
|
||||
var wnd. window = this->get_window();
|
||||
var browser. scene::file_browser = wnd->new_scene<scene::file_browser>();
|
||||
browser->set_callback(
|
||||
lambda(filename. char, this.keybd) [
|
||||
this->insert(this->get_window()->get_render(), filename);
|
||||
], null, this
|
||||
);
|
||||
browser->set_fadeout(&this.fadeio);
|
||||
if browser->set_dir(wnd->get_render(), "/home/cpi") or
|
||||
browser->set_dir(wnd->get_render(), "/") {
|
||||
browser->set_mode(
|
||||
scene::file_browser::mode.select);
|
||||
wnd->push_scene(this);
|
||||
wnd->set_scene(browser);
|
||||
else
|
||||
wnd->free_scene(browser);
|
||||
}
|
||||
}
|
||||
else
|
||||
this.input_lock->set(false);
|
||||
}
|
||||
}
|
||||
|
||||
private func draw_button(render void, index int, rect. SDL_Rect, tex. texture, custom_color bool = false) {
|
||||
var focus bool = index == this.cursor;
|
||||
if !custom_color {
|
||||
if focus {
|
||||
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
|
||||
else
|
||||
SDL_SetRenderDrawColor(render, 235, 235, 235, 0xff);
|
||||
}
|
||||
}
|
||||
SDL_RenderFillRect(render, rect);
|
||||
if focus {
|
||||
SDL_SetRenderDrawColor(render, 0, 162, 232, 0xff);
|
||||
SDL_RenderDrawRect(render, rect);
|
||||
else
|
||||
SDL_SetRenderDrawColor(render, 127, 127, 127, 0xff);
|
||||
SDL_RenderDrawRect(render, rect);
|
||||
}
|
||||
tex->draw(render,
|
||||
rect.x + (rect.w - tex->get_width()) / 2,
|
||||
rect.y + (rect.h - tex->get_height()) / 2);
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
define {
|
||||
TITLE_X = 10;
|
||||
TITLE_Y = 10;
|
||||
TEXT_Y = 45;
|
||||
KEYBD_Y = 85;
|
||||
}
|
||||
SDL_SetRenderDrawColor(render, 245, 245, 245, 0xff);
|
||||
SDL_RenderClear(render);
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
// title
|
||||
this.tex.title->draw(render, TITLE_X, TITLE_Y);
|
||||
using caret_x int {
|
||||
// text
|
||||
if this.tex.text->get_texture() == null {
|
||||
caret_x = rect.w / 2;
|
||||
else
|
||||
var width int = this.tex.text->get_width();
|
||||
if width > (rect.w - TEXT_GAP) {
|
||||
var x int = (TEXT_GAP / 2);
|
||||
caret_x = x + (this.caret_x - this.start_x);
|
||||
this.tex.text->draw(render, x + -this.start_x, TEXT_Y);
|
||||
else
|
||||
var x int = (rect.w - width) / 2;
|
||||
caret_x = x + this.caret_x;
|
||||
this.tex.text->draw(render, x, TEXT_Y);
|
||||
}
|
||||
}
|
||||
// caret
|
||||
if this.draw_caret {
|
||||
SDL_SetRenderDrawColor(render, 125, 125, 125, 0xff);
|
||||
SDL_RenderDrawLine(render, caret_x, TEXT_Y, caret_x,
|
||||
TEXT_Y + global::uni_font->get_height());
|
||||
}
|
||||
}
|
||||
// keybd
|
||||
var sub_rect SDL_Rect;
|
||||
var x int = (rect.w - ((BUTTON_COL * (BUTTON_WIDTH + BUTTON_GAP)) - BUTTON_GAP)) / 2;
|
||||
var y int = KEYBD_Y;
|
||||
forvar index int = 0; index < BUTTON_COUNT; index++ {
|
||||
sub_rect.x = x + ((index % BUTTON_COL) * (BUTTON_WIDTH + BUTTON_GAP));
|
||||
sub_rect.y = y + ((index / BUTTON_COL) * (BUTTON_HEIGHT + BUTTON_GAP));
|
||||
sub_rect.w = BUTTON_WIDTH;
|
||||
sub_rect.h = BUTTON_HEIGHT;
|
||||
this->draw_button(render, index, &sub_rect,
|
||||
&singleton::ascii[layout[this.mode, index]]);
|
||||
}
|
||||
sub_rect.x = x;
|
||||
sub_rect.y += BUTTON_WIDTH + BUTTON_GAP;
|
||||
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 2) - BUTTON_GAP;
|
||||
sub_rect.h = BUTTON_HEIGHT;
|
||||
this->draw_button(render, TAB, &sub_rect,
|
||||
&singleton::tab);
|
||||
sub_rect.x += sub_rect.w + BUTTON_GAP;
|
||||
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 2) - BUTTON_GAP;
|
||||
sub_rect.h = BUTTON_HEIGHT;
|
||||
{
|
||||
var custom_color bool = false;
|
||||
var tex. texture = &singleton::shift;
|
||||
if this.enable_shift {
|
||||
if this.mode == 1 {
|
||||
if this.lock {
|
||||
tex = &singleton::shift_white;
|
||||
SDL_SetRenderDrawColor(render, 130, 130, 130, 0xff);
|
||||
else
|
||||
SDL_SetRenderDrawColor(render, 205, 205, 205, 0xff);
|
||||
}
|
||||
custom_color = true;
|
||||
}
|
||||
else
|
||||
SDL_SetRenderDrawColor(render, 165, 165, 165, 0xff);
|
||||
custom_color = true;
|
||||
}
|
||||
this->draw_button(render, SHIFT, &sub_rect, tex, custom_color);
|
||||
}
|
||||
SDL_SetRenderDrawColor(render, 205, 205, 205, 0xff);
|
||||
if this.enable_return {
|
||||
sub_rect.x += sub_rect.w + BUTTON_GAP;
|
||||
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 3) - BUTTON_GAP;
|
||||
sub_rect.h = BUTTON_HEIGHT;
|
||||
this->draw_button(render, SPACE, &sub_rect,
|
||||
&singleton::space, true);
|
||||
sub_rect.x += sub_rect.w + BUTTON_GAP;
|
||||
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 2) - BUTTON_GAP;
|
||||
sub_rect.h = BUTTON_HEIGHT;
|
||||
this->draw_button(render, RETURN, &sub_rect,
|
||||
&singleton::ret);
|
||||
else
|
||||
sub_rect.x += sub_rect.w + BUTTON_GAP;
|
||||
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 5) - BUTTON_GAP;
|
||||
sub_rect.h = BUTTON_HEIGHT;
|
||||
this->draw_button(render, SPACE, &sub_rect,
|
||||
&singleton::space, true);
|
||||
}
|
||||
sub_rect.x += sub_rect.w + BUTTON_GAP;
|
||||
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 2) - BUTTON_GAP;
|
||||
sub_rect.h = BUTTON_HEIGHT;
|
||||
this->draw_button(render, BACKSPACE, &sub_rect,
|
||||
&singleton::backspace);
|
||||
this.fadeio->do();
|
||||
}
|
||||
|
||||
func wake() {
|
||||
this.caret_timer->done();
|
||||
this.cursor_delay->reset(false);
|
||||
this.remove_delay->reset(false);
|
||||
this.input_lock->set(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
|
||||
class game+, scene+, main+, status_bar {
|
||||
|
||||
inherit game::control = super;
|
||||
|
||||
private import rt::c, lib::sdl2;
|
||||
|
||||
struct status_bar {
|
||||
long_timer delay;
|
||||
short_timer delay;
|
||||
batt_icon(4) texture;
|
||||
batt_charging_icon texture;
|
||||
batt_cap int;
|
||||
wifi_icon(4) texture;
|
||||
wifi_sig int;
|
||||
colon bool;
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
constructor(this);
|
||||
this.batt_cap = -1;
|
||||
this.wifi_sig = -1;
|
||||
this.colon = true;
|
||||
}
|
||||
|
||||
func destructor() {
|
||||
destructor(this);
|
||||
}
|
||||
|
||||
define {
|
||||
BATT_UNKNOWN = 0;
|
||||
BATT_LOW = 1;
|
||||
BATT_MID = 2;
|
||||
BATT_FULL = 3;
|
||||
}
|
||||
|
||||
define {
|
||||
WIFI_OFF = 0;
|
||||
WIFI_LOW = 1;
|
||||
WIFI_MID = 2;
|
||||
WIFI_HIGH = 3;
|
||||
}
|
||||
|
||||
func init(render void) bool {
|
||||
this.long_timer->init(3000);
|
||||
this.long_timer->done();
|
||||
this.short_timer->init(1000);
|
||||
this.short_timer->done();
|
||||
this.batt_icon[BATT_UNKNOWN]->load_file(render,
|
||||
global::make_path("main/battery.png"));
|
||||
this.batt_icon[BATT_LOW]->load_file(render,
|
||||
global::make_path("main/battery_low.png"));
|
||||
this.batt_icon[BATT_MID]->load_file(render,
|
||||
global::make_path("main/battery_mid.png"));
|
||||
this.batt_icon[BATT_FULL]->load_file(render,
|
||||
global::make_path("main/battery_full.png"));
|
||||
this.batt_charging_icon->load_file(render,
|
||||
global::make_path("main/battery_charging.png"));
|
||||
this.wifi_icon[WIFI_OFF]->load_file(render,
|
||||
global::make_path("main/wifi.png"));
|
||||
this.wifi_icon[WIFI_LOW]->load_file(render,
|
||||
global::make_path("main/wifi_low.png"));
|
||||
this.wifi_icon[WIFI_MID]->load_file(render,
|
||||
global::make_path("main/wifi_mid.png"));
|
||||
this.wifi_icon[WIFI_HIGH]->load_file(render,
|
||||
global::make_path("main/wifi_high.png"));
|
||||
return true;
|
||||
}
|
||||
|
||||
func update(render void) {
|
||||
if this.long_timer->do() {
|
||||
if !global::wifi->is_connected(&this.wifi_sig);
|
||||
this.wifi_sig = -1;
|
||||
this.long_timer->undo();
|
||||
}
|
||||
if this.short_timer->do() {
|
||||
this.batt_cap = global::get_battery_cap();
|
||||
this.colon = !this.colon;
|
||||
this.short_timer->undo();
|
||||
}
|
||||
}
|
||||
|
||||
private func get_batt_icon() .texture {
|
||||
var icon int = BATT_UNKNOWN;
|
||||
if this.batt_cap ~= -1 {
|
||||
var cap int = this.batt_cap & ~0x100;
|
||||
if cap > 65 {
|
||||
icon = BATT_FULL;
|
||||
elseif cap > 20;
|
||||
icon = BATT_MID;
|
||||
elseif cap > 0;
|
||||
icon = BATT_LOW;
|
||||
}
|
||||
}
|
||||
return &this.batt_icon[icon];
|
||||
}
|
||||
|
||||
private func get_wifi_icon() .texture {
|
||||
var icon int;
|
||||
if this.wifi_sig > 60 {
|
||||
icon = WIFI_HIGH;
|
||||
elseif this.wifi_sig > 30;
|
||||
icon = WIFI_MID;
|
||||
elseif this.wifi_sig > 0;
|
||||
icon = WIFI_LOW;
|
||||
else
|
||||
icon = WIFI_OFF;
|
||||
}
|
||||
return &this.wifi_icon[icon];
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
var x int = this->get_right();
|
||||
var y int = this->get_y();
|
||||
using batt_icon. texture = this->get_batt_icon() {
|
||||
if this.batt_cap ~= -1;
|
||||
global::small_font->draw_cap(render, x -= 40, y + 7, this.batt_cap & ~0x100);;
|
||||
batt_icon->draw(render, x -= batt_icon->get_width(), y);
|
||||
if this.batt_cap ~= -1 and
|
||||
this.batt_cap & 0x100;
|
||||
this.batt_charging_icon->draw(render, x, y);
|
||||
}
|
||||
using wifi_icon. texture = this->get_wifi_icon() {
|
||||
wifi_icon->draw(render, x -= wifi_icon->get_width(), y);
|
||||
}
|
||||
global::small_font->draw_time(render,
|
||||
x -= 55, y + 7, time(null), this.colon);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
|
||||
/*
|
||||
set_callback(on_press void, arg void)
|
||||
add_menu(render void, id int, title. char, icon_filename. char) bool
|
||||
set_cursor(cursor int)
|
||||
get_selected_menu() .menu
|
||||
*/
|
||||
|
||||
class game+, scene+, main+, sub_menu {
|
||||
|
||||
inherit game::control = super;
|
||||
|
||||
private import rt::c, lib::sdl2;
|
||||
|
||||
class menu {
|
||||
struct menu {
|
||||
icon texture;
|
||||
title texture;
|
||||
id int;
|
||||
}
|
||||
func constructor() {
|
||||
constructor(this); }
|
||||
func destructor() {
|
||||
destructor(this); }
|
||||
}
|
||||
|
||||
struct sub_menu {
|
||||
struct tex {
|
||||
button texture;
|
||||
button_hover texture;
|
||||
}
|
||||
menus(MENU_COUNT) menu;
|
||||
menu_count int;
|
||||
input_delay repeat;
|
||||
input_lock norepeat;
|
||||
cursor int;
|
||||
on_press void;
|
||||
arg void;
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
memset(this, 0, sizeof(sub_menu));
|
||||
constructor(this);
|
||||
}
|
||||
|
||||
func destructor() {
|
||||
destructor(this);
|
||||
}
|
||||
|
||||
define {
|
||||
MENU_COUNT = 5;
|
||||
BUTTON_WIDTH = 40;
|
||||
BUTTON_HEIGHT = 40;
|
||||
BUTTON_GAP = 10;
|
||||
}
|
||||
|
||||
func init(render void) bool {
|
||||
this.tex.button->load_file(render,
|
||||
global::make_path("main/button_40x40.png"));
|
||||
this.tex.button_hover->load_file(render,
|
||||
global::make_path("main/button_hover_40x40.png"));
|
||||
this.input_delay->init(300, -10, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline set_callback(on_press void, arg void) {
|
||||
this.on_press = on_press;
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
func add_menu(render void, id int, title. char, icon_filename. char) bool {
|
||||
if this.menu_count >= MENU_COUNT;
|
||||
return false;
|
||||
this.menus[this.menu_count].icon->load_file(render, icon_filename);
|
||||
this.menus[this.menu_count].title->init(
|
||||
global::uni_font->create_tex(render, title, 0xff000000));
|
||||
this.menus[this.menu_count].id = id;
|
||||
this.menu_count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
func update(render void) {
|
||||
if this->has_focus() {
|
||||
var state. uint8 = SDL_GetKeyboardState(null);
|
||||
if state[CPI_SCANCODE_LEFT] {
|
||||
if this.input_delay->do() {
|
||||
if this.cursor;
|
||||
this.cursor--;
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_RIGHT];
|
||||
if this.input_delay->do() {
|
||||
if this.cursor < MENU_COUNT - 1;
|
||||
this.cursor++;
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_UP];
|
||||
var parent. scene::main = this->get_parent();
|
||||
var cursor int = this.cursor;
|
||||
#if MENU_COUNT > tile_menu::TILE_HALF_COUNT;
|
||||
cursor /= (MENU_COUNT / tile_menu::TILE_HALF_COUNT);
|
||||
#else
|
||||
cursor += (tile_menu::TILE_HALF_COUNT - MENU_COUNT) / 2;
|
||||
#endif
|
||||
if (cursor += tile_menu::TILE_HALF_COUNT) >= tile_menu::TILE_COUNT;
|
||||
cursor = tile_menu::TILE_COUNT - 1;
|
||||
var tile_menu. tile_menu = parent.tile_menu;
|
||||
tile_menu->set_cursor(cursor);
|
||||
tile_menu->wake();
|
||||
parent->set_focus(tile_menu);
|
||||
else
|
||||
this.input_delay->reset();
|
||||
}
|
||||
if state[CPI_SCANCODE_B] {
|
||||
if this.input_lock->do() {
|
||||
var menu. menu = this->get_selected_menu();
|
||||
if menu ~= null {
|
||||
proto fn(id int, arg void);
|
||||
fn[this.on_press](menu.id, this.arg);
|
||||
}
|
||||
}
|
||||
else
|
||||
this.input_lock->set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
var focus bool = this->has_focus();
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
var x int = this->get_x() +
|
||||
(this->get_width() - ((BUTTON_WIDTH * MENU_COUNT) + (BUTTON_GAP * (MENU_COUNT - 1)))) / 2;
|
||||
var y int = this->get_y();
|
||||
forvar index int = 0; index < MENU_COUNT; index++ {
|
||||
var menu. menu = &this.menus[index];
|
||||
if focus and this.cursor == index {
|
||||
this.tex.button_hover->draw(render, x, y);
|
||||
// out of bounds
|
||||
menu.title->draw(render,
|
||||
this->get_x() + (rect.w - menu.title->get_width()) / 2,
|
||||
y - (menu.title->get_height() + 4));
|
||||
else
|
||||
this.tex.button->draw(render, x, y);
|
||||
}
|
||||
menu.icon->draw(render, x + 1, y + 1);
|
||||
x += (BUTTON_WIDTH + BUTTON_GAP);
|
||||
}
|
||||
}
|
||||
|
||||
func wake() {
|
||||
this.input_delay->reset(false);
|
||||
this.input_lock->set(true);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
inline set_cursor(cursor int) {
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
inline get_selected_menu() .menu {
|
||||
if this.cursor < this.menu_count;
|
||||
return &this.menus[this.cursor];
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,635 +0,0 @@
|
||||
|
||||
/*
|
||||
reload_page(render void)
|
||||
set_mode(mode. mode)
|
||||
get_mode() mode
|
||||
set_link(filename. char)
|
||||
clear_link()
|
||||
get_page() int
|
||||
set_page(render void, page int)
|
||||
set_cursor(cursor int)
|
||||
get_app(index int) .tile_app
|
||||
get_selected_app() .tile_app
|
||||
*/
|
||||
|
||||
class game+, scene+, main+, tile_menu {
|
||||
|
||||
inherit game::control = super;
|
||||
|
||||
private import rt::c, lib::sdl2;
|
||||
|
||||
private alias
|
||||
string = std::string,
|
||||
strings = std::strings;
|
||||
|
||||
private alias popup_menu = control::popup_menu;
|
||||
|
||||
enum mode {
|
||||
none,
|
||||
move,
|
||||
link
|
||||
}
|
||||
|
||||
class image_cache {
|
||||
private import rt::c;
|
||||
private alias
|
||||
vector = std::vector,
|
||||
string = std::string;
|
||||
struct cache {
|
||||
filename string;
|
||||
tex texture;
|
||||
}
|
||||
struct image_cache {
|
||||
caches vector<cache>;
|
||||
}
|
||||
func constructor() {
|
||||
constructor(this); }
|
||||
func destructor() {
|
||||
destructor(this); }
|
||||
func find(filename. char) .cache {
|
||||
var count size_t = this.caches->count();
|
||||
while count {
|
||||
var cache. cache = this.caches->at(--count);
|
||||
if !strcmp(cache.filename->ptr(), filename) {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
func load_file(render void, filename. char) void {
|
||||
var cache. cache = this->find(filename);
|
||||
if cache == null {
|
||||
cache = this.caches->new();
|
||||
cache.filename->set(filename);
|
||||
if !cache.tex->load_file(render, filename) {
|
||||
this.caches->pop_back();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return cache.tex->get_texture();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fixme
|
||||
*/
|
||||
class tile_app {
|
||||
struct tile_app {
|
||||
struct tex {
|
||||
icon texture;
|
||||
title texture;
|
||||
}
|
||||
icon. char;
|
||||
title. char;
|
||||
cmd. char;
|
||||
slot int;
|
||||
type int;
|
||||
}
|
||||
func constructor() {
|
||||
constructor(this); }
|
||||
func destructor() {
|
||||
destructor(this); }
|
||||
}
|
||||
|
||||
struct tile_menu {
|
||||
struct tex {
|
||||
tile texture;
|
||||
tile_hover texture;
|
||||
// ...
|
||||
move_mode texture;
|
||||
link_mode texture;
|
||||
}
|
||||
input_delay repeat;
|
||||
input_lock norepeat;
|
||||
page int;
|
||||
cursor int;
|
||||
struct slide {
|
||||
delay delay;
|
||||
dir bool;
|
||||
}
|
||||
image_cache image_cache;
|
||||
apps(TILE_COUNT) tile_app;
|
||||
temp_apps(TILE_COUNT) tile_app;
|
||||
moving_icon texture;
|
||||
mode mode;
|
||||
from int;
|
||||
link string;
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
memset(this, 0, sizeof(tile_menu));
|
||||
constructor(this);
|
||||
}
|
||||
|
||||
func destructor() {
|
||||
destructor(this);
|
||||
}
|
||||
|
||||
define {
|
||||
TILE_COUNT = 10;
|
||||
TILE_HALF_COUNT = TILE_COUNT / 2;
|
||||
TILE_WIDTH = 52;
|
||||
TILE_HEIGHT = 52;
|
||||
TILE_GAP = 10;
|
||||
}
|
||||
|
||||
define {
|
||||
MAX_PAGE = 10;
|
||||
}
|
||||
|
||||
static func free_app(app. tile_app) {
|
||||
app.tex.icon->destroy();
|
||||
app.tex.title->destroy();
|
||||
app.icon = null;
|
||||
app.title = null;
|
||||
app.cmd = null;
|
||||
app.type = -1;
|
||||
}
|
||||
|
||||
func reload_page(render void) {
|
||||
struct args {
|
||||
tile_menu. tile_menu;
|
||||
tile_apps. tile_app;
|
||||
render void;
|
||||
begin int;
|
||||
}
|
||||
var arg args;
|
||||
arg.tile_menu = this;
|
||||
arg.tile_apps = &this.apps;
|
||||
arg.render = render;
|
||||
arg.begin = (this.page - 1) * TILE_COUNT;
|
||||
forvar i int = 0; i < TILE_COUNT; i++ {
|
||||
var app. tile_app = &this.apps[i];
|
||||
this->free_app(app);
|
||||
app.slot = arg.begin + i;
|
||||
}
|
||||
global::apps->for_each(arg.begin, arg.begin + (TILE_COUNT - 1),
|
||||
lambda(app. app_list::app, arg. args) [
|
||||
var tile_menu. tile_menu = arg.tile_menu;
|
||||
var tile_app. tile_app = &arg.tile_apps[app.slot - arg.begin];
|
||||
tile_app.tex.icon->init(
|
||||
tile_menu.image_cache->load_file(arg.render,
|
||||
tile_app.icon = app.icon->ptr()), false);
|
||||
using title void {
|
||||
tile_app.title = app.title->ptr();
|
||||
// deprecated
|
||||
if global::outlined_font {
|
||||
title = global::uni_font->create_outlined_tex(arg.render, tile_app.title,
|
||||
0xffffffff, 0xff000000, 1);
|
||||
else
|
||||
title = global::uni_font->create_tex(arg.render, tile_app.title, 0xff000000);
|
||||
}
|
||||
tile_app.tex.title->init(title);
|
||||
}
|
||||
tile_app.cmd = app.cmd->ptr();
|
||||
tile_app.type = app.type;
|
||||
], &arg
|
||||
);
|
||||
}
|
||||
|
||||
func init(render void) bool {
|
||||
this.tex.tile->load_file(render,
|
||||
global::make_path("main/tile_52x52.png"));
|
||||
this.tex.tile_hover->load_file(render,
|
||||
global::make_path("main/tile_hover_52x52.png"));
|
||||
// ...
|
||||
this.tex.move_mode->init(
|
||||
global::uni_font->create_tex(render, "Move Mode", 0xffffffff));
|
||||
this.tex.link_mode->init(
|
||||
global::uni_font->create_tex(render, "Link Mode", 0xffffffff));
|
||||
this.input_delay->init(300, -25, 10);
|
||||
this.slide.delay->done();
|
||||
this.page = 1;
|
||||
this->reload_page(render);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func exec(cmd. char) {
|
||||
if .cmd == '#' {
|
||||
var strs strings;
|
||||
strs->split(++cmd, "\t");
|
||||
/*
|
||||
#exec dir ext format
|
||||
*/
|
||||
if !strcmp(strs->first_item(), "exec") {
|
||||
if strs->count() > 3 {
|
||||
var wnd. window = this->get_window();
|
||||
var browser. scene::file_browser = wnd->new_scene<scene::file_browser>();
|
||||
browser->set_fadeout(&this->get_parent_t<scene::main>().fadeio);
|
||||
browser->hidden_files(true);
|
||||
browser->set_mode(
|
||||
scene::file_browser::mode.exec);
|
||||
if strlen(strs->item(2));
|
||||
browser->set_ext(strs->item(2));
|
||||
browser->set_exec_format(strs->item(3));
|
||||
mkdir(strs->item(1), 0775);
|
||||
if browser->set_dir(wnd->get_render(), strs->item(1), true) {
|
||||
wnd->push_scene(this->get_parent());
|
||||
wnd->set_scene(browser);
|
||||
else
|
||||
wnd->free_scene(browser);
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif .cmd;
|
||||
exec3(this->get_window(), "Please Wait", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// popup
|
||||
|
||||
private func adjust_popup_pos(popup. popup_menu) {
|
||||
var x int = this->get_x() + TILE_GAP;
|
||||
var y int = this->get_y();
|
||||
if this.cursor < TILE_HALF_COUNT {
|
||||
x += this.cursor * (TILE_WIDTH + TILE_GAP);
|
||||
else
|
||||
x += (this.cursor - TILE_HALF_COUNT) * (TILE_WIDTH + TILE_GAP);
|
||||
y += TILE_HEIGHT + TILE_GAP;
|
||||
}
|
||||
x += TILE_WIDTH;
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
var popup_width int = popup->get_width();
|
||||
var popup_height int = popup->get_height();
|
||||
if (x + popup_width) > rect.w;
|
||||
x -= popup_width + TILE_WIDTH;
|
||||
if (y + popup_height) > rect.h;
|
||||
y = rect.h - popup_height;
|
||||
popup->set_pos(x, y);
|
||||
}
|
||||
|
||||
private func show_edit_popup(render void, app. tile_app) {
|
||||
define {
|
||||
POPUP_WIDTH = 280;
|
||||
POPUP_HEIGHT = 186;
|
||||
}
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
this->close_popup();
|
||||
var popup. edit_popup = this->create_control<edit_popup>(
|
||||
(rect.w - POPUP_WIDTH) / 2,
|
||||
(rect.h - POPUP_HEIGHT) / 2, POPUP_WIDTH, POPUP_HEIGHT);
|
||||
popup->fill_in(render, app);
|
||||
this->set_popup(popup);
|
||||
}
|
||||
|
||||
private func show_popup(render void, app. tile_app) {
|
||||
define {
|
||||
MENU_REMOVE = -1;
|
||||
MENU_EXECUTE = 0;
|
||||
MENU_MOVE = 1;
|
||||
MENU_EDIT = 2;
|
||||
}
|
||||
this->close_popup();
|
||||
var popup. popup_menu = this->create_control<popup_menu>(0, 0);
|
||||
popup->set_callback(
|
||||
lambda(id int, this.tile_menu) [
|
||||
var app. tile_app = this->get_selected_app();
|
||||
if id == MENU_REMOVE {
|
||||
if global::apps->remove(app.slot);
|
||||
this->free_app(app);
|
||||
elseif id == MENU_EXECUTE;
|
||||
if app.cmd ~= null;
|
||||
this->exec(app.cmd);
|
||||
elseif id == MENU_MOVE;
|
||||
var render void = this->get_window()->get_render();
|
||||
this.from = app.slot;
|
||||
this.moving_icon->init(
|
||||
this.image_cache->load_file(render, app.icon), false);
|
||||
this.mode = mode.move;
|
||||
elseif id == MENU_EDIT;
|
||||
this->show_edit_popup(this->get_window()->get_render(), app);
|
||||
}
|
||||
],
|
||||
lambda(this.tile_menu) [
|
||||
this->close_popup();
|
||||
], this);
|
||||
if app.type == -1 {
|
||||
popup->add_menu(render, MENU_EDIT, "Edit");
|
||||
else
|
||||
popup->add_menu(render, MENU_EXECUTE, "Execute");
|
||||
popup->add_menu(render, MENU_MOVE, "Move");
|
||||
if app.type {
|
||||
popup->add_menu(render, MENU_EDIT, "Edit");
|
||||
popup->add_menu(render, MENU_REMOVE, "Remove");
|
||||
}
|
||||
}
|
||||
this->adjust_popup_pos(popup);
|
||||
this->set_popup(popup);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private func try_slide(render void, cursor int, page int, dir bool, delay int = 300) {
|
||||
if this.slide.delay->done?() {
|
||||
this.cursor = cursor;
|
||||
this.page = page;
|
||||
this.temp_apps = this.apps;
|
||||
memset(&this.apps, 0, sizeof(tile_app, TILE_COUNT));
|
||||
this->reload_page(render);
|
||||
this.slide.dir = dir;
|
||||
this.slide.delay->init(delay);
|
||||
this->get_window()->enable_turbo(delay * 2);
|
||||
}
|
||||
}
|
||||
|
||||
func update(render void) {
|
||||
if this->has_focus() {
|
||||
if this->has_popup() {
|
||||
this.super->update(render);
|
||||
else
|
||||
var state. uint8 = SDL_GetKeyboardState(null);
|
||||
if state[CPI_SCANCODE_LEFT] {
|
||||
if this.input_delay->do() {
|
||||
if !this.cursor {
|
||||
if this.page > 1 {
|
||||
this->try_slide(render, TILE_HALF_COUNT - 1, this.page - 1, false);
|
||||
else
|
||||
this->try_slide(render, TILE_HALF_COUNT - 1, MAX_PAGE, false);
|
||||
}
|
||||
elseif this.cursor == TILE_HALF_COUNT;
|
||||
if this.page > 1 {
|
||||
this->try_slide(render, TILE_COUNT - 1, this.page - 1, false);
|
||||
else
|
||||
this->try_slide(render, TILE_COUNT - 1, MAX_PAGE, false);
|
||||
}
|
||||
elseif this.cursor;
|
||||
this.cursor--;
|
||||
}
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_RIGHT];
|
||||
if this.input_delay->do() {
|
||||
if this.cursor == TILE_HALF_COUNT - 1 {
|
||||
if this.page < MAX_PAGE {
|
||||
this->try_slide(render, 0, this.page + 1, true);
|
||||
else
|
||||
this->try_slide(render, 0, 1, true);
|
||||
}
|
||||
elseif this.cursor == TILE_COUNT - 1;
|
||||
if this.page < MAX_PAGE {
|
||||
this->try_slide(render, TILE_HALF_COUNT, this.page + 1, true);
|
||||
else
|
||||
this->try_slide(render, TILE_HALF_COUNT, 1, true);
|
||||
}
|
||||
elseif this.cursor < TILE_COUNT - 1;
|
||||
this.cursor++;
|
||||
}
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_UP];
|
||||
if this.input_delay->do() {
|
||||
if this.cursor >= TILE_HALF_COUNT;
|
||||
this.cursor -= TILE_HALF_COUNT;
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_DOWN];
|
||||
if this.input_delay->do() {
|
||||
if this.cursor < TILE_HALF_COUNT {
|
||||
this.cursor += TILE_HALF_COUNT;
|
||||
elseif this.mode == mode.none;
|
||||
var parent. scene::main = this->get_parent();
|
||||
var cursor int = this.cursor - TILE_HALF_COUNT;
|
||||
#if TILE_HALF_COUNT > sub_menu::MENU_COUNT;
|
||||
cursor /= (TILE_HALF_COUNT / sub_menu::MENU_COUNT);
|
||||
#else
|
||||
cursor += (sub_menu::MENU_COUNT - TILE_HALF_COUNT) / 2;
|
||||
#endif
|
||||
if cursor >= sub_menu::MENU_COUNT;
|
||||
cursor = sub_menu::MENU_COUNT - 1;
|
||||
var sub_menu. sub_menu = parent.sub_menu;
|
||||
sub_menu->set_cursor(cursor);
|
||||
sub_menu->wake();
|
||||
parent->set_focus(sub_menu);
|
||||
}
|
||||
this.input_delay->undo();
|
||||
}
|
||||
else
|
||||
this.input_delay->reset();
|
||||
}
|
||||
if state[CPI_SCANCODE_A] {
|
||||
if this.input_lock->do() {
|
||||
if this.mode == mode.move {
|
||||
this.mode = mode.none;
|
||||
this.moving_icon->destroy();
|
||||
elseif this.mode == mode.link;
|
||||
this.mode = mode.none;
|
||||
this.link->clear();
|
||||
}
|
||||
}
|
||||
elseif state[CPI_SCANCODE_B];
|
||||
if this.input_lock->do() {
|
||||
if this.mode == mode.none {
|
||||
var app. tile_app = this->get_selected_app();
|
||||
if app.cmd ~= null {
|
||||
this->exec(app.cmd);
|
||||
}
|
||||
elseif this.mode == mode.move;
|
||||
var app. tile_app = this->get_selected_app();
|
||||
if app.slot == this.from {
|
||||
this.mode = mode.none;
|
||||
this.moving_icon->destroy();
|
||||
else
|
||||
if app.type {
|
||||
if global::apps->move(this.from, app.slot);
|
||||
this->reload_page(render);
|
||||
this.mode = mode.none;
|
||||
this.moving_icon->destroy();
|
||||
else
|
||||
// system app
|
||||
}
|
||||
}
|
||||
elseif this.mode == mode.link;
|
||||
var app. tile_app = this->get_selected_app();
|
||||
if app.type == -1 {
|
||||
app.cmd = this.link->ptr();
|
||||
this->show_edit_popup(render, app);
|
||||
this.mode = mode.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif state[CPI_SCANCODE_MENU];
|
||||
if this.input_lock->do() {
|
||||
if this.mode == mode.none;
|
||||
this->show_popup(render, this->get_selected_app());
|
||||
}
|
||||
elseif state[CPI_SCANCODE_LK1];
|
||||
if this.input_lock->do() {
|
||||
if this.page > 1 {
|
||||
this->try_slide(render, this.cursor, this.page - 1, false);
|
||||
else
|
||||
this->try_slide(render, this.cursor, MAX_PAGE, false);
|
||||
}
|
||||
}
|
||||
elseif state[CPI_SCANCODE_LK5];
|
||||
if this.input_lock->do() {
|
||||
if this.page < MAX_PAGE {
|
||||
this->try_slide(render, this.cursor, this.page + 1, true);
|
||||
else
|
||||
this->try_slide(render, this.cursor, 1, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
this.input_lock->set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func draw_icon(render void, icon. texture, rect. SDL_Rect) {
|
||||
var width int = icon->get_width();
|
||||
var height int = icon->get_height();
|
||||
if width > rect.w;
|
||||
width = rect.w;
|
||||
if height > rect.h;
|
||||
height = rect.h;
|
||||
icon->draw3(render,
|
||||
rect.x + (rect.w - width) / 2,
|
||||
rect.y + (rect.h - height) / 2, width, height);
|
||||
}
|
||||
|
||||
private func draw_tiles(render void, x int, y int, start int, end int) {
|
||||
var rect SDL_Rect;
|
||||
rect.y = y + 1;
|
||||
rect.w = TILE_WIDTH - 2;
|
||||
rect.h = TILE_HEIGHT - 2;
|
||||
forvar index int = start; index < end; index++ {
|
||||
var app. tile_app = &this.apps[index];
|
||||
rect.x = x + 1;
|
||||
if this->has_focus() and this.cursor == index {
|
||||
this.tex.tile_hover->draw(render, x, y);
|
||||
if this.moving_icon->get_texture() == null {
|
||||
this->draw_icon(render, &app.tex.icon, &rect);
|
||||
else
|
||||
this->draw_icon(render, &this.moving_icon, &rect);
|
||||
}
|
||||
// out of bounds
|
||||
app.tex.title->draw(render,
|
||||
this->get_x() + (this->get_width() - app.tex.title->get_width()) / 2,
|
||||
this->get_bottom() + 5);
|
||||
else
|
||||
this.tex.tile->draw(render, x, y);
|
||||
this->draw_icon(render,
|
||||
&app.tex.icon, &rect);
|
||||
}
|
||||
x += (TILE_GAP + TILE_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
private func draw_temp_tiles(render void, x int, y int, start int, end int) {
|
||||
var rect SDL_Rect;
|
||||
rect.y = y + 1;
|
||||
rect.w = TILE_WIDTH - 2;
|
||||
rect.h = TILE_HEIGHT - 2;
|
||||
forvar index int = start; index < end; index++ {
|
||||
this.tex.tile->draw(render, x, y);
|
||||
rect.x = x + 1;
|
||||
this->draw_icon(render, &this.temp_apps[index].tex.icon, &rect);
|
||||
x += (TILE_GAP + TILE_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
private func slide(render void) int {
|
||||
if this.slide.delay->do() {
|
||||
forvar index int = 0; index < TILE_COUNT; index++;
|
||||
this->free_app(&this.temp_apps[index]);
|
||||
return 0;
|
||||
}
|
||||
var delta int = this.slide.delay->get_per_r<int>(this->get_width());
|
||||
if this.slide.dir {
|
||||
this->draw_temp_tiles(render,
|
||||
this->get_x() - delta + TILE_GAP,
|
||||
this->get_y(), 0, TILE_HALF_COUNT);
|
||||
this->draw_temp_tiles(render,
|
||||
this->get_x() - delta + TILE_GAP,
|
||||
this->get_y() + (TILE_GAP + TILE_HEIGHT), TILE_HALF_COUNT, TILE_COUNT);
|
||||
return this->get_width() - delta;
|
||||
else
|
||||
this->draw_temp_tiles(render,
|
||||
this->get_x() + delta + TILE_GAP,
|
||||
this->get_y(), 0, TILE_HALF_COUNT);
|
||||
this->draw_temp_tiles(render,
|
||||
this->get_x() + delta + TILE_GAP,
|
||||
this->get_y() + (TILE_GAP + TILE_HEIGHT), TILE_HALF_COUNT, TILE_COUNT);
|
||||
return -(this->get_width() - delta);
|
||||
}
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
var delta int = this->slide(render);
|
||||
this->draw_tiles(render,
|
||||
this->get_x() + TILE_GAP + delta,
|
||||
this->get_y(), 0, TILE_HALF_COUNT);
|
||||
this->draw_tiles(render,
|
||||
this->get_x() + TILE_GAP + delta,
|
||||
this->get_y() + (TILE_GAP + TILE_HEIGHT), TILE_HALF_COUNT, TILE_COUNT);
|
||||
this.super->draw(render);
|
||||
// out of bounds
|
||||
if this.mode ~= mode.none {
|
||||
define {
|
||||
PADDING = 3;
|
||||
}
|
||||
var tex. texture;
|
||||
if this.mode == mode.move {
|
||||
tex = &this.tex.move_mode;
|
||||
elseif this.mode == mode.link;
|
||||
tex = &this.tex.link_mode;
|
||||
}
|
||||
var rect SDL_Rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.w = tex->get_width() + (PADDING * 2);
|
||||
rect.h = tex->get_height() + (PADDING * 2);
|
||||
SDL_SetRenderDrawColor(render, 52, 152, 219, 0xff);
|
||||
SDL_RenderFillRect(render, &rect);
|
||||
tex->draw(render, PADDING, PADDING);
|
||||
}
|
||||
}
|
||||
|
||||
func wake() {
|
||||
this.input_delay->reset(false);
|
||||
this.input_lock->set(true);
|
||||
this.super->wake();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
inline set_mode(mode. mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
inline get_mode() mode {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
inline set_link(filename. char) {
|
||||
this.link->set(filename);
|
||||
}
|
||||
|
||||
inline clear_link() {
|
||||
this.link->clear();
|
||||
}
|
||||
|
||||
inline get_page() int {
|
||||
return this.page;
|
||||
}
|
||||
|
||||
inline set_page(render void, page int) {
|
||||
this.page = page;
|
||||
this->reload_page(render);
|
||||
}
|
||||
|
||||
inline set_cursor(cursor int) {
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
inline get_app(index int) .tile_app {
|
||||
return &this.apps[index];
|
||||
}
|
||||
|
||||
inline get_selected_app() .tile_app {
|
||||
return this->get_app(this.cursor);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
|
||||
class game+, scene+, main+ {
|
||||
|
||||
inherit game::scene = super;
|
||||
|
||||
private import rt::c, lib::sdl2;
|
||||
|
||||
private alias vector = std::vector;
|
||||
|
||||
struct main {
|
||||
struct tex {
|
||||
background texture;
|
||||
}
|
||||
fadeio fadeio;
|
||||
input_lock norepeat;
|
||||
status_bar. status_bar;
|
||||
tile_menu. tile_menu;
|
||||
sub_menu. sub_menu;
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
constructor(this);
|
||||
}
|
||||
|
||||
func destructor() {
|
||||
destructor(this);
|
||||
}
|
||||
|
||||
private func standby() bool {
|
||||
var level byte = global::get_backlight_level();
|
||||
if level == -1;
|
||||
return false;
|
||||
if !global::set_backlight_level(0);
|
||||
return false;
|
||||
lambda signal(pids. vector<int>, sig int) [
|
||||
var count size_t = pids->count();
|
||||
while count {
|
||||
var pid int = .pids->at(--count);
|
||||
if pid ~= -1;
|
||||
kill(pid, sig);
|
||||
}
|
||||
];
|
||||
var pids vector<int>;
|
||||
pids->push_back(find_pid_by_cmdline("/home/cpi/launcher/sys.py/gsnotify/gsnotify-arm"));
|
||||
signal(&pids, SIGTSTP);
|
||||
for ;; {
|
||||
var event SDL_Event;
|
||||
while SDL_PollEvent(&event) {
|
||||
if event.type == SDL_KEYDOWN {
|
||||
break 2;
|
||||
elseif event.type == SDL_QUIT;
|
||||
this->get_window()->quit();
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
sleep(3);
|
||||
}
|
||||
signal(&pids, SIGCONT);
|
||||
forvar attempt int = 0; attempt < 3; attempt++ {
|
||||
if global::set_backlight_level(level);
|
||||
break;
|
||||
sleep(1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func init(render void) bool {
|
||||
var wnd. window = this->get_window();
|
||||
var rect SDL_Rect = 0;
|
||||
wnd->get_size(&rect.w, &rect.h);
|
||||
this.tex.background->load_file(render,
|
||||
global::make_path("main/background.png"));
|
||||
this.fadeio->init(wnd, 300);
|
||||
this.fadeio->set_texture(wnd->screen_capture2());
|
||||
// 1st
|
||||
this.tile_menu = this->new_control<tile_menu>(0, 36, rect.w, 114);
|
||||
define {
|
||||
MENU_NONE = 1;
|
||||
MENU_BROWSER = 2;
|
||||
MENU_STANDBY = 3;
|
||||
MENU_QUIT = 4;
|
||||
}
|
||||
// 2nd
|
||||
this.sub_menu = this->new_control<sub_menu>(0, 176, rect.w, 40);
|
||||
this.sub_menu->set_callback(
|
||||
lambda(id int, this.main) [
|
||||
if id == MENU_BROWSER {
|
||||
var wnd. window = this->get_window();
|
||||
var browser. scene::file_browser = wnd->new_scene<scene::file_browser>();
|
||||
browser->set_fadeout(&this.fadeio);
|
||||
browser->set_mode(
|
||||
scene::file_browser::mode.browse);
|
||||
var cwd(0x800) char;
|
||||
if getcwd(&cwd, sizeof(cwd)) ~= null and browser->set_dir(wnd->get_render(), &cwd) {
|
||||
wnd->push_scene(this);
|
||||
wnd->set_scene(browser);
|
||||
else
|
||||
wnd->free_scene(browser);
|
||||
}
|
||||
elseif id == MENU_STANDBY;
|
||||
this->standby();
|
||||
elseif id == MENU_QUIT;
|
||||
this->get_window()->quit();
|
||||
}
|
||||
], this
|
||||
);
|
||||
this.sub_menu->add_menu(render, MENU_BROWSER, "File Browser",
|
||||
global::make_path("main/browser.png"));
|
||||
this.sub_menu->add_menu(render, MENU_STANDBY, "Standby",
|
||||
global::make_path("main/standby.png"));
|
||||
this.sub_menu->add_menu(render, MENU_QUIT, "Quit",
|
||||
global::make_path("main/quit.png"));
|
||||
// 3rd
|
||||
this.status_bar = this->new_control<status_bar>(8, 4, rect.w - 16, 26);
|
||||
this->set_focus(this.tile_menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
func update(render void) {
|
||||
this.super->update(render);
|
||||
var state. uint8 = SDL_GetKeyboardState(null);
|
||||
if state[CPI_SCANCODE_SELECT] {
|
||||
/*
|
||||
if this.input_lock->do() {
|
||||
var cwd(0x800) char;
|
||||
if getcwd(&cwd, sizeof(cwd)) ~= null {
|
||||
var filename std::string;
|
||||
filename->format("%s/bean", &cwd);
|
||||
execl( filename->ptr(),
|
||||
filename->ptr(), null);
|
||||
}
|
||||
}
|
||||
*/
|
||||
else
|
||||
this.input_lock->set(false);
|
||||
}
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
if this.tex.background->get_texture() == null {
|
||||
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
|
||||
SDL_RenderClear(render);
|
||||
else
|
||||
this.tex.background->draw(render, 0, 0);
|
||||
}
|
||||
var rect SDL_Rect = 0;
|
||||
this->get_window()->get_size(&rect.w, &rect.h);
|
||||
// ...
|
||||
global::small_font->draw_page(render, 8, rect.h - 18,
|
||||
this.tile_menu->get_page(), tile_menu::MAX_PAGE);
|
||||
this.super->draw(render);
|
||||
this.fadeio->do();
|
||||
}
|
||||
|
||||
func wake() {
|
||||
this.input_lock->set(true);
|
||||
this.super->wake();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
|
||||
/*
|
||||
fill_in(render void, app. tile_app)
|
||||
*/
|
||||
|
||||
class game+, scene+, main+, edit_popup {
|
||||
|
||||
inherit game::control = super;
|
||||
|
||||
private import rt::c, lib::sdl2;
|
||||
|
||||
private alias string = std::string;
|
||||
|
||||
private alias
|
||||
button = control::button,
|
||||
edit = control::edit,
|
||||
image_button = control::image_button,
|
||||
label = control::label;
|
||||
|
||||
private alias tile_app = tile_menu::tile_app;
|
||||
|
||||
struct edit_popup {
|
||||
input_delay repeat;
|
||||
input_lock norepeat;
|
||||
new_icon string;
|
||||
focus_map focus_map;
|
||||
app. tile_app;
|
||||
label_title. label;
|
||||
label_cmd. label;
|
||||
label_icon. label;
|
||||
edit_title. edit;
|
||||
edit_cmd. edit;
|
||||
button_icon. image_button;
|
||||
button_cancel. button;
|
||||
button_save. button;
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
constructor(this);
|
||||
}
|
||||
|
||||
func destructor() {
|
||||
destructor(this);
|
||||
}
|
||||
|
||||
func init(render void) bool {
|
||||
this.input_delay->init(300, -10, 20);
|
||||
var rect SDL_Rect = this->get_rect();
|
||||
var y int = 10;
|
||||
this.label_title = this->new_control<label>(10, y);
|
||||
this.label_title->set_text(render, "Title");
|
||||
this.edit_title = this->new_control<edit>(
|
||||
10, y += (this.label_title->get_height() + 3), rect.w - 20, 25);
|
||||
this.label_cmd = this->new_control<label>(
|
||||
10, y += (this.edit_title->get_height() + 3));
|
||||
this.label_cmd->set_text(render, "CommandLine");
|
||||
this.edit_cmd = this->new_control<edit>(
|
||||
10, y += (this.label_cmd->get_height() + 3), rect.w - 20, 25);
|
||||
this.label_icon = this->new_control<label>(
|
||||
10, y += (this.edit_cmd->get_height() + 3));
|
||||
this.label_icon->set_text(render, "Icon");
|
||||
this.button_icon = this->new_control<image_button>(
|
||||
10, y += (this.label_icon->get_height() + 3));
|
||||
this.button_icon->set_normal_image(render,
|
||||
global::make_path("main/tile_52x52.png"));
|
||||
this.button_icon->set_hover_image(render,
|
||||
global::make_path("main/tile_hover_52x52.png"));
|
||||
this.button_icon->set_outline_size(1);
|
||||
define {
|
||||
BUTTON_WIDTH = 70;
|
||||
BUTTON_HEIGHT = 30;
|
||||
}
|
||||
this.button_cancel = this->new_control<button>(
|
||||
rect.w - ((BUTTON_WIDTH * 2) + 16),
|
||||
rect.h - (BUTTON_HEIGHT + 10), BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
this.button_cancel->set_text(render, "Cancel");
|
||||
this.button_save = this->new_control<button>(
|
||||
rect.w - (BUTTON_WIDTH + 10),
|
||||
rect.h - (BUTTON_HEIGHT + 10), BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
this.button_save->set_text(render, "Save");
|
||||
this.focus_map->register(this.edit_title, null, this.edit_cmd, null, null);
|
||||
this.focus_map->register(this.edit_cmd, this.edit_title, this.button_icon, null, null);
|
||||
this.focus_map->register(this.button_icon, this.edit_cmd, null, null, this.button_cancel);
|
||||
this.focus_map->register(this.button_cancel, this.edit_cmd, null, this.button_icon, this.button_save);
|
||||
this.focus_map->register(this.button_save, this.edit_cmd, null, this.button_cancel, null);
|
||||
this->set_focus(this.edit_title);
|
||||
return true;
|
||||
}
|
||||
|
||||
func fill_in(render void, app. tile_app) {
|
||||
this.app = app;
|
||||
if app.title ~= null;
|
||||
this.edit_title->set_text(render, app.title);
|
||||
if app.cmd ~= null;
|
||||
this.edit_cmd->set_text(render, app.cmd);
|
||||
if app.icon ~= null;
|
||||
this.button_icon->set_image(render, app.icon);
|
||||
}
|
||||
|
||||
private func show_keybd(render void, title. char, edit. edit) {
|
||||
var wnd. window = this->get_window();
|
||||
var keybd. scene::keybd = wnd->new_scene<scene::keybd>();
|
||||
keybd->set_callback(edit->get_keybd_cb(), null, edit);
|
||||
keybd->set_fadeout(&this->get_parent_t<scene::main>().fadeio);
|
||||
keybd->set_title(render, title);
|
||||
keybd->set_text(render, edit->get_text());
|
||||
wnd->push_scene(this->get_parent());
|
||||
wnd->set_scene(keybd);
|
||||
}
|
||||
|
||||
private func close() {
|
||||
var parent. tile_menu = this->get_parent_control();
|
||||
parent->clear_link();
|
||||
parent->close_popup();
|
||||
}
|
||||
|
||||
func update(render void) {
|
||||
var state. uint8 = SDL_GetKeyboardState(null);
|
||||
if state[CPI_SCANCODE_UP] {
|
||||
if this.input_delay->do() {
|
||||
var focus void = this.focus_map->get(this->get_focus(), CPI_SCANCODE_UP);
|
||||
if focus ~= null;
|
||||
this->set_focus(focus);
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_DOWN];
|
||||
if this.input_delay->do() {
|
||||
var focus void = this.focus_map->get(this->get_focus(), CPI_SCANCODE_DOWN);
|
||||
if focus ~= null;
|
||||
this->set_focus(focus);
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_LEFT];
|
||||
if this.input_delay->do() {
|
||||
var focus void = this.focus_map->get(this->get_focus(), CPI_SCANCODE_LEFT);
|
||||
if focus ~= null;
|
||||
this->set_focus(focus);
|
||||
this.input_delay->undo();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_RIGHT];
|
||||
if this.input_delay->do() {
|
||||
var focus void = this.focus_map->get(this->get_focus(), CPI_SCANCODE_RIGHT);
|
||||
if focus ~= null;
|
||||
this->set_focus(focus);
|
||||
this.input_delay->undo();
|
||||
}
|
||||
else
|
||||
this.input_delay->reset();
|
||||
}
|
||||
if state[CPI_SCANCODE_A] or
|
||||
state[CPI_SCANCODE_MENU] {
|
||||
if this.input_lock->do() {
|
||||
this->close();
|
||||
}
|
||||
elseif state[CPI_SCANCODE_B];
|
||||
if this.input_lock->do() {
|
||||
var focus void = this->get_focus();
|
||||
if focus == this.edit_title {
|
||||
this->show_keybd(render, "Title", this.edit_title);
|
||||
elseif focus == this.edit_cmd;
|
||||
this->show_keybd(render, "CommandLine", this.edit_cmd);
|
||||
elseif focus == this.button_icon;
|
||||
var wnd. window = this->get_window();
|
||||
var browser. scene::file_browser = wnd->new_scene<scene::file_browser>();
|
||||
browser->set_callback(
|
||||
lambda(filename. char, this.edit_popup) [
|
||||
var render void = this->get_window()->get_render();
|
||||
if this.button_icon->set_image(render, filename) {
|
||||
this.new_icon->set(filename);
|
||||
else
|
||||
var app. tile_app = this.app;
|
||||
this.button_icon->set_image(render, app.icon);
|
||||
this.new_icon->clear();
|
||||
}
|
||||
], null, this
|
||||
);
|
||||
browser->set_fadeout(&this->get_parent_t<scene::main>().fadeio);
|
||||
browser->set_mode(
|
||||
scene::file_browser::mode.select_image);
|
||||
var path string;
|
||||
var cwd(0x800) char;
|
||||
if getcwd(&cwd, sizeof(cwd)) ~= null and
|
||||
browser->set_dir(wnd->get_render(), path->format("%s/icons", &cwd)) or
|
||||
browser->set_dir(wnd->get_render(), &cwd) {
|
||||
wnd->push_scene(this->get_parent());
|
||||
wnd->set_scene(browser);
|
||||
else
|
||||
wnd->free_scene(browser);
|
||||
}
|
||||
elseif focus == this.button_cancel;
|
||||
this->close();
|
||||
elseif focus == this.button_save;
|
||||
var tile_app. tile_app = this.app;
|
||||
var new_icon. char;
|
||||
if this.new_icon->empty() {
|
||||
new_icon = tile_app.icon;
|
||||
else
|
||||
new_icon = this.new_icon->ptr();
|
||||
}
|
||||
if tile_app.type == -1 {
|
||||
global::apps->insert(tile_app.slot, 1,
|
||||
this.edit_title->get_text(),
|
||||
this.edit_cmd->get_text(), new_icon);
|
||||
else
|
||||
global::apps->update(tile_app.slot, tile_app.type,
|
||||
this.edit_title->get_text(),
|
||||
this.edit_cmd->get_text(), new_icon);
|
||||
}
|
||||
var parent. tile_menu = this->get_parent_control();
|
||||
parent->reload_page(render);
|
||||
this->close();
|
||||
}
|
||||
}
|
||||
else
|
||||
this.input_lock->set(false);
|
||||
}
|
||||
this.super->update(render);
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
var rect SDL_Rect = this->get_rect();
|
||||
SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(render, 245, 245, 245, 230);
|
||||
SDL_RenderFillRect(render, &rect);
|
||||
SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(render, 0xcd, 0xcd, 0xcd, 0xff);
|
||||
SDL_RenderDrawRect(render, &rect);
|
||||
this.super->draw(render);
|
||||
}
|
||||
|
||||
func wake() {
|
||||
this.input_delay->reset(false);
|
||||
this.input_lock->set(true);
|
||||
this.super->wake();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
// template
|
||||
|
||||
class game+, scene+, temp {
|
||||
|
||||
inherit game::scene = super;
|
||||
|
||||
private import lib::sdl2;
|
||||
|
||||
struct temp {
|
||||
|
||||
}
|
||||
|
||||
func constructor() {
|
||||
constructor(this);
|
||||
}
|
||||
|
||||
func destructor() {
|
||||
destructor(this);
|
||||
}
|
||||
|
||||
func init(render void) bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
func update(render void) {
|
||||
this.super->update(render);
|
||||
}
|
||||
|
||||
func draw(render void) {
|
||||
SDL_SetRenderDrawColor(render, 0, 0, 0, 0xff);
|
||||
SDL_RenderClear(render);
|
||||
this.super->draw(render);
|
||||
}
|
||||
|
||||
func wake() {
|
||||
this.super->wake();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user