mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v042 release.
A new release quite a bit faster than I was expecting, but a lot has changed. Most importantly is a new Windows input driver, "RawInput". The downside is that this makes bsnes require at least Windows XP, as Windows 2000 and earlier lack RawInput support. The upside is that input from multiple keyboards and mice can be distinguished from each other — very useful for dual-Justifier support in Lethal Enforcers. Users of previous versions of bsnes will need to manually select the new driver via Settings->Configuration->Advanced->Input driver, and will need to re-map all assigned input keys, including the default user interface hotkeys. Or alternatively, delete the configuration file under %APPDATA%\.bsnes or ~/.bsnes. Also new is an XInput driver, which avoids the DirectInput driver limitation of being unable to distinguish the two shoulder trigger buttons. This makes bsnes require DirectX 9.0c or later for the necessary drivers. Note that Windows Vista SP0 does not ship with these, so if you haven't installed it yet, you'll need to do so. This driver is part of the "RawInput" driver mentioned above. This part is important: if you receive an error regarding xinput1_3.dll, you need to download and install the DirectX 9.0c run-time. For those on Windows 2000, or without DirectX 9.0c, it is still possible to compile and run bsnes with the older DirectInput driver only; but I won't be providing a binary myself for this — at least not at this time. More bad news for some: hiro, my Win32 / GTK+ API wrapper, has been discontinued and removed from the source tree for this release. Qt 4.5.0+ is now required for the user interface. Very sorry to the Linux distros that do not have packages for QT 4.5 yet. You'll need to continue with v041 for now.
This commit is contained in:
parent
2b587de04b
commit
b5b21a4ec2
18
src/Makefile
18
src/Makefile
|
@ -17,8 +17,9 @@ ifneq ($(findstring gcc,$(compiler)),) # GCC family
|
|||
link = -s
|
||||
mkbin = -o$1
|
||||
mkdef = -D$1
|
||||
mkinc = -I$1
|
||||
mkincpath = -I$1
|
||||
mklib = -l$1
|
||||
mklibpath = -L$1
|
||||
|
||||
# profile-guided optimization:
|
||||
# flags += -fprofile-generate
|
||||
|
@ -34,8 +35,9 @@ else ifeq ($(compiler),cl) # Visual C++
|
|||
link = /link
|
||||
mkbin = /Fe$1
|
||||
mkdef = /D$1
|
||||
mkinc = /I$1
|
||||
mkincpath = /I$1
|
||||
mklib = $1.lib
|
||||
mklibpath = /L$1
|
||||
else
|
||||
unknown_compiler: help;
|
||||
endif
|
||||
|
@ -48,10 +50,13 @@ ifeq ($(platform),x) # X11
|
|||
ruby = video.glx video.xv video.sdl audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao input.sdl input.x
|
||||
delete = rm -f $1
|
||||
else ifeq ($(platform),win) # Windows
|
||||
# enable static linking to Qt for Windows build
|
||||
mingw_link_flags = -mwindows -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
mingw_link_flags = -mwindows
|
||||
# mingw_links_flags = -mconsole
|
||||
|
||||
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.directinput
|
||||
# enable static linking to Qt for Windows build
|
||||
mingw_link_flags += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
|
||||
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.rawinput input.directinput
|
||||
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
|
||||
link += $(if $(findstring mingw,$(compiler)),$(mingw_link_flags))
|
||||
link += $(call mklib,uuid)
|
||||
|
@ -68,6 +73,7 @@ endif
|
|||
############
|
||||
|
||||
rubyflags = $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
|
||||
link += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`)
|
||||
|
||||
link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9))
|
||||
link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw))
|
||||
|
@ -80,7 +86,7 @@ link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound))
|
|||
link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32)))
|
||||
link += $(if $(findstring audio.pulseaudio,$(ruby)),$(call mklib,pulse-simple))
|
||||
link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid))
|
||||
link += $(if $(findstring input.sdl,$(ruby)),`sdl-config --libs`)
|
||||
link += $(if $(findstring input.rawinput,$(ruby)),$(call mklib,xinput) $(call mklib,dinput8) $(call mklib,dxguid))
|
||||
|
||||
####################
|
||||
### core objects ###
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define BSNES_VERSION "0.041"
|
||||
#define BSNES_VERSION "0.042"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define BUSCORE sBus
|
||||
|
|
|
@ -118,7 +118,7 @@ bool Cartridge::load_bsx(const char *base, const char *slot) {
|
|||
delete[] data;
|
||||
}
|
||||
|
||||
if(load_image(slot, data, size, patch_applied)) {
|
||||
if(load_image(slot, data, size, patch_applied) == true) {
|
||||
set(bsx_flash_loaded, true);
|
||||
if(patch_applied) set(patched, true);
|
||||
bs.ram = data;
|
||||
|
@ -157,7 +157,7 @@ bool Cartridge::load_sufami_turbo(const char *base, const char *slotA, const cha
|
|||
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
|
||||
set_cartinfo(cartinfo);
|
||||
|
||||
if(load_image(slotA, data, size, patch_applied)) {
|
||||
if(load_image(slotA, data, size, patch_applied) == true) {
|
||||
if(patch_applied) set(patched, true);
|
||||
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
|
||||
memcpy(stA.rom, data, min(size, stA.rom_size));
|
||||
|
@ -166,7 +166,7 @@ bool Cartridge::load_sufami_turbo(const char *base, const char *slotA, const cha
|
|||
load_ram(get_filename(slotA, "srm", snes.config.path.save), stA.ram, stA.ram_size = 0x020000, 0xff);
|
||||
}
|
||||
|
||||
if(load_image(slotB, data, size, patch_applied)) {
|
||||
if(load_image(slotB, data, size, patch_applied) == true) {
|
||||
if(patch_applied) set(patched, true);
|
||||
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
|
||||
memcpy(stB.rom, data, min(size, stB.rom_size));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
@mingw32-make platform=win compiler=mingw32-gcc
|
||||
::@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
||||
::@mingw32-make platform=win compiler=mingw32-gcc
|
||||
@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
||||
@pause
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
void power();
|
||||
void reset();
|
||||
|
||||
unsigned size();
|
||||
unsigned size() const;
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
|
|
|
@ -32,9 +32,9 @@ uint8 BSXBase::mmio_read(unsigned addr) {
|
|||
if(regs.r2192_counter >= 18) regs.r2192_counter = 0;
|
||||
|
||||
if(counter == 0) {
|
||||
time_t rawtime;
|
||||
time_t rawtime;
|
||||
time(&rawtime);
|
||||
tm *t = localtime(&rawtime);
|
||||
tm *t = localtime(&rawtime);
|
||||
|
||||
regs.r2192_hour = t->tm_hour;
|
||||
regs.r2192_minute = t->tm_min;
|
||||
|
@ -42,11 +42,11 @@ uint8 BSXBase::mmio_read(unsigned addr) {
|
|||
}
|
||||
|
||||
switch(counter) {
|
||||
case 0: return 0x00; //???
|
||||
case 1: return 0x00; //???
|
||||
case 2: return 0x00; //???
|
||||
case 3: return 0x00; //???
|
||||
case 4: return 0x00; //???
|
||||
case 0: return 0x00; //???
|
||||
case 1: return 0x00; //???
|
||||
case 2: return 0x00; //???
|
||||
case 3: return 0x00; //???
|
||||
case 4: return 0x00; //???
|
||||
case 5: return 0x01;
|
||||
case 6: return 0x01;
|
||||
case 7: return 0x00;
|
||||
|
@ -55,11 +55,11 @@ uint8 BSXBase::mmio_read(unsigned addr) {
|
|||
case 10: return regs.r2192_second;
|
||||
case 11: return regs.r2192_minute;
|
||||
case 12: return regs.r2192_hour;
|
||||
case 13: return 0x00; //???
|
||||
case 14: return 0x00; //???
|
||||
case 15: return 0x00; //???
|
||||
case 16: return 0x00; //???
|
||||
case 17: return 0x00; //???
|
||||
case 13: return 0x00; //???
|
||||
case 14: return 0x00; //???
|
||||
case 15: return 0x00; //???
|
||||
case 16: return 0x00; //???
|
||||
case 17: return 0x00; //???
|
||||
}
|
||||
} break;
|
||||
|
||||
|
|
|
@ -22,10 +22,12 @@ void BSXCart::reset() {
|
|||
void BSXCart::update_memory_map() {
|
||||
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
|
||||
|
||||
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
|
||||
if((regs.r[0x02] & 0x80) == 0x00) {
|
||||
//LoROM mapping
|
||||
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
||||
bus.map(Bus::MapLinear, 0x80, 0xff, 0x8000, 0xffff, cart);
|
||||
} else { //HiROM mapping
|
||||
} else {
|
||||
//HiROM mapping
|
||||
bus.map(Bus::MapShadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
|
||||
bus.map(Bus::MapLinear, 0x40, 0x7d, 0x0000, 0xffff, cart);
|
||||
bus.map(Bus::MapShadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
|
||||
|
@ -58,12 +60,12 @@ void BSXCart::update_memory_map() {
|
|||
}
|
||||
|
||||
uint8 BSXCart::mmio_read(unsigned addr) {
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
return regs.r[n];
|
||||
}
|
||||
|
||||
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||
return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
|
||||
}
|
||||
|
||||
|
@ -71,14 +73,14 @@ uint8 BSXCart::mmio_read(unsigned addr) {
|
|||
}
|
||||
|
||||
void BSXCart::mmio_write(unsigned addr, uint8 data) {
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
regs.r[n] = data;
|
||||
if(n == 0x0e && data & 0x80) update_memory_map();
|
||||
return;
|
||||
}
|
||||
|
||||
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||
return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ void BSXFlash::reset() {
|
|||
regs.write_enable = false;
|
||||
}
|
||||
|
||||
unsigned BSXFlash::size() {
|
||||
unsigned BSXFlash::size() const {
|
||||
return memory::bscram.size();
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ uint8 BSXFlash::read(unsigned addr) {
|
|||
}
|
||||
|
||||
if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) {
|
||||
//read flash cartridge vendor information
|
||||
//read flash cartridge vendor information
|
||||
switch(addr - 0xff00) {
|
||||
case 0x00: return 0x4d;
|
||||
case 0x01: return 0x00;
|
||||
|
@ -39,7 +39,7 @@ uint8 BSXFlash::read(unsigned addr) {
|
|||
case 0x03: return 0x00;
|
||||
case 0x04: return 0x00;
|
||||
case 0x05: return 0x00;
|
||||
case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID)
|
||||
case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID)
|
||||
case 0x07: return 0x00;
|
||||
default: return 0x00;
|
||||
}
|
||||
|
@ -49,14 +49,14 @@ uint8 BSXFlash::read(unsigned addr) {
|
|||
}
|
||||
|
||||
void BSXFlash::write(unsigned addr, uint8 data) {
|
||||
//there exist both read-only and read-write BS-X flash cartridges ...
|
||||
//unfortunately, the vendor info is not stored inside memory dumps
|
||||
//of BS-X flashcarts, so it is impossible to determine whether a
|
||||
//given flashcart is writeable.
|
||||
//however, it has been observed that LoROM-mapped BS-X carts always
|
||||
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
|
||||
//read-only flashcarts.
|
||||
//below is an unfortunately necessary workaround to this problem.
|
||||
//there exist both read-only and read-write BS-X flash cartridges ...
|
||||
//unfortunately, the vendor info is not stored inside memory dumps
|
||||
//of BS-X flashcarts, so it is impossible to determine whether a
|
||||
//given flashcart is writeable.
|
||||
//however, it has been observed that LoROM-mapped BS-X carts always
|
||||
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
|
||||
//read-only flashcarts.
|
||||
//below is an unfortunately necessary workaround to this problem.
|
||||
if(cartridge.mapper() == Cartridge::BSCHiROM) return;
|
||||
|
||||
if((addr & 0xff0000) == 0) {
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
void hiro_pbutton_tick(pButton *p) {
|
||||
if(p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self));
|
||||
}
|
||||
|
||||
void pButton::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
button = gtk_button_new_with_label(text ? text : "");
|
||||
set_default_font(button);
|
||||
gtk_widget_set_size_request(button, width, height);
|
||||
gtk_widget_show(button);
|
||||
g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(hiro_pbutton_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pButton::set_text(const char *text) {
|
||||
if(!button) return;
|
||||
gtk_button_set_label(GTK_BUTTON(button), text ? text : "");
|
||||
set_default_font(button);
|
||||
}
|
||||
|
||||
pButton::pButton(Button &self_) : pFormControl(self_), self(self_) {
|
||||
button = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pButton::gtk_handle() {
|
||||
return button;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
class pButton : public pFormControl {
|
||||
public:
|
||||
Button &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pButton(Button&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *button;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,89 +0,0 @@
|
|||
void hiro_pcanvas_expose(pCanvas *p) {
|
||||
uint32_t *f = p->fbuffer;
|
||||
uint32_t *r = p->rbuffer;
|
||||
for(unsigned y = p->canvas->allocation.height; y; y--) {
|
||||
for(unsigned x = p->canvas->allocation.width; x; x--) {
|
||||
uint32_t p = *f++;
|
||||
*r++ = ((p << 16) & 0xff0000) + (p & 0x00ff00) + ((p >> 16) & 0x0000ff);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_draw_rgb_32_image(p->canvas->window,
|
||||
p->canvas->style->fg_gc[GTK_WIDGET_STATE(p->canvas)],
|
||||
0, 0, p->canvas->allocation.width, p->canvas->allocation.height,
|
||||
GDK_RGB_DITHER_NONE, (guchar*)p->rbuffer, p->bpitch);
|
||||
}
|
||||
|
||||
gboolean hiro_pcanvas_button_press(GtkWidget *widget, GdkEventButton *event, pCanvas *p) {
|
||||
if(p->self.on_input && event->button < mouse::buttons) {
|
||||
p->self.on_input(event_t(event_t::Input, (mouse::button + event->button) + (1 << 16), &p->self));
|
||||
}
|
||||
return false; //do not propogate the event to other handlers
|
||||
}
|
||||
|
||||
gboolean hiro_pcanvas_button_release(GtkWidget *widget, GdkEventButton *event, pCanvas *p) {
|
||||
if(p->self.on_input && event->button < mouse::buttons) {
|
||||
p->self.on_input(event_t(event_t::Input, (mouse::button + event->button) + (0 << 16), &p->self));
|
||||
}
|
||||
return false; //do not propogate the event to other handlers
|
||||
}
|
||||
|
||||
void pCanvas::create(unsigned style, unsigned width, unsigned height) {
|
||||
canvas = gtk_drawing_area_new();
|
||||
resize(width, height);
|
||||
GdkColor color;
|
||||
color.pixel = color.red = color.green = color.blue = 0;
|
||||
gtk_widget_modify_bg(canvas, GTK_STATE_NORMAL, &color);
|
||||
gtk_widget_set_double_buffered(canvas, false);
|
||||
gtk_widget_add_events(canvas, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
|
||||
gtk_widget_show(canvas);
|
||||
g_signal_connect_swapped(G_OBJECT(canvas), "expose_event", G_CALLBACK(hiro_pcanvas_expose), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(canvas), "button_press_event", G_CALLBACK(hiro_pcanvas_button_press), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(canvas), "button_release_event", G_CALLBACK(hiro_pcanvas_button_release), (gpointer)this);
|
||||
}
|
||||
|
||||
void pCanvas::redraw() {
|
||||
if(!canvas || !canvas->window) return;
|
||||
|
||||
GdkRectangle rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = canvas->allocation.width;
|
||||
rect.height = canvas->allocation.height;
|
||||
gdk_window_invalidate_rect(canvas->window, &rect, true);
|
||||
}
|
||||
|
||||
uint32_t* pCanvas::buffer() {
|
||||
return fbuffer;
|
||||
}
|
||||
|
||||
pCanvas::pCanvas(Canvas &self_) : pFormControl(self_), self(self_) {
|
||||
canvas = 0;
|
||||
fbuffer = 0;
|
||||
rbuffer = 0;
|
||||
bpitch = 0;
|
||||
}
|
||||
|
||||
pCanvas::~pCanvas() {
|
||||
if(fbuffer) free(fbuffer);
|
||||
if(rbuffer) free(rbuffer);
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
void pCanvas::resize(unsigned width, unsigned height) {
|
||||
if(fbuffer) free(fbuffer);
|
||||
if(rbuffer) free(rbuffer);
|
||||
|
||||
bpitch = width * sizeof(uint32_t);
|
||||
fbuffer = (uint32_t*)malloc(bpitch * height);
|
||||
rbuffer = (uint32_t*)malloc(bpitch * height);
|
||||
memset(fbuffer, 0, bpitch * height);
|
||||
memset(rbuffer, 0, bpitch * height);
|
||||
|
||||
pFormControl::resize(width, height);
|
||||
}
|
||||
|
||||
GtkWidget* pCanvas::gtk_handle() {
|
||||
return canvas;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
class pCanvas : public pFormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height);
|
||||
void redraw();
|
||||
uint32_t* buffer();
|
||||
|
||||
Canvas &self;
|
||||
pCanvas(Canvas&);
|
||||
~pCanvas();
|
||||
|
||||
/* internal */
|
||||
GtkWidget *canvas;
|
||||
//GTK+ RGB drawing function draws in xBGR format, so two buffers are needed ...
|
||||
uint32_t *fbuffer; //one for the xRGB image
|
||||
uint32_t *rbuffer; //one for the xBGR image
|
||||
unsigned bpitch;
|
||||
void resize(unsigned width, unsigned height);
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,41 +0,0 @@
|
|||
void hiro_pcheckbox_tick(pCheckbox *p) {
|
||||
if(!p->locked && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, p->checked(), &p->self));
|
||||
}
|
||||
|
||||
void pCheckbox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
checkbox = gtk_check_button_new_with_label(text ? text : "");
|
||||
set_default_font(checkbox);
|
||||
gtk_widget_set_size_request(checkbox, width, height);
|
||||
gtk_widget_show(checkbox);
|
||||
g_signal_connect_swapped(G_OBJECT(checkbox), "toggled", G_CALLBACK(hiro_pcheckbox_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pCheckbox::set_text(const char *text) {
|
||||
if(!checkbox) return;
|
||||
gtk_button_set_label(GTK_BUTTON(checkbox), text ? text : "");
|
||||
}
|
||||
|
||||
void pCheckbox::check(bool state) {
|
||||
locked = true;
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), state ? TRUE : FALSE);
|
||||
locked = false;
|
||||
}
|
||||
|
||||
void pCheckbox::uncheck() {
|
||||
check(false);
|
||||
}
|
||||
|
||||
bool pCheckbox::checked() {
|
||||
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox));
|
||||
}
|
||||
|
||||
pCheckbox::pCheckbox(Checkbox &self_) : pFormControl(self_), self(self_) {
|
||||
checkbox = 0;
|
||||
locked = false;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pCheckbox::gtk_handle() {
|
||||
return checkbox;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
class pCheckbox : public pFormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check(bool state = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
|
||||
Checkbox &self;
|
||||
pCheckbox(Checkbox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget* gtk_handle();
|
||||
GtkWidget *checkbox;
|
||||
bool locked;
|
||||
};
|
|
@ -1,45 +0,0 @@
|
|||
void hiro_pcombobox_change(pCombobox *p) {
|
||||
if(p->self.on_change) p->self.on_change(event_t(event_t::Change, p->get_selection(), &p->self));
|
||||
}
|
||||
|
||||
void pCombobox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
combobox = gtk_combo_box_new_text();
|
||||
set_default_font(combobox);
|
||||
gtk_widget_set_size_request(combobox, width, height);
|
||||
gtk_widget_show(combobox);
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(combobox), "changed", G_CALLBACK(hiro_pcombobox_change), (gpointer)this);
|
||||
}
|
||||
|
||||
void pCombobox::add_item(const char *text) {
|
||||
if(!combobox) return;
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), text ? text : "?");
|
||||
if(counter++ == 0) set_selection(0);
|
||||
}
|
||||
|
||||
int pCombobox::get_selection() {
|
||||
return gtk_combo_box_get_active(GTK_COMBO_BOX(combobox));
|
||||
}
|
||||
|
||||
void pCombobox::set_selection(int index) {
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), index);
|
||||
}
|
||||
|
||||
void pCombobox::reset() {
|
||||
if(counter == 0) return;
|
||||
for(int i = counter - 1; i >= 0; i--) {
|
||||
gtk_combo_box_remove_text(GTK_COMBO_BOX(combobox), i);
|
||||
}
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
pCombobox::pCombobox(Combobox &self_) : pFormControl(self_), self(self_) {
|
||||
combobox = 0;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pCombobox::gtk_handle() {
|
||||
return combobox;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
class pCombobox : public pFormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void add_item(const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
Combobox &self;
|
||||
pCombobox(Combobox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *combobox;
|
||||
unsigned counter;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,74 +0,0 @@
|
|||
static void hiro_peditbox_change(pEditbox *p) {
|
||||
if(p->self.on_change) {
|
||||
p->self.on_change(event_t(event_t::Change, 0, &p->self));
|
||||
}
|
||||
}
|
||||
|
||||
void pEditbox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
multiline = bool(style & Editbox::Multiline);
|
||||
|
||||
if(multiline == false) {
|
||||
editbox = gtk_entry_new();
|
||||
if(style & Editbox::Readonly) { gtk_entry_set_editable(GTK_ENTRY(editbox), false); }
|
||||
gtk_entry_set_text(GTK_ENTRY(editbox), text ? text : "");
|
||||
gtk_widget_set_size_request(editbox, width, height);
|
||||
gtk_widget_show(editbox);
|
||||
g_signal_connect_swapped(G_OBJECT(editbox), "changed", G_CALLBACK(hiro_peditbox_change), (gpointer)this);
|
||||
} else {
|
||||
GtkPolicyType hscroll = (style & Editbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Editbox::HorizontalScrollNever ) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
GtkPolicyType vscroll = (style & Editbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Editbox::VerticalScrollNever ) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
scrollbox = gtk_scrolled_window_new(0, 0);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN);
|
||||
gtk_widget_set_size_request(scrollbox, width, height);
|
||||
editbox = gtk_text_view_new();
|
||||
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(editbox),
|
||||
(hscroll == GTK_POLICY_NEVER ? GTK_WRAP_WORD_CHAR : GTK_WRAP_NONE));
|
||||
gtk_container_add(GTK_CONTAINER(scrollbox), editbox);
|
||||
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(editbox));
|
||||
if(style & Editbox::Readonly) { gtk_text_view_set_editable(GTK_TEXT_VIEW(editbox), false); }
|
||||
gtk_text_buffer_set_text(buffer, text ? text : "", -1);
|
||||
gtk_widget_show(editbox);
|
||||
gtk_widget_show(scrollbox);
|
||||
g_signal_connect_swapped(G_OBJECT(buffer), "changed", G_CALLBACK(hiro_peditbox_change), (gpointer)this);
|
||||
}
|
||||
|
||||
set_default_font(editbox);
|
||||
}
|
||||
|
||||
void pEditbox::set_text(const char *text) {
|
||||
if(multiline == false) {
|
||||
gtk_entry_set_text(GTK_ENTRY(editbox), text);
|
||||
} else {
|
||||
gtk_text_buffer_set_text(buffer, text, -1);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned pEditbox::get_text(char *text, unsigned length) {
|
||||
if(multiline == false) {
|
||||
const char *temp = gtk_entry_get_text(GTK_ENTRY(editbox));
|
||||
return strlcpy(text, temp ? temp : "", length);
|
||||
} else {
|
||||
GtkTextIter start, end;
|
||||
gtk_text_buffer_get_start_iter(buffer, &start);
|
||||
gtk_text_buffer_get_end_iter(buffer, &end);
|
||||
return strlcpy(text, gtk_text_buffer_get_text(buffer, &start, &end, true), length);
|
||||
}
|
||||
}
|
||||
|
||||
pEditbox::pEditbox(Editbox &self_) : pFormControl(self_), self(self_) {
|
||||
scrollbox = 0;
|
||||
editbox = 0;
|
||||
buffer = 0;
|
||||
multiline = false;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pEditbox::gtk_handle() {
|
||||
return multiline ? scrollbox : editbox;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
class pEditbox : public pFormControl {
|
||||
public:
|
||||
Editbox &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
unsigned get_text(char *text, unsigned length = -1U);
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pEditbox(Editbox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *scrollbox;
|
||||
GtkWidget *editbox;
|
||||
GtkTextBuffer *buffer;
|
||||
bool multiline;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,32 +0,0 @@
|
|||
void pFormControl::resize(unsigned width, unsigned height) {
|
||||
gtk_widget_set_size_request(gtk_handle(), width, height);
|
||||
}
|
||||
|
||||
void pFormControl::focus() {
|
||||
gtk_widget_grab_focus(gtk_handle());
|
||||
}
|
||||
|
||||
bool pFormControl::focused() {
|
||||
return GTK_WIDGET_HAS_FOCUS(gtk_handle());
|
||||
}
|
||||
|
||||
void pFormControl::enable(bool state) {
|
||||
gtk_widget_set_sensitive(gtk_handle(), state);
|
||||
}
|
||||
|
||||
void pFormControl::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pFormControl::enabled() {
|
||||
return GTK_WIDGET_SENSITIVE(gtk_handle());
|
||||
}
|
||||
|
||||
pFormControl::pFormControl(FormControl &self_) : pWidget(self_), self(self_) {
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pFormControl::gtk_handle() {
|
||||
return 0;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
class pFormControl : public pWidget {
|
||||
public:
|
||||
virtual void resize(unsigned width, unsigned height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
FormControl &self;
|
||||
pFormControl(FormControl&);
|
||||
|
||||
/* internal */
|
||||
virtual GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
void pFrame::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
frame = gtk_frame_new(text ? text : "");
|
||||
set_default_font(frame);
|
||||
gtk_widget_set_size_request(frame, width, height);
|
||||
gtk_widget_show(frame);
|
||||
}
|
||||
|
||||
void pFrame::set_text(const char *text) {
|
||||
gtk_frame_set_label(GTK_FRAME(frame), text ? text : "");
|
||||
}
|
||||
|
||||
pFrame::pFrame(Frame &self_) : pFormControl(self_), self(self_) {
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pFrame::gtk_handle() {
|
||||
return frame;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
class pFrame : public pFormControl {
|
||||
public:
|
||||
Frame &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pFrame(Frame&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *frame;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,270 +0,0 @@
|
|||
#include "hiro.hpp"
|
||||
#include "port.cpp"
|
||||
|
||||
#include <nall/algorithm.hpp>
|
||||
using nall::min;
|
||||
using nall::max;
|
||||
|
||||
namespace libhiro {
|
||||
|
||||
static void set_font(GtkWidget *widget, gpointer font) {
|
||||
gtk_widget_modify_font(widget, (PangoFontDescription*)font);
|
||||
if(GTK_IS_CONTAINER(widget)) {
|
||||
gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)set_font, font);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_default_font(GtkWidget *widget) {
|
||||
set_font(widget, phiro().font);
|
||||
}
|
||||
|
||||
#include "keymap.cpp"
|
||||
#include "widget.cpp"
|
||||
#include "window.cpp"
|
||||
#include "menucontrol.cpp"
|
||||
#include "menugroup.cpp"
|
||||
#include "menuitem.cpp"
|
||||
#include "menucheckitem.cpp"
|
||||
#include "menuradioitem.cpp"
|
||||
#include "menuseparator.cpp"
|
||||
#include "formcontrol.cpp"
|
||||
#include "frame.cpp"
|
||||
#include "canvas.cpp"
|
||||
#include "label.cpp"
|
||||
#include "button.cpp"
|
||||
#include "checkbox.cpp"
|
||||
#include "radiobox.cpp"
|
||||
#include "editbox.cpp"
|
||||
#include "listbox.cpp"
|
||||
#include "combobox.cpp"
|
||||
#include "progressbar.cpp"
|
||||
#include "slider.cpp"
|
||||
|
||||
void pHiro::init() {
|
||||
is_composited = false;
|
||||
*default_path = 0;
|
||||
screen = gdk_screen_get_default();
|
||||
if(gdk_screen_is_composited(screen)) {
|
||||
colormap = gdk_screen_get_rgba_colormap(screen);
|
||||
if(colormap) is_composited = true;
|
||||
else colormap = gdk_screen_get_rgb_colormap(screen); //fallback
|
||||
} else {
|
||||
colormap = gdk_screen_get_rgb_colormap(screen);
|
||||
}
|
||||
|
||||
font = pango_font_description_new();
|
||||
pango_font_description_set_family(font, "Sans");
|
||||
pango_font_description_set_absolute_size(font, 11.0 * PANGO_SCALE);
|
||||
pango_font_description_set_style(font, PANGO_STYLE_NORMAL);
|
||||
|
||||
//apply custom GTK+-2.0 stylesheet.
|
||||
//it's obviously not ideal to override the global GTK+ theme settings;
|
||||
//however it is necessary to ensure consistency between ports of hiro.
|
||||
//without this, it would be impossible to develop a hiro application
|
||||
//on one platform, and be assured text wouldn't clipped off, etc on
|
||||
//another platform.
|
||||
gtk_rc_parse_string(
|
||||
"style \"ruby-gtk\"\n"
|
||||
"{\n"
|
||||
" GtkComboBox::appears-as-list = 1\n" //text tends to get cut off in some themes otherwise
|
||||
" GtkTreeView::vertical-separator = 0\n" //GTK+ lists tend to have way more space than on Windows
|
||||
"}\n"
|
||||
"\n"
|
||||
"class \"GtkComboBox\" style \"ruby-gtk\"\n"
|
||||
"class \"GtkTreeView\" style \"ruby-gtk\"\n"
|
||||
);
|
||||
}
|
||||
|
||||
void pHiro::term() {
|
||||
pango_font_description_free(font);
|
||||
enable_screensaver();
|
||||
}
|
||||
|
||||
bool pHiro::run() {
|
||||
if(is_screensaver_enabled == false) screensaver_tick();
|
||||
gtk_main_iteration_do(false);
|
||||
return pending();
|
||||
}
|
||||
|
||||
bool pHiro::pending() {
|
||||
return gtk_events_pending();
|
||||
}
|
||||
|
||||
bool pHiro::folder_select(Window *focus, char *filename, const char *path) {
|
||||
if(!filename) return false;
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Select Folder",
|
||||
focus ? GTK_WINDOW(focus->p.gtk_handle()) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0);
|
||||
|
||||
if(path && *path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
else if(*default_path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), default_path);
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
strcpy(filename, fn);
|
||||
set_default_path(fn);
|
||||
g_free(fn);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return strcmp(filename, ""); //return true if filename exists
|
||||
}
|
||||
|
||||
bool pHiro::file_open(Window *focus, char *filename, const char *path, const char *filter) {
|
||||
if(!filename) return false;
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Open File",
|
||||
focus ? GTK_WINDOW(focus->p.gtk_handle()) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0);
|
||||
|
||||
if(path && *path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
else if(*default_path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), default_path);
|
||||
|
||||
if(filter && *filter) {
|
||||
lstring filterlist;
|
||||
filterlist.split("\n", filter);
|
||||
for(unsigned i = 0; i < filterlist.size(); i++) {
|
||||
GtkFileFilter *filter = gtk_file_filter_new();
|
||||
lstring filterpart;
|
||||
filterpart.split("\t", filterlist[i]);
|
||||
gtk_file_filter_set_name(filter, string() << filterpart[0] << " (" << filterpart[1] << ")");
|
||||
lstring patternlist;
|
||||
patternlist.split(",", filterpart[1]);
|
||||
for(unsigned l = 0; l < patternlist.size(); l++) {
|
||||
gtk_file_filter_add_pattern(filter, patternlist[l]);
|
||||
}
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
||||
}
|
||||
}
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
strcpy(filename, fn);
|
||||
set_default_path(fn);
|
||||
g_free(fn);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return strcmp(filename, ""); //return true if filename exists
|
||||
}
|
||||
|
||||
bool pHiro::file_save(Window *focus, char *filename, const char *path, const char *filter) {
|
||||
if(!filename) return false;
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Save File",
|
||||
focus ? GTK_WINDOW(focus->p.gtk_handle()) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0);
|
||||
|
||||
if(path && *path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
else if(*default_path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), default_path);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
|
||||
if(filter && *filter) {
|
||||
lstring filterlist;
|
||||
filterlist.split("\n", filter);
|
||||
for(unsigned i = 0; i < filterlist.size(); i++) {
|
||||
GtkFileFilter *filter = gtk_file_filter_new();
|
||||
lstring filterpart;
|
||||
filterpart.split("\t", filterlist[i]);
|
||||
gtk_file_filter_set_name(filter, string() << filterpart[0] << " (" << filterpart[1] << ")");
|
||||
lstring patternlist;
|
||||
patternlist.split(",", filterpart[1]);
|
||||
for(unsigned l = 0; l < patternlist.size(); l++) {
|
||||
gtk_file_filter_add_pattern(filter, patternlist[l]);
|
||||
}
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
||||
}
|
||||
}
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
strcpy(filename, fn);
|
||||
set_default_path(fn);
|
||||
g_free(fn);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return strcmp(filename, ""); //return true if filename exists
|
||||
}
|
||||
|
||||
unsigned pHiro::screen_width() {
|
||||
return gdk_screen_width();
|
||||
}
|
||||
|
||||
unsigned pHiro::screen_height() {
|
||||
return gdk_screen_height();
|
||||
}
|
||||
|
||||
void pHiro::enable_screensaver() {
|
||||
if(is_screensaver_enabled == true) return;
|
||||
is_screensaver_enabled = true;
|
||||
DPMSDisable(GDK_DISPLAY());
|
||||
}
|
||||
|
||||
void pHiro::disable_screensaver() {
|
||||
if(is_screensaver_enabled == false) return;
|
||||
is_screensaver_enabled = false;
|
||||
DPMSEnable(GDK_DISPLAY());
|
||||
}
|
||||
|
||||
pHiro& pHiro::handle() {
|
||||
return hiro().p;
|
||||
}
|
||||
|
||||
pHiro::pHiro(Hiro &self_) : self(self_) {
|
||||
is_screensaver_enabled = true;
|
||||
}
|
||||
|
||||
pHiro& phiro() {
|
||||
return pHiro::handle();
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
//GTK+ does not save the most recent path to a file.
|
||||
//Strip trailing filename / folder to save path for next file dialog request.
|
||||
//This is only called when file dialog filename / folder is accepted, not when dialog cancelled.
|
||||
void pHiro::set_default_path(const char *p) {
|
||||
strcpy(default_path, p);
|
||||
for(int i = strlen(default_path) - 1; i >= 0; i--) {
|
||||
if(default_path[i] == '/' || default_path[i] == '\\') {
|
||||
default_path[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pHiro::screensaver_tick() {
|
||||
static clock_t delta_x = 0, delta_y = 0;
|
||||
|
||||
delta_y = clock();
|
||||
if(delta_y - delta_x < CLOCKS_PER_SEC * 20) return;
|
||||
|
||||
//XSetScreenSaver(timeout = 0) does not work
|
||||
//XResetScreenSaver() does not work
|
||||
//XScreenSaverSuspend() does not work
|
||||
//DPMSDisable() does not work
|
||||
//XSendEvent(KeyPressMask) does not work
|
||||
//use XTest extension to send fake keypress every ~20 seconds.
|
||||
//keycode of 255 does not map to any actual key, but it will block screensaver.
|
||||
delta_x = delta_y;
|
||||
XTestFakeKeyEvent(GDK_DISPLAY(), 255, True, 0);
|
||||
XSync(GDK_DISPLAY(), False);
|
||||
XTestFakeKeyEvent(GDK_DISPLAY(), 255, False, 0);
|
||||
XSync(GDK_DISPLAY(), False);
|
||||
}
|
||||
|
||||
} //namespace libhiro
|
|
@ -1,78 +0,0 @@
|
|||
#ifndef HIRO_GTK_H
|
||||
#define HIRO_GTK_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <cairo.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <X11/extensions/dpms.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
extern int hiromain(int argc, const char *const argv[]);
|
||||
|
||||
namespace libhiro {
|
||||
|
||||
#include "widget.hpp"
|
||||
#include "window.hpp"
|
||||
#include "menucontrol.hpp"
|
||||
#include "menugroup.hpp"
|
||||
#include "menuitem.hpp"
|
||||
#include "menucheckitem.hpp"
|
||||
#include "menuradioitem.hpp"
|
||||
#include "menuseparator.hpp"
|
||||
#include "formcontrol.hpp"
|
||||
#include "frame.hpp"
|
||||
#include "canvas.hpp"
|
||||
#include "label.hpp"
|
||||
#include "button.hpp"
|
||||
#include "checkbox.hpp"
|
||||
#include "radiobox.hpp"
|
||||
#include "editbox.hpp"
|
||||
#include "listbox.hpp"
|
||||
#include "combobox.hpp"
|
||||
#include "progressbar.hpp"
|
||||
#include "slider.hpp"
|
||||
|
||||
class pHiro {
|
||||
public:
|
||||
Hiro &self;
|
||||
void init();
|
||||
void term();
|
||||
bool run();
|
||||
bool pending();
|
||||
|
||||
bool folder_select(Window *focus, char *filename, const char *path = "");
|
||||
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||
|
||||
unsigned screen_width();
|
||||
unsigned screen_height();
|
||||
|
||||
void enable_screensaver();
|
||||
void disable_screensaver();
|
||||
|
||||
static pHiro& handle();
|
||||
pHiro(Hiro&);
|
||||
|
||||
/* internal */
|
||||
GdkScreen *screen;
|
||||
GdkColormap *colormap;
|
||||
PangoFontDescription *font;
|
||||
bool is_composited;
|
||||
char default_path[PATH_MAX];
|
||||
|
||||
void set_default_path(const char*);
|
||||
bool is_screensaver_enabled;
|
||||
void screensaver_tick();
|
||||
uint16_t translate_key(unsigned key);
|
||||
};
|
||||
|
||||
pHiro& phiro();
|
||||
|
||||
} //namespace libhiro
|
||||
|
||||
#endif //ifndef HIRO_GTK_H
|
|
@ -1,188 +0,0 @@
|
|||
uint16_t pHiro::translate_key(unsigned key) {
|
||||
switch(key) {
|
||||
case GDK_Escape: return keyboard::escape;
|
||||
|
||||
case GDK_F1: return keyboard::f1;
|
||||
case GDK_F2: return keyboard::f2;
|
||||
case GDK_F3: return keyboard::f3;
|
||||
case GDK_F4: return keyboard::f4;
|
||||
case GDK_F5: return keyboard::f5;
|
||||
case GDK_F6: return keyboard::f6;
|
||||
case GDK_F7: return keyboard::f7;
|
||||
case GDK_F8: return keyboard::f8;
|
||||
case GDK_F9: return keyboard::f9;
|
||||
case GDK_F10: return keyboard::f10;
|
||||
case GDK_F11: return keyboard::f11;
|
||||
case GDK_F12: return keyboard::f12;
|
||||
|
||||
case GDK_Print: return keyboard::print_screen;
|
||||
case GDK_Sys_Req: return keyboard::print_screen;
|
||||
case GDK_Scroll_Lock: return keyboard::scroll_lock;
|
||||
case GDK_Pause: return keyboard::pause;
|
||||
case GDK_Break: return keyboard::pause;
|
||||
|
||||
case GDK_grave: return keyboard::tilde;
|
||||
case GDK_asciitilde: return keyboard::tilde;
|
||||
|
||||
case GDK_1: return keyboard::num_1;
|
||||
case GDK_2: return keyboard::num_2;
|
||||
case GDK_3: return keyboard::num_3;
|
||||
case GDK_4: return keyboard::num_4;
|
||||
case GDK_5: return keyboard::num_5;
|
||||
case GDK_6: return keyboard::num_6;
|
||||
case GDK_7: return keyboard::num_7;
|
||||
case GDK_8: return keyboard::num_8;
|
||||
case GDK_9: return keyboard::num_9;
|
||||
case GDK_0: return keyboard::num_0;
|
||||
|
||||
case GDK_exclam: return keyboard::num_1;
|
||||
case GDK_at: return keyboard::num_2;
|
||||
case GDK_numbersign: return keyboard::num_3;
|
||||
case GDK_dollar: return keyboard::num_4;
|
||||
case GDK_percent: return keyboard::num_5;
|
||||
case GDK_asciicircum: return keyboard::num_6;
|
||||
case GDK_ampersand: return keyboard::num_7;
|
||||
case GDK_asterisk: return keyboard::num_8;
|
||||
case GDK_parenleft: return keyboard::num_9;
|
||||
case GDK_parenright: return keyboard::num_0;
|
||||
|
||||
case GDK_minus: return keyboard::dash;
|
||||
case GDK_underscore: return keyboard::dash;
|
||||
case GDK_equal: return keyboard::equal;
|
||||
case GDK_plus: return keyboard::equal;
|
||||
case GDK_BackSpace: return keyboard::backspace;
|
||||
|
||||
case GDK_Insert: return keyboard::insert;
|
||||
case GDK_Delete: return keyboard::delete_;
|
||||
case GDK_Home: return keyboard::home;
|
||||
case GDK_End: return keyboard::end;
|
||||
case GDK_Page_Up: return keyboard::page_up;
|
||||
case GDK_Page_Down: return keyboard::page_down;
|
||||
|
||||
case GDK_a: return keyboard::a;
|
||||
case GDK_b: return keyboard::b;
|
||||
case GDK_c: return keyboard::c;
|
||||
case GDK_d: return keyboard::d;
|
||||
case GDK_e: return keyboard::e;
|
||||
case GDK_f: return keyboard::f;
|
||||
case GDK_g: return keyboard::g;
|
||||
case GDK_h: return keyboard::h;
|
||||
case GDK_i: return keyboard::i;
|
||||
case GDK_j: return keyboard::j;
|
||||
case GDK_k: return keyboard::k;
|
||||
case GDK_l: return keyboard::l;
|
||||
case GDK_m: return keyboard::m;
|
||||
case GDK_n: return keyboard::n;
|
||||
case GDK_o: return keyboard::o;
|
||||
case GDK_p: return keyboard::p;
|
||||
case GDK_q: return keyboard::q;
|
||||
case GDK_r: return keyboard::r;
|
||||
case GDK_s: return keyboard::s;
|
||||
case GDK_t: return keyboard::t;
|
||||
case GDK_u: return keyboard::u;
|
||||
case GDK_v: return keyboard::v;
|
||||
case GDK_w: return keyboard::w;
|
||||
case GDK_x: return keyboard::x;
|
||||
case GDK_y: return keyboard::y;
|
||||
case GDK_z: return keyboard::z;
|
||||
|
||||
case GDK_A: return keyboard::a;
|
||||
case GDK_B: return keyboard::b;
|
||||
case GDK_C: return keyboard::c;
|
||||
case GDK_D: return keyboard::d;
|
||||
case GDK_E: return keyboard::e;
|
||||
case GDK_F: return keyboard::f;
|
||||
case GDK_G: return keyboard::g;
|
||||
case GDK_H: return keyboard::h;
|
||||
case GDK_I: return keyboard::i;
|
||||
case GDK_J: return keyboard::j;
|
||||
case GDK_K: return keyboard::k;
|
||||
case GDK_L: return keyboard::l;
|
||||
case GDK_M: return keyboard::m;
|
||||
case GDK_N: return keyboard::n;
|
||||
case GDK_O: return keyboard::o;
|
||||
case GDK_P: return keyboard::p;
|
||||
case GDK_Q: return keyboard::q;
|
||||
case GDK_R: return keyboard::r;
|
||||
case GDK_S: return keyboard::s;
|
||||
case GDK_T: return keyboard::t;
|
||||
case GDK_U: return keyboard::u;
|
||||
case GDK_V: return keyboard::v;
|
||||
case GDK_W: return keyboard::w;
|
||||
case GDK_X: return keyboard::x;
|
||||
case GDK_Y: return keyboard::y;
|
||||
case GDK_Z: return keyboard::z;
|
||||
|
||||
case GDK_bracketleft: return keyboard::lbracket;
|
||||
case GDK_bracketright: return keyboard::rbracket;
|
||||
case GDK_backslash: return keyboard::backslash;
|
||||
case GDK_semicolon: return keyboard::semicolon;
|
||||
case GDK_apostrophe: return keyboard::apostrophe;
|
||||
case GDK_comma: return keyboard::comma;
|
||||
case GDK_period: return keyboard::period;
|
||||
case GDK_slash: return keyboard::slash;
|
||||
|
||||
case GDK_braceleft: return keyboard::lbracket;
|
||||
case GDK_braceright: return keyboard::rbracket;
|
||||
case GDK_bar: return keyboard::backslash;
|
||||
case GDK_colon: return keyboard::semicolon;
|
||||
case GDK_quotedbl: return keyboard::apostrophe;
|
||||
case GDK_less: return keyboard::comma;
|
||||
case GDK_greater: return keyboard::period;
|
||||
case GDK_question: return keyboard::slash;
|
||||
|
||||
case GDK_KP_1: return keyboard::pad_1;
|
||||
case GDK_KP_2: return keyboard::pad_2;
|
||||
case GDK_KP_3: return keyboard::pad_3;
|
||||
case GDK_KP_4: return keyboard::pad_4;
|
||||
case GDK_KP_5: return keyboard::pad_5;
|
||||
case GDK_KP_6: return keyboard::pad_6;
|
||||
case GDK_KP_7: return keyboard::pad_7;
|
||||
case GDK_KP_8: return keyboard::pad_8;
|
||||
case GDK_KP_9: return keyboard::pad_9;
|
||||
case GDK_KP_0: return keyboard::pad_0;
|
||||
case GDK_KP_Decimal: return keyboard::point;
|
||||
|
||||
case GDK_KP_End: return keyboard::pad_1;
|
||||
case GDK_KP_Down: return keyboard::pad_2;
|
||||
case GDK_KP_Page_Down: return keyboard::pad_3;
|
||||
case GDK_KP_Left: return keyboard::pad_4;
|
||||
case GDK_KP_Begin: return keyboard::pad_5;
|
||||
case GDK_KP_Right: return keyboard::pad_6;
|
||||
case GDK_KP_Home: return keyboard::pad_7;
|
||||
case GDK_KP_Up: return keyboard::pad_8;
|
||||
case GDK_KP_Page_Up: return keyboard::pad_9;
|
||||
case GDK_KP_Insert: return keyboard::pad_0;
|
||||
case GDK_KP_Delete: return keyboard::point;
|
||||
|
||||
case GDK_KP_Add: return keyboard::add;
|
||||
case GDK_KP_Subtract: return keyboard::subtract;
|
||||
case GDK_KP_Multiply: return keyboard::multiply;
|
||||
case GDK_KP_Divide: return keyboard::divide;
|
||||
case GDK_KP_Enter: return keyboard::enter;
|
||||
|
||||
case GDK_Num_Lock: return keyboard::num_lock;
|
||||
case GDK_Caps_Lock: return keyboard::caps_lock;
|
||||
|
||||
case GDK_Up: return keyboard::up;
|
||||
case GDK_Down: return keyboard::down;
|
||||
case GDK_Left: return keyboard::left;
|
||||
case GDK_Right: return keyboard::right;
|
||||
|
||||
case GDK_Tab: return keyboard::tab;
|
||||
case GDK_Return: return keyboard::return_;
|
||||
case GDK_space: return keyboard::spacebar;
|
||||
|
||||
case GDK_Control_L: return keyboard::lctrl;
|
||||
case GDK_Control_R: return keyboard::rctrl;
|
||||
case GDK_Alt_L: return keyboard::lalt;
|
||||
case GDK_Alt_R: return keyboard::ralt;
|
||||
case GDK_Shift_L: return keyboard::lshift;
|
||||
case GDK_Shift_R: return keyboard::rshift;
|
||||
case GDK_Super_L: return keyboard::lsuper;
|
||||
case GDK_Super_R: return keyboard::rsuper;
|
||||
case GDK_Menu: return keyboard::menu;
|
||||
}
|
||||
|
||||
return keyboard::none;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
void pLabel::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
label = gtk_label_new(text ? text : "");
|
||||
set_default_font(label);
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
|
||||
gtk_widget_set_size_request(label, width, height);
|
||||
gtk_widget_show(label);
|
||||
}
|
||||
|
||||
void pLabel::set_text(const char *text) {
|
||||
if(!label) return;
|
||||
gtk_label_set_label(GTK_LABEL(label), text ? text : "");
|
||||
}
|
||||
|
||||
pLabel::pLabel(Label &self_) : pFormControl(self_), self(self_) {
|
||||
label = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pLabel::gtk_handle() {
|
||||
return label;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
class pLabel : public pFormControl {
|
||||
public:
|
||||
Label &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pLabel(Label&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *label;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,160 +0,0 @@
|
|||
static void hiro_plistbox_change(pListbox *p) {
|
||||
//only send message when active item changes
|
||||
if(p->listbox_selection == p->get_selection()) return;
|
||||
|
||||
p->listbox_selection = p->get_selection();
|
||||
if(p->self.on_change) {
|
||||
p->self.on_change(event_t(event_t::Change, p->listbox_selection, &p->self));
|
||||
}
|
||||
}
|
||||
|
||||
static void hiro_plistbox_activate(pListbox *p) {
|
||||
p->listbox_selection = p->get_selection();
|
||||
if(p->self.on_activate) {
|
||||
p->self.on_activate(event_t(event_t::Activate, p->listbox_selection, &p->self));
|
||||
}
|
||||
}
|
||||
|
||||
void pListbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) {
|
||||
bool header = style & Listbox::Header;
|
||||
GtkPolicyType hscroll = (style & Listbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Listbox::HorizontalScrollNever ) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
GtkPolicyType vscroll = (style & Listbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Listbox::VerticalScrollNever ) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
|
||||
scrollbox = gtk_scrolled_window_new(0, 0);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN);
|
||||
|
||||
lstring list;
|
||||
list.split("\t", columns);
|
||||
|
||||
GType *v = (GType*)malloc(list.size() * sizeof(GType));
|
||||
for(unsigned i = 0; i < list.size(); i++) v[i] = G_TYPE_STRING;
|
||||
store = gtk_list_store_newv(list.size(), v);
|
||||
free(v);
|
||||
|
||||
listbox = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
|
||||
gtk_container_add(GTK_CONTAINER(scrollbox), listbox);
|
||||
g_object_unref(G_OBJECT(store));
|
||||
gtk_widget_set_size_request(scrollbox, width, height);
|
||||
gtk_widget_show(listbox);
|
||||
gtk_widget_show(scrollbox);
|
||||
|
||||
//alternate colors for each listbox entry if there are multiple columns
|
||||
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(listbox), list.size() >= 2 ? true : false);
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
unsigned i = column.size();
|
||||
column[i].renderer = gtk_cell_renderer_text_new();
|
||||
column[i].column = gtk_tree_view_column_new_with_attributes(
|
||||
list[i], column[i].renderer, "text", i, (void*)0
|
||||
);
|
||||
//default header widget is GtkLabel with stock font size;
|
||||
//only way to assign a custom font to header widget is to create custom GtkLabel widget.
|
||||
column[i].label = gtk_label_new(list[i]);
|
||||
set_default_font(column[i].label);
|
||||
gtk_widget_show(column[i].label);
|
||||
gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(column[i].column), column[i].label);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(listbox), column[i].column);
|
||||
}
|
||||
|
||||
if(text && *text) {
|
||||
list.split("\n", text);
|
||||
for(unsigned i = 0; i < list.size(); i++) add_item(list[i]);
|
||||
}
|
||||
|
||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(listbox), header);
|
||||
autosize_columns();
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(listbox), "cursor-changed", G_CALLBACK(hiro_plistbox_change), (gpointer)this);
|
||||
g_signal_connect_swapped(G_OBJECT(listbox), "row-activated", G_CALLBACK(hiro_plistbox_activate), (gpointer)this);
|
||||
|
||||
set_default_font(listbox);
|
||||
}
|
||||
|
||||
void pListbox::autosize_columns() {
|
||||
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listbox));
|
||||
}
|
||||
|
||||
void pListbox::set_column_width(unsigned index, unsigned width) {
|
||||
gtk_tree_view_column_set_min_width(column[index].column, width);
|
||||
gtk_tree_view_column_set_max_width(column[index].column, width);
|
||||
}
|
||||
|
||||
void pListbox::add_item(const char *text) {
|
||||
lstring list;
|
||||
list.split("\t", text);
|
||||
gtk_list_store_append(store, &iter);
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
gtk_list_store_set(store, &iter, i, (const char*)list[i], -1);
|
||||
}
|
||||
}
|
||||
|
||||
void pListbox::set_item(unsigned index, const char *text) {
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||
for(unsigned i = 0; i <= index; i++) {
|
||||
i == 0 ?
|
||||
gtk_tree_model_get_iter_first(model, &iter) :
|
||||
gtk_tree_model_iter_next(model, &iter);
|
||||
}
|
||||
|
||||
lstring list;
|
||||
list.split("\t", text);
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
gtk_list_store_set(store, &iter, i, (const char*)list[i], -1);
|
||||
}
|
||||
}
|
||||
|
||||
int pListbox::get_selection() {
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) return -1;
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return 0;
|
||||
for(unsigned i = 1; i < 100000; i++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) return -1;
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pListbox::set_selection(int index) {
|
||||
int current = get_selection();
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||
gtk_tree_selection_unselect_all(selection);
|
||||
if(index < 0) return; //nothing to select?
|
||||
|
||||
if(gtk_tree_model_get_iter_first(model, &iter)) {
|
||||
if(index == 0) {
|
||||
gtk_tree_selection_select_iter(selection, &iter);
|
||||
} else {
|
||||
for(unsigned i = 1; i < 100000; i++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) break;
|
||||
if(index == i) {
|
||||
gtk_tree_selection_select_iter(selection, &iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListbox::reset() {
|
||||
listbox_selection = -1;
|
||||
gtk_list_store_clear(GTK_LIST_STORE(store));
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(listbox), GTK_TREE_MODEL(store));
|
||||
}
|
||||
|
||||
pListbox::pListbox(Listbox &self_) : pFormControl(self_), self(self_) {
|
||||
scrollbox = 0;
|
||||
listbox = 0;
|
||||
listbox_selection = -1;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pListbox::gtk_handle() {
|
||||
return scrollbox;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
class pListbox : public pFormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = "");
|
||||
void autosize_columns();
|
||||
void set_column_width(unsigned column, unsigned width);
|
||||
void add_item(const char *text);
|
||||
void set_item(unsigned index, const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
Listbox &self;
|
||||
pListbox(Listbox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *scrollbox;
|
||||
GtkWidget *listbox;
|
||||
GtkListStore *store;
|
||||
struct GtkColumn {
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkWidget *label;
|
||||
};
|
||||
vector<GtkColumn> column;
|
||||
GtkTreeIter iter;
|
||||
int listbox_selection;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,35 +0,0 @@
|
|||
void hiro_pmenucheckitem_tick(pMenuCheckItem *p) {
|
||||
if(!p->locked && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, p->checked(), &p->self));
|
||||
}
|
||||
|
||||
void pMenuCheckItem::create(const char *text) {
|
||||
item = gtk_check_menu_item_new_with_label(text ? text : "?");
|
||||
set_default_font(item);
|
||||
gtk_widget_show(item);
|
||||
g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(hiro_pmenucheckitem_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pMenuCheckItem::check(bool state) {
|
||||
locked = true;
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), state ? TRUE : FALSE);
|
||||
locked = false;
|
||||
}
|
||||
|
||||
void pMenuCheckItem::uncheck() {
|
||||
check(false);
|
||||
}
|
||||
|
||||
bool pMenuCheckItem::checked() {
|
||||
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
|
||||
}
|
||||
|
||||
pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) {
|
||||
item = 0;
|
||||
locked = true;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuCheckItem::gtk_handle() {
|
||||
return item;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
class pMenuCheckItem : public pMenuControl {
|
||||
public:
|
||||
void create(const char *text = "");
|
||||
void check(bool state = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
|
||||
MenuCheckItem &self;
|
||||
pMenuCheckItem(MenuCheckItem&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget* gtk_handle();
|
||||
GtkWidget *item;
|
||||
bool locked;
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
void pMenuControl::enable(bool state) {
|
||||
gtk_widget_set_sensitive(gtk_handle(), state);
|
||||
}
|
||||
|
||||
void pMenuControl::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pMenuControl::enabled() {
|
||||
return GTK_WIDGET_SENSITIVE(gtk_handle());
|
||||
}
|
||||
|
||||
pMenuControl::pMenuControl(MenuControl &self_) : pWidget(self_), self(self_) {
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuControl::gtk_handle() {
|
||||
return 0;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
class pMenuControl : public pWidget {
|
||||
public:
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
MenuControl &self;
|
||||
pMenuControl(MenuControl&);
|
||||
|
||||
/* internal */
|
||||
virtual GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
void pMenuGroup::create(const char *text) {
|
||||
group = gtk_menu_new();
|
||||
item = gtk_menu_item_new_with_label(text ? text : "");
|
||||
set_default_font(item);
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), group);
|
||||
gtk_widget_show(item);
|
||||
}
|
||||
|
||||
void pMenuGroup::attach(MenuControl &menucontrol) {
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(group), menucontrol.p.gtk_handle());
|
||||
}
|
||||
|
||||
pMenuGroup::pMenuGroup(MenuGroup &self_) : pMenuControl(self_), self(self_) {
|
||||
group = 0;
|
||||
item = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuGroup::gtk_handle() {
|
||||
return item;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
class pMenuGroup : public pMenuControl {
|
||||
public:
|
||||
MenuGroup &self;
|
||||
void create(const char *text);
|
||||
void attach(MenuControl &menucontrol);
|
||||
|
||||
pMenuGroup(MenuGroup&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *group;
|
||||
GtkWidget *item;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
void hiro_pmenuitem_tick(pMenuItem *p) {
|
||||
if(p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self));
|
||||
}
|
||||
|
||||
void pMenuItem::create(const char *text) {
|
||||
item = gtk_menu_item_new_with_label(text ? text : "");
|
||||
set_default_font(item);
|
||||
g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(hiro_pmenuitem_tick), (gpointer)this);
|
||||
gtk_widget_show(item);
|
||||
}
|
||||
|
||||
pMenuItem::pMenuItem(MenuItem &self_) : pMenuControl(self_), self(self_) {
|
||||
item = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuItem::gtk_handle() {
|
||||
return item;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
class pMenuItem : public pMenuControl {
|
||||
public:
|
||||
void create(const char *text = "");
|
||||
|
||||
MenuItem &self;
|
||||
pMenuItem(MenuItem&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *item;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
void hiro_pmenuradioitem_tick(pMenuRadioItem *p) {
|
||||
//GTK+ sends two messages: one for the activated radio item,
|
||||
//and one for the deactivated radio item. ignore the latter.
|
||||
if(!p->locked && p->checked() && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self));
|
||||
}
|
||||
|
||||
void pMenuRadioItem::create(MenuRadioItemGroup &group, const char *text) {
|
||||
if(group.size() == 0 || group[0] == &self) {
|
||||
item = gtk_radio_menu_item_new_with_label(0, text ? text : "?");
|
||||
} else {
|
||||
item = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(group[0]->p.gtk_handle()), text ? text : "");
|
||||
}
|
||||
set_default_font(item);
|
||||
gtk_widget_show(item);
|
||||
g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(hiro_pmenuradioitem_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pMenuRadioItem::check() {
|
||||
locked = true;
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
|
||||
locked = false;
|
||||
}
|
||||
|
||||
bool pMenuRadioItem::checked() {
|
||||
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
|
||||
}
|
||||
|
||||
pMenuRadioItem::pMenuRadioItem(MenuRadioItem &self_) : pMenuControl(self_), self(self_) {
|
||||
item = 0;
|
||||
locked = false;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuRadioItem::gtk_handle() {
|
||||
return item;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
class pMenuRadioItem : public pMenuControl {
|
||||
public:
|
||||
void create(MenuRadioItemGroup &group, const char *text = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
MenuRadioItem &self;
|
||||
pMenuRadioItem(MenuRadioItem&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget* gtk_handle();
|
||||
GtkWidget *item;
|
||||
bool locked;
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
void pMenuSeparator::create() {
|
||||
item = gtk_separator_menu_item_new();
|
||||
gtk_widget_show(item);
|
||||
}
|
||||
|
||||
pMenuSeparator::pMenuSeparator(MenuSeparator &self_) : pMenuControl(self_), self(self_) {
|
||||
item = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuSeparator::gtk_handle() {
|
||||
return item;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
class pMenuSeparator : public pMenuControl {
|
||||
public:
|
||||
MenuSeparator &self;
|
||||
void create();
|
||||
|
||||
pMenuSeparator(MenuSeparator&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *item;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
char* userpath(char *output) {
|
||||
struct passwd *userinfo = getpwuid(getuid());
|
||||
if(userinfo) { strcpy(output, userinfo->pw_dir); }
|
||||
return output;
|
||||
}
|
||||
|
||||
int mkdir(const char *path) {
|
||||
return mkdir(path, 0755);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
gtk_init(&argc, &argv);
|
||||
libhiro::hiro().init();
|
||||
int result = hiromain(argc, argv);
|
||||
libhiro::hiro().term();
|
||||
return result;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
void pProgressbar::create(unsigned style, unsigned width, unsigned height) {
|
||||
progressbar = gtk_progress_bar_new();
|
||||
gtk_widget_set_size_request(progressbar, width, height);
|
||||
gtk_widget_show(progressbar);
|
||||
}
|
||||
|
||||
unsigned pProgressbar::get_progress() {
|
||||
unsigned progress = (unsigned)(gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progressbar)) * 100.0);
|
||||
return max(0U, min(progress, 100U));
|
||||
}
|
||||
|
||||
void pProgressbar::set_progress(unsigned progress) {
|
||||
progress = max(0U, min(progress, 100U));
|
||||
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), (double)progress / 100.0);
|
||||
}
|
||||
|
||||
pProgressbar::pProgressbar(Progressbar &self_) : pFormControl(self_), self(self_) {
|
||||
progressbar = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pProgressbar::gtk_handle() {
|
||||
return progressbar;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
class pProgressbar : public pFormControl {
|
||||
public:
|
||||
Progressbar &self;
|
||||
void create(unsigned style, unsigned width, unsigned height);
|
||||
unsigned get_progress();
|
||||
void set_progress(unsigned progress);
|
||||
|
||||
pProgressbar(Progressbar&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *progressbar;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,43 +0,0 @@
|
|||
void hiro_pradiobox_tick(pRadiobox *p) {
|
||||
//GTK+ sends two messages: one for the activated radiobox,
|
||||
//and one for the deactivated radiobox. ignore the latter.
|
||||
if(!p->locked && p->checked() && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self));
|
||||
}
|
||||
|
||||
void pRadiobox::create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
if(group.size() == 0 || group[0] == &self) {
|
||||
radiobox = gtk_radio_button_new_with_label(0, text ? text : "");
|
||||
} else {
|
||||
radiobox = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(group[0]->p.gtk_handle()), text ? text : "");
|
||||
}
|
||||
set_default_font(radiobox);
|
||||
gtk_widget_set_size_request(radiobox, width, height);
|
||||
gtk_widget_show(radiobox);
|
||||
g_signal_connect_swapped(G_OBJECT(radiobox), "toggled", G_CALLBACK(hiro_pradiobox_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pRadiobox::set_text(const char *text) {
|
||||
if(!radiobox) return;
|
||||
gtk_button_set_label(GTK_BUTTON(radiobox), text ? text : "");
|
||||
}
|
||||
|
||||
void pRadiobox::check() {
|
||||
locked = true;
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobox), TRUE);
|
||||
locked = false;
|
||||
}
|
||||
|
||||
bool pRadiobox::checked() {
|
||||
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radiobox));
|
||||
}
|
||||
|
||||
pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self), self(self_) {
|
||||
radiobox = 0;
|
||||
locked = false;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pRadiobox::gtk_handle() {
|
||||
return radiobox;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
class pRadiobox : public pFormControl {
|
||||
public:
|
||||
void create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
Radiobox &self;
|
||||
pRadiobox(Radiobox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget* gtk_handle();
|
||||
GtkWidget *radiobox;
|
||||
bool locked;
|
||||
};
|
|
@ -1,36 +0,0 @@
|
|||
void hiro_pslider_change(pSlider *p) {
|
||||
if(p->slider_position == p->get_position()) return;
|
||||
if(p->self.on_change) p->self.on_change(event_t(event_t::Change, p->slider_position = p->get_position(), &p->self));
|
||||
}
|
||||
|
||||
void pSlider::create(unsigned style, unsigned width, unsigned height, unsigned length) {
|
||||
if(length < 1) length = 1;
|
||||
if(style & Slider::Vertical) {
|
||||
slider = gtk_vscale_new_with_range(0, length - 1, 1);
|
||||
} else {
|
||||
slider = gtk_hscale_new_with_range(0, length - 1, 1);
|
||||
}
|
||||
gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE);
|
||||
gtk_widget_set_size_request(slider, width, height);
|
||||
gtk_widget_show(slider);
|
||||
g_signal_connect_swapped(G_OBJECT(slider), "value-changed", G_CALLBACK(hiro_pslider_change), (gpointer)this);
|
||||
}
|
||||
|
||||
unsigned pSlider::get_position() {
|
||||
return (unsigned)gtk_range_get_value(GTK_RANGE(slider));
|
||||
}
|
||||
|
||||
void pSlider::set_position(unsigned position) {
|
||||
gtk_range_set_value(GTK_RANGE(slider), position);
|
||||
}
|
||||
|
||||
pSlider::pSlider(Slider &self_) : pFormControl(self_), self(self_) {
|
||||
slider = 0;
|
||||
slider_position = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pSlider::gtk_handle() {
|
||||
return slider;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
class pSlider : public pFormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, unsigned length);
|
||||
unsigned get_position();
|
||||
void set_position(unsigned position);
|
||||
|
||||
Slider &self;
|
||||
pSlider(Slider&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *slider;
|
||||
unsigned slider_position;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
void pWidget::show(bool state) {
|
||||
state ? gtk_widget_show(gtk_handle()) : gtk_widget_hide(gtk_handle());
|
||||
}
|
||||
|
||||
void pWidget::hide() {
|
||||
show(false);
|
||||
}
|
||||
|
||||
bool pWidget::visible() {
|
||||
return GTK_WIDGET_VISIBLE(gtk_handle());
|
||||
}
|
||||
|
||||
uintptr_t pWidget::handle() {
|
||||
return GDK_WINDOW_XID(gtk_handle()->window);
|
||||
}
|
||||
|
||||
pWidget::pWidget(Widget &self_) : self(self_) {
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pWidget::gtk_handle() {
|
||||
return 0;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
class pWidget {
|
||||
public:
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
uintptr_t handle();
|
||||
|
||||
Widget &self;
|
||||
pWidget(Widget&);
|
||||
|
||||
/* internal */
|
||||
virtual GtkWidget* gtk_handle();
|
||||
};
|
|
@ -1,325 +0,0 @@
|
|||
static gint hiro_pwindow_close(pWindow *p) {
|
||||
uintptr_t r = p->self.on_close ? p->self.on_close(event_t(event_t::Close, 0, &p->self)) : true;
|
||||
return !bool(r);
|
||||
}
|
||||
|
||||
static gboolean hiro_pwindow_expose(pWindow *p) {
|
||||
cairo_t *context = gdk_cairo_create(p->window->window);
|
||||
GtkStyle *style = gtk_widget_get_style(p->window);
|
||||
|
||||
double red = double(style->bg[GTK_STATE_NORMAL].red) / 65536.0;
|
||||
double green = double(style->bg[GTK_STATE_NORMAL].green) / 65536.0;
|
||||
double blue = double(style->bg[GTK_STATE_NORMAL].blue) / 65536.0;
|
||||
double alpha = double(p->state.alpha) / 256.0;
|
||||
|
||||
if(phiro().is_composited == true) {
|
||||
cairo_set_source_rgba(context, red, green, blue, alpha);
|
||||
} else {
|
||||
cairo_set_source_rgb(context, red, green, blue);
|
||||
}
|
||||
|
||||
cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint(context);
|
||||
cairo_destroy(context);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint hiro_pwindow_keydown(GtkWidget *w, GdkEventKey *key, pWindow *p) {
|
||||
if(p && p->self.on_input) {
|
||||
p->self.on_input(event_t(event_t::Input,
|
||||
phiro().translate_key(key->keyval) + (1 << 16),
|
||||
&p->self));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint hiro_pwindow_keyup(GtkWidget *w, GdkEventKey *key, pWindow *p) {
|
||||
if(p && p->self.on_input) {
|
||||
p->self.on_input(event_t(event_t::Input,
|
||||
phiro().translate_key(key->keyval) + (0 << 16),
|
||||
&p->self));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void pWindow::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_widget_set_colormap(window, phiro().colormap);
|
||||
|
||||
gtk_window_set_title(GTK_WINDOW(window), text ? text : "");
|
||||
gtk_window_set_resizable(GTK_WINDOW(window), false);
|
||||
gtk_widget_set_app_paintable(window, true);
|
||||
if(style & Window::AutoCenter) gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
|
||||
g_signal_connect_swapped(G_OBJECT(window), "delete_event", G_CALLBACK(hiro_pwindow_close), (gpointer)this);
|
||||
g_signal_connect_swapped(G_OBJECT(window), "expose_event", G_CALLBACK(hiro_pwindow_expose), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(hiro_pwindow_keydown), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(hiro_pwindow_keyup), (gpointer)this);
|
||||
|
||||
menucontainer = gtk_vbox_new(false, 0);
|
||||
gtk_container_add(GTK_CONTAINER(window), menucontainer);
|
||||
gtk_widget_show(menucontainer);
|
||||
|
||||
menubar = gtk_menu_bar_new();
|
||||
gtk_box_pack_start(GTK_BOX(menucontainer), menubar, false, false, 0);
|
||||
|
||||
formcontainer = gtk_fixed_new();
|
||||
gtk_widget_set_size_request(formcontainer, width, height);
|
||||
gtk_box_pack_start(GTK_BOX(menucontainer), formcontainer, true, true, 0);
|
||||
gtk_widget_show(formcontainer);
|
||||
|
||||
//GTK+ statusbar background can be transparent, depending upon GTK+ theme
|
||||
//therefore, pack statusbar inside an event box, which always has a background
|
||||
//this allows pWindow::set_background_color() to change the window color,
|
||||
//without affecting the statusbar color
|
||||
statuscontainer = gtk_event_box_new();
|
||||
statusbar = gtk_statusbar_new();
|
||||
set_default_font(statusbar);
|
||||
gtk_container_add(GTK_CONTAINER(statuscontainer), statusbar);
|
||||
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusbar), false);
|
||||
gtk_box_pack_start(GTK_BOX(menucontainer), statuscontainer, false, false, 0);
|
||||
gtk_widget_show(statuscontainer);
|
||||
|
||||
gtk_widget_realize(window);
|
||||
state.is_fullscreen = false;
|
||||
state.width = width;
|
||||
state.height = height;
|
||||
}
|
||||
|
||||
void pWindow::close() {
|
||||
gtk_widget_destroy(window);
|
||||
}
|
||||
|
||||
void pWindow::move(unsigned x, unsigned y) {
|
||||
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE);
|
||||
gtk_window_move(GTK_WINDOW(window), x, y);
|
||||
}
|
||||
|
||||
void pWindow::resize(unsigned width, unsigned height) {
|
||||
gtk_widget_set_size_request(formcontainer, width, height);
|
||||
state.width = width;
|
||||
state.height = height;
|
||||
}
|
||||
|
||||
void pWindow::focus() {
|
||||
gtk_window_present(GTK_WINDOW(window));
|
||||
}
|
||||
|
||||
bool pWindow::focused() {
|
||||
return gtk_window_is_active(GTK_WINDOW(window));
|
||||
}
|
||||
|
||||
//gtk_window_(un/)fullscreen() alone does not work well on certain WMs, such as Openbox.
|
||||
//sometimes, the window will not resize (but will move to the top left.)
|
||||
//sometimes, the window decorations will not disappear.
|
||||
//therefore, to be safe, perform some manual window adjustments as well
|
||||
|
||||
void pWindow::fullscreen() {
|
||||
if(state.is_fullscreen == true) return;
|
||||
state.is_fullscreen = true;
|
||||
|
||||
gtk_window_fullscreen(GTK_WINDOW(window));
|
||||
gtk_window_set_decorated(GTK_WINDOW(window), false);
|
||||
gtk_widget_set_size_request(window, gdk_screen_width(), gdk_screen_height());
|
||||
}
|
||||
|
||||
//note that the size of the window is bound to be at least the size of the formcontainer.
|
||||
//this is why the window size is set to -1, -1 below, so that it becomes the minimum
|
||||
//needed to display all of the formcontainer.
|
||||
|
||||
void pWindow::unfullscreen() {
|
||||
if(state.is_fullscreen == false) return;
|
||||
state.is_fullscreen = false;
|
||||
|
||||
gtk_widget_set_size_request(formcontainer, state.width, state.height);
|
||||
gtk_widget_set_size_request(window, -1, -1);
|
||||
gtk_window_set_decorated(GTK_WINDOW(window), true);
|
||||
gtk_window_unfullscreen(GTK_WINDOW(window));
|
||||
}
|
||||
|
||||
//gtk_widget_size_request() on a window immediately after gtk_window_(un/)fullscreen()
|
||||
//is unreliable, as it will usually report the previous window size.
|
||||
//therefore, calculate it manually by using state information.
|
||||
|
||||
unsigned pWindow::get_width() {
|
||||
if(state.is_fullscreen == false) return state.width;
|
||||
return gdk_screen_width();
|
||||
}
|
||||
|
||||
unsigned pWindow::get_height() {
|
||||
if(state.is_fullscreen == false) return state.height;
|
||||
unsigned height = gdk_screen_height();
|
||||
|
||||
//do not include menubar height in client area height
|
||||
if(menu.visible()) {
|
||||
GtkRequisition req;
|
||||
gtk_widget_size_request(menubar, &req);
|
||||
height -= req.height;
|
||||
}
|
||||
|
||||
//do not include statusbar height in client area height
|
||||
if(status.visible()) {
|
||||
GtkRequisition req;
|
||||
gtk_widget_size_request(statusbar, &req);
|
||||
height -= req.height;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
void pWindow::set_opacity(uint8_t opacity) {
|
||||
state.alpha = opacity;
|
||||
if(window) gtk_widget_queue_draw(window);
|
||||
}
|
||||
|
||||
void pWindow::set_background_color(uint8_t r, uint8_t g, uint8_t b) {
|
||||
GdkColor color;
|
||||
color.pixel = (r << 16) | (g << 8) | b;
|
||||
color.red = (r << 8) | r;
|
||||
color.green = (g << 8) | g;
|
||||
color.blue = (b << 8) | b;
|
||||
gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);
|
||||
}
|
||||
|
||||
void pWindow::set_icon(unsigned width, unsigned height, const uint32_t *data) {
|
||||
uint8_t *temp = (uint8_t*)malloc(width * height * 4);
|
||||
memcpy(temp, data, width * height * 4);
|
||||
for(unsigned i = 0; i < width * height; i++) {
|
||||
//ABGR -> ARGB
|
||||
uint8_t t = temp[i * 4 + 0];
|
||||
temp[i * 4 + 0] = temp[i * 4 + 2];
|
||||
temp[i * 4 + 2] = t;
|
||||
}
|
||||
|
||||
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(
|
||||
(const guchar*)temp, GDK_COLORSPACE_RGB,
|
||||
/* has_alpha = */ TRUE, /* bits_per_sample = */ 8,
|
||||
width, height, /* rowstride = */ width * 4,
|
||||
/* destroy_fn = */ NULL, /* destroy_fn_data = */ NULL
|
||||
);
|
||||
gtk_window_set_icon(GTK_WINDOW(window), pixbuf);
|
||||
|
||||
g_object_unref(pixbuf);
|
||||
free(temp);
|
||||
}
|
||||
|
||||
void pWindow::set_text(const char *text) {
|
||||
gtk_window_set_title(GTK_WINDOW(window), text ? text : "");
|
||||
}
|
||||
|
||||
void pWindow::attach(Window &window, unsigned x, unsigned y) {
|
||||
window.p.owner = this;
|
||||
|
||||
//GTK+ does not support attaching a window to another window,
|
||||
//so instead reparent the container from the child window to
|
||||
//the parent window, and reposition the child window's container
|
||||
gtk_widget_hide(window.p.window);
|
||||
gtk_widget_hide(window.p.formcontainer);
|
||||
gtk_widget_reparent(window.p.formcontainer, formcontainer);
|
||||
gtk_fixed_move(GTK_FIXED(formcontainer), window.p.formcontainer, x, y);
|
||||
gtk_widget_show(window.p.formcontainer);
|
||||
}
|
||||
|
||||
void pWindow::attach(MenuGroup &menugroup) {
|
||||
gtk_menu_bar_append(menubar, menugroup.p.item);
|
||||
gtk_widget_show(menubar);
|
||||
}
|
||||
|
||||
void pWindow::attach(FormControl &formcontrol, unsigned x, unsigned y) {
|
||||
gtk_fixed_put(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y);
|
||||
}
|
||||
|
||||
void pWindow::move(Window &window, unsigned x, unsigned y) {
|
||||
gtk_fixed_move(GTK_FIXED(formcontainer), window.p.gtk_handle(), x, y);
|
||||
}
|
||||
|
||||
void pWindow::move(FormControl &formcontrol, unsigned x, unsigned y) {
|
||||
gtk_fixed_move(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y);
|
||||
}
|
||||
|
||||
/* pWindow -> Menubar */
|
||||
|
||||
void pWindow::Menubar::show(bool state) {
|
||||
p.menu_show(state);
|
||||
}
|
||||
|
||||
void pWindow::Menubar::hide() {
|
||||
p.menu_hide();
|
||||
}
|
||||
|
||||
bool pWindow::Menubar::visible() {
|
||||
return p.menu_visible();
|
||||
}
|
||||
|
||||
pWindow::Menubar::Menubar(pWindow &p_) : p(p_) {
|
||||
}
|
||||
|
||||
/* pWindow -> Statusbar */
|
||||
|
||||
void pWindow::Statusbar::set_text(const char *text) {
|
||||
p.status_set_text(text);
|
||||
}
|
||||
|
||||
void pWindow::Statusbar::show(bool state) {
|
||||
p.status_show(state);
|
||||
}
|
||||
|
||||
void pWindow::Statusbar::hide() {
|
||||
p.status_hide();
|
||||
}
|
||||
|
||||
bool pWindow::Statusbar::visible() {
|
||||
return p.status_visible();
|
||||
}
|
||||
|
||||
pWindow::Statusbar::Statusbar(pWindow &p_) : p(p_) {
|
||||
}
|
||||
|
||||
pWindow::pWindow(Window &self_) : pWidget(self_), self(self_), menu(*this), status(*this) {
|
||||
owner = 0;
|
||||
window = 0;
|
||||
menubar = 0;
|
||||
statusbar = 0;
|
||||
menucontainer = 0;
|
||||
formcontainer = 0;
|
||||
statuscontainer = 0;
|
||||
|
||||
state.is_fullscreen = false;
|
||||
state.width = 0;
|
||||
state.height = 0;
|
||||
state.alpha = 255;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pWindow::gtk_handle() {
|
||||
return owner ? formcontainer : window;
|
||||
}
|
||||
|
||||
void pWindow::menu_show(bool state) {
|
||||
state ? gtk_widget_show(menubar) : gtk_widget_hide(menubar);
|
||||
}
|
||||
|
||||
void pWindow::menu_hide() {
|
||||
menu_show(false);
|
||||
}
|
||||
|
||||
bool pWindow::menu_visible() {
|
||||
return GTK_WIDGET_VISIBLE(menubar);
|
||||
}
|
||||
|
||||
void pWindow::status_set_text(const char *text) {
|
||||
gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1);
|
||||
gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, text ? text : "");
|
||||
}
|
||||
|
||||
void pWindow::status_show(bool state) {
|
||||
state ? gtk_widget_show(statusbar) : gtk_widget_hide(statusbar);
|
||||
}
|
||||
|
||||
void pWindow::status_hide() {
|
||||
status_show(false);
|
||||
}
|
||||
|
||||
bool pWindow::status_visible() {
|
||||
return GTK_WIDGET_VISIBLE(statusbar);
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
class pWindow : public pWidget {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void close();
|
||||
void move(unsigned x, unsigned y);
|
||||
void resize(unsigned width, unsigned height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void fullscreen();
|
||||
void unfullscreen();
|
||||
unsigned get_width();
|
||||
unsigned get_height();
|
||||
void set_opacity(uint8_t opacity);
|
||||
void set_background_color(uint8_t r, uint8_t g, uint8_t b);
|
||||
void set_icon(unsigned width, unsigned height, const uint32_t *data);
|
||||
void set_text(const char *text = "");
|
||||
void attach(Window &window, unsigned x, unsigned y);
|
||||
void attach(MenuGroup &menugroup);
|
||||
void attach(FormControl &formcontrol, unsigned x, unsigned y);
|
||||
void move(Window &window, unsigned x, unsigned y);
|
||||
void move(FormControl &formcontrol, unsigned x, unsigned y);
|
||||
|
||||
class Statusbar {
|
||||
public:
|
||||
void set_text(const char *text = "");
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
pWindow &p;
|
||||
Statusbar(pWindow&);
|
||||
} status;
|
||||
|
||||
class Menubar {
|
||||
public:
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
pWindow &p;
|
||||
Menubar(pWindow&);
|
||||
} menu;
|
||||
|
||||
Window &self;
|
||||
pWindow(Window&);
|
||||
|
||||
/* internal */
|
||||
pWindow *owner; //0 = no owner (default)
|
||||
GtkWidget *window;
|
||||
GtkWidget *menubar;
|
||||
GtkWidget *statusbar;
|
||||
GtkWidget *menucontainer;
|
||||
GtkWidget *formcontainer;
|
||||
GtkWidget *statuscontainer;
|
||||
GtkWidget* gtk_handle();
|
||||
struct {
|
||||
bool is_fullscreen;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned alpha;
|
||||
} state;
|
||||
|
||||
void menu_show(bool = true);
|
||||
void menu_hide();
|
||||
bool menu_visible();
|
||||
|
||||
void status_set_text(const char *text = "");
|
||||
void status_show(bool = true);
|
||||
void status_hide();
|
||||
bool status_visible();
|
||||
};
|
|
@ -1,274 +0,0 @@
|
|||
#include "hiro.hpp"
|
||||
using namespace nall;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "win/hiro.cpp"
|
||||
#else
|
||||
#include "gtk/hiro.cpp"
|
||||
#endif
|
||||
|
||||
namespace libhiro {
|
||||
|
||||
/* Hiro (singleton) */
|
||||
|
||||
void Hiro::init() { p.init(); }
|
||||
void Hiro::term() { p.term(); }
|
||||
bool Hiro::run() { return p.run(); }
|
||||
bool Hiro::pending() { return p.pending(); }
|
||||
bool Hiro::folder_select(Window *focus, char *filename, const char *path) { return p.folder_select(focus, filename, path); }
|
||||
bool Hiro::file_open(Window *focus, char *filename, const char *path, const char *filter) { return p.file_open(focus, filename, path, filter); }
|
||||
bool Hiro::file_save(Window *focus, char *filename, const char *path, const char *filter) { return p.file_save(focus, filename, path, filter); }
|
||||
unsigned Hiro::screen_width() { return p.screen_width(); }
|
||||
unsigned Hiro::screen_height() { return p.screen_height(); }
|
||||
void Hiro::enable_screensaver() { p.enable_screensaver(); }
|
||||
void Hiro::disable_screensaver() { p.disable_screensaver(); }
|
||||
Hiro& Hiro::handle() { static Hiro hiro; return hiro; }
|
||||
Hiro::Hiro() : p(*new pHiro(*this)) {}
|
||||
Hiro::~Hiro() { delete &p; }
|
||||
Hiro& hiro() { return Hiro::handle(); }
|
||||
|
||||
/* Widget */
|
||||
|
||||
void Widget::show(bool state) { p.show(state); }
|
||||
void Widget::hide() { p.hide(); }
|
||||
bool Widget::visible() { return p.visible(); }
|
||||
uintptr_t Widget::handle() { return p.handle(); }
|
||||
Widget::Widget() : p(*new pWidget(*this)) { type = WidgetType; }
|
||||
Widget::Widget(pWidget &p_) : p(p_) { type = WidgetType; }
|
||||
Widget::~Widget() { delete &p; }
|
||||
|
||||
/* Widget -> Window */
|
||||
|
||||
void Window::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||
void Window::close() { p.close(); }
|
||||
void Window::move(unsigned x, unsigned y) { p.move(x, y); }
|
||||
void Window::resize(unsigned width, unsigned height) { p.resize(width, height); }
|
||||
void Window::focus() { p.focus(); }
|
||||
bool Window::focused() { return p.focused(); }
|
||||
void Window::fullscreen() { p.fullscreen(); }
|
||||
void Window::unfullscreen() { p.unfullscreen(); }
|
||||
unsigned Window::get_width() { return p.get_width(); }
|
||||
unsigned Window::get_height() { return p.get_height(); }
|
||||
void Window::set_opacity(uint8_t opacity) { p.set_opacity(opacity); }
|
||||
void Window::set_background_color(uint8_t r, uint8_t g, uint8_t b) { p.set_background_color(r, g, b); }
|
||||
void Window::set_icon(unsigned width, unsigned height, const uint32_t *data) { p.set_icon(width, height, data); }
|
||||
void Window::set_text(const char *text) { p.set_text(text); }
|
||||
void Window::attach(Window &window, unsigned x, unsigned y) { p.attach(window, x, y); }
|
||||
void Window::attach(MenuGroup &menugroup) { p.attach(menugroup); }
|
||||
void Window::attach(FormControl &formcontrol, unsigned x, unsigned y) { p.attach(formcontrol, x, y); }
|
||||
void Window::move(Window &window, unsigned x, unsigned y) { p.move(window, x, y); }
|
||||
void Window::move(FormControl &formcontrol, unsigned x, unsigned y) { p.move(formcontrol, x, y); }
|
||||
|
||||
void Window::Menubar::show(bool state) { p.menu.show(state); }
|
||||
void Window::Menubar::hide() { p.menu.hide(); }
|
||||
bool Window::Menubar::visible() { return p.menu.visible(); }
|
||||
Window::Menubar::Menubar(pWindow &p_) : p(p_) {}
|
||||
|
||||
void Window::Statusbar::set_text(const char *text) { p.status.set_text(text); }
|
||||
void Window::Statusbar::show(bool state) { p.status.show(state); }
|
||||
void Window::Statusbar::hide() { p.status.hide(); }
|
||||
bool Window::Statusbar::visible() { return p.status.visible(); }
|
||||
Window::Statusbar::Statusbar(pWindow &p_) : p(p_) {}
|
||||
|
||||
Window::Window() :
|
||||
base_from_member<pWindow&>(*new pWindow(*this)),
|
||||
Widget(base_from_member<pWindow&>::value),
|
||||
p(base_from_member<pWindow&>::value),
|
||||
menu(base_from_member<pWindow&>::value),
|
||||
status(base_from_member<pWindow&>::value) { type = WindowType; }
|
||||
|
||||
/* Widget -> MenuControl */
|
||||
|
||||
void MenuControl::enable(bool state) { p.enable(state); }
|
||||
void MenuControl::disable() { p.disable(); }
|
||||
bool MenuControl::enabled() { return p.enabled(); }
|
||||
MenuControl::MenuControl() :
|
||||
base_from_member<pMenuControl&>(*new pMenuControl(*this)),
|
||||
Widget(base_from_member<pMenuControl&>::value),
|
||||
p(base_from_member<pMenuControl&>::value) { type = MenuControlType; }
|
||||
MenuControl::MenuControl(pMenuControl &p_) :
|
||||
base_from_member<pMenuControl&>(p_),
|
||||
Widget(base_from_member<pMenuControl&>::value),
|
||||
p(base_from_member<pMenuControl&>::value) { type = MenuControlType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuGroup */
|
||||
|
||||
MenuGroup& MenuGroup::create(const char *text) { p.create(text); return *this; }
|
||||
void MenuGroup::attach(MenuControl &menucontrol) { p.attach(menucontrol); }
|
||||
MenuGroup::MenuGroup() :
|
||||
base_from_member<pMenuGroup&>(*new pMenuGroup(*this)),
|
||||
MenuControl(base_from_member<pMenuGroup&>::value),
|
||||
p(base_from_member<pMenuGroup&>::value) { type = MenuGroupType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuItem */
|
||||
|
||||
MenuItem& MenuItem::create(const char *text) { p.create(text); return *this; }
|
||||
MenuItem::MenuItem() :
|
||||
base_from_member<pMenuItem&>(*new pMenuItem(*this)),
|
||||
MenuControl(base_from_member<pMenuItem&>::value),
|
||||
p(base_from_member<pMenuItem&>::value) { type = MenuItemType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuCheckItem */
|
||||
|
||||
MenuCheckItem& MenuCheckItem::create(const char *text) { p.create(text); return *this; }
|
||||
void MenuCheckItem::check(bool state) { state ? p.check() : p.uncheck(); }
|
||||
void MenuCheckItem::uncheck() { p.uncheck(); }
|
||||
bool MenuCheckItem::checked() { return p.checked(); }
|
||||
MenuCheckItem::MenuCheckItem() :
|
||||
base_from_member<pMenuCheckItem&>(*new pMenuCheckItem(*this)),
|
||||
MenuControl(base_from_member<pMenuCheckItem&>::value),
|
||||
p(base_from_member<pMenuCheckItem&>::value) { type = MenuCheckItemType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuRadioItem */
|
||||
|
||||
MenuRadioItem& MenuRadioItem::create(MenuRadioItemGroup &group, const char *text) { p.create(group, text); return *this; }
|
||||
void MenuRadioItem::check() { p.check(); }
|
||||
bool MenuRadioItem::checked() { return p.checked(); }
|
||||
MenuRadioItem::MenuRadioItem() :
|
||||
base_from_member<pMenuRadioItem&>(*new pMenuRadioItem(*this)),
|
||||
MenuControl(base_from_member<pMenuRadioItem&>::value),
|
||||
p(base_from_member<pMenuRadioItem&>::value) { type = MenuRadioItemType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuSeparator */
|
||||
|
||||
MenuSeparator& MenuSeparator::create() { p.create(); return *this; }
|
||||
MenuSeparator::MenuSeparator() :
|
||||
base_from_member<pMenuSeparator&>(*new pMenuSeparator(*this)),
|
||||
MenuControl(base_from_member<pMenuSeparator&>::value),
|
||||
p(base_from_member<pMenuSeparator&>::value) { type = MenuSeparatorType; }
|
||||
|
||||
/* Widget -> FormControl */
|
||||
|
||||
void FormControl::resize(unsigned width, unsigned height) { p.resize(width, height); }
|
||||
void FormControl::focus() { p.focus(); }
|
||||
bool FormControl::focused() { return p.focused(); }
|
||||
void FormControl::enable(bool state) { p.enable(state); }
|
||||
void FormControl::disable() { p.disable(); }
|
||||
bool FormControl::enabled() { return p.enabled(); }
|
||||
FormControl::FormControl() :
|
||||
base_from_member<pFormControl&>(*new pFormControl(*this)),
|
||||
Widget(base_from_member<pFormControl&>::value),
|
||||
p(base_from_member<pFormControl&>::value) { type = FormControlType; }
|
||||
FormControl::FormControl(pFormControl &p_) :
|
||||
base_from_member<pFormControl&>(p_),
|
||||
Widget(base_from_member<pFormControl&>::value),
|
||||
p(base_from_member<pFormControl&>::value) { type = FormControlType; }
|
||||
|
||||
/* Widget -> FormControl -> Frame */
|
||||
|
||||
void Frame::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||
void Frame::set_text(const char *text) { p.set_text(text); }
|
||||
Frame::Frame() :
|
||||
base_from_member<pFrame&>(*new pFrame(*this)),
|
||||
FormControl(base_from_member<pFrame&>::value),
|
||||
p(base_from_member<pFrame&>::value) { type = FrameType; }
|
||||
|
||||
/* Widget -> FormControl -> Canvas */
|
||||
|
||||
void Canvas::create(unsigned style, unsigned width, unsigned height) { p.create(style, width, height); }
|
||||
void Canvas::redraw() { p.redraw(); }
|
||||
uint32_t* Canvas::buffer() { return p.buffer(); }
|
||||
Canvas::Canvas() :
|
||||
base_from_member<pCanvas&>(*new pCanvas(*this)),
|
||||
FormControl(base_from_member<pCanvas&>::value),
|
||||
p(base_from_member<pCanvas&>::value) { type = CanvasType; }
|
||||
|
||||
/* Widget -> FormControl -> Label */
|
||||
|
||||
void Label::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||
void Label::set_text(const char *text) { p.set_text(text); }
|
||||
Label::Label() :
|
||||
base_from_member<pLabel&>(*new pLabel(*this)),
|
||||
FormControl(base_from_member<pLabel&>::value),
|
||||
p(base_from_member<pLabel&>::value) { type = LabelType; }
|
||||
|
||||
/* Widget -> FormControl -> Button */
|
||||
|
||||
void Button::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||
void Button::set_text(const char *text) { p.set_text(text); }
|
||||
Button::Button() :
|
||||
base_from_member<pButton&>(*new pButton(*this)),
|
||||
FormControl(base_from_member<pButton&>::value),
|
||||
p(base_from_member<pButton&>::value) { type = ButtonType; }
|
||||
|
||||
/* Widget -> FormControl -> Checkbox */
|
||||
|
||||
void Checkbox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||
void Checkbox::set_text(const char *text) { p.set_text(text); }
|
||||
void Checkbox::check(bool state) { state ? p.check() : p.uncheck(); }
|
||||
void Checkbox::uncheck() { p.uncheck(); }
|
||||
bool Checkbox::checked() { return p.checked(); }
|
||||
Checkbox::Checkbox() :
|
||||
base_from_member<pCheckbox&>(*new pCheckbox(*this)),
|
||||
FormControl(base_from_member<pCheckbox&>::value),
|
||||
p(base_from_member<pCheckbox&>::value) { type = CheckboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Radiobox */
|
||||
|
||||
void Radiobox::create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text) { p.create(group, style, width, height, text); }
|
||||
void Radiobox::set_text(const char *text) { p.set_text(text); }
|
||||
void Radiobox::check() { p.check(); }
|
||||
bool Radiobox::checked() { return p.checked(); }
|
||||
Radiobox::Radiobox() :
|
||||
base_from_member<pRadiobox&>(*new pRadiobox(*this)),
|
||||
FormControl(base_from_member<pRadiobox&>::value),
|
||||
p(base_from_member<pRadiobox&>::value) { type = RadioboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Editbox */
|
||||
|
||||
void Editbox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||
unsigned Editbox::get_text(char *text, unsigned length) { return p.get_text(text, length); }
|
||||
void Editbox::set_text(const char *text) { p.set_text(text); }
|
||||
Editbox::Editbox() :
|
||||
base_from_member<pEditbox&>(*new pEditbox(*this)),
|
||||
FormControl(base_from_member<pEditbox&>::value),
|
||||
p(base_from_member<pEditbox&>::value) { type = EditboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Listbox */
|
||||
|
||||
void Listbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) { p.create(style, width, height, columns, text); }
|
||||
void Listbox::autosize_columns() { p.autosize_columns(); }
|
||||
void Listbox::set_column_width(unsigned column, unsigned width) { p.set_column_width(column, width); }
|
||||
void Listbox::add_item(const char *text) { p.add_item(text); }
|
||||
void Listbox::set_item(unsigned index, const char *text) { p.set_item(index, text); }
|
||||
int Listbox::get_selection() { return p.get_selection(); }
|
||||
void Listbox::set_selection(int index) { p.set_selection(index); }
|
||||
void Listbox::reset() { p.reset(); }
|
||||
Listbox::Listbox() :
|
||||
base_from_member<pListbox&>(*new pListbox(*this)),
|
||||
FormControl(base_from_member<pListbox&>::value),
|
||||
p(base_from_member<pListbox&>::value) { type = ListboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Combobox */
|
||||
|
||||
void Combobox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||
void Combobox::add_item(const char *text) { p.add_item(text); }
|
||||
int Combobox::get_selection() { return p.get_selection(); }
|
||||
void Combobox::set_selection(int index) { p.set_selection(index); }
|
||||
void Combobox::reset() { p.reset(); }
|
||||
Combobox::Combobox() :
|
||||
base_from_member<pCombobox&>(*new pCombobox(*this)),
|
||||
FormControl(base_from_member<pCombobox&>::value),
|
||||
p(base_from_member<pCombobox&>::value) { type = ComboboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Progressbar */
|
||||
|
||||
void Progressbar::create(unsigned style, unsigned width, unsigned height) { p.create(style, width, height); }
|
||||
unsigned Progressbar::get_progress() { return p.get_progress(); }
|
||||
void Progressbar::set_progress(unsigned progress) { p.set_progress(progress); }
|
||||
Progressbar::Progressbar() :
|
||||
base_from_member<pProgressbar&>(*new pProgressbar(*this)),
|
||||
FormControl(base_from_member<pProgressbar&>::value),
|
||||
p(base_from_member<pProgressbar&>::value) { type = ProgressbarType; }
|
||||
|
||||
/* Widget -> FormControl -> Slider */
|
||||
|
||||
void Slider::create(unsigned style, unsigned width, unsigned height, unsigned length) { p.create(style, width, height, length); }
|
||||
unsigned Slider::get_position() { return p.get_position(); }
|
||||
void Slider::set_position(unsigned position) { p.set_position(position); }
|
||||
Slider::Slider() :
|
||||
base_from_member<pSlider&>(*new pSlider(*this)),
|
||||
FormControl(base_from_member<pSlider&>::value),
|
||||
p(base_from_member<pSlider&>::value) { type = SliderType; }
|
||||
|
||||
} //namespace libhiro
|
|
@ -1,538 +0,0 @@
|
|||
/*
|
||||
hiro
|
||||
version: 0.008.1 (2008-11-02)
|
||||
author: byuu
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef HIRO_H
|
||||
#define HIRO_H
|
||||
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/input.hpp>
|
||||
#include <nall/new.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
extern char* realpath(const char*, char*);
|
||||
extern char* userpath(char*);
|
||||
int mkdir(const char*);
|
||||
|
||||
namespace libhiro {
|
||||
|
||||
class pHiro;
|
||||
class pWidget;
|
||||
class pWindow;
|
||||
class pMenuControl;
|
||||
class pMenuGroup;
|
||||
class pMenuItem;
|
||||
class pMenuCheckItem;
|
||||
class pMenuRadioItem;
|
||||
class pMenuSeparator;
|
||||
class pFormControl;
|
||||
class pFrame;
|
||||
class pCanvas;
|
||||
class pLabel;
|
||||
class pButton;
|
||||
class pCheckbox;
|
||||
class pRadiobox;
|
||||
class pEditbox;
|
||||
class pListbox;
|
||||
class pCombobox;
|
||||
class pProgressbar;
|
||||
class pSlider;
|
||||
|
||||
#define pFriends \
|
||||
friend class pHiro; \
|
||||
friend class pWidget; \
|
||||
friend class pWindow; \
|
||||
friend class pMenuControl; \
|
||||
friend class pMenuGroup; \
|
||||
friend class pMenuItem; \
|
||||
friend class pMenuCheckItem; \
|
||||
friend class pMenuRadioItem; \
|
||||
friend class pMenuSeparator; \
|
||||
friend class pFormControl; \
|
||||
friend class pFrame; \
|
||||
friend class pCanvas; \
|
||||
friend class pLabel; \
|
||||
friend class pButton; \
|
||||
friend class pCheckbox; \
|
||||
friend class pRadiobox; \
|
||||
friend class pEditbox; \
|
||||
friend class pListbox; \
|
||||
friend class pCombobox; \
|
||||
friend class pProgressbar; \
|
||||
friend class pSlider
|
||||
|
||||
class Hiro;
|
||||
class Widget;
|
||||
class Window;
|
||||
class MenuControl;
|
||||
class MenuGroup;
|
||||
class MenuItem;
|
||||
class MenuCheckItem;
|
||||
class MenuRadioItem;
|
||||
class MenuSeparator;
|
||||
class FormControl;
|
||||
class Frame;
|
||||
class Canvas;
|
||||
class Label;
|
||||
class Button;
|
||||
class Checkbox;
|
||||
class Radiobox;
|
||||
class Editbox;
|
||||
class Listbox;
|
||||
class Combobox;
|
||||
class Progressbar;
|
||||
class Slider;
|
||||
|
||||
typedef nall::array<MenuRadioItem*> MenuRadioItemGroup;
|
||||
typedef nall::array<Radiobox*> RadioboxGroup;
|
||||
|
||||
struct event_t {
|
||||
enum type_t {
|
||||
Close,
|
||||
Block,
|
||||
Input,
|
||||
Change,
|
||||
Tick,
|
||||
Activate,
|
||||
} type;
|
||||
uintptr_t param;
|
||||
Widget *widget;
|
||||
|
||||
event_t(type_t type_, uintptr_t param_ = 0, Widget *widget_ = 0) :
|
||||
type(type_), param(param_), widget(widget_) {}
|
||||
};
|
||||
|
||||
class Hiro : nall::noncopyable {
|
||||
public:
|
||||
void init();
|
||||
void term();
|
||||
bool run();
|
||||
bool pending();
|
||||
|
||||
bool folder_select(Window *focus, char *filename, const char *path = "");
|
||||
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||
|
||||
unsigned screen_width();
|
||||
unsigned screen_height();
|
||||
|
||||
void enable_screensaver();
|
||||
void disable_screensaver();
|
||||
|
||||
static Hiro& handle();
|
||||
Hiro();
|
||||
~Hiro();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pHiro &p;
|
||||
};
|
||||
|
||||
Hiro& hiro();
|
||||
|
||||
class Widget : nall::noncopyable {
|
||||
public:
|
||||
enum Type {
|
||||
WidgetType,
|
||||
WindowType,
|
||||
MenuControlType,
|
||||
MenuGroupType,
|
||||
MenuItemType,
|
||||
MenuCheckItemType,
|
||||
MenuRadioItemType,
|
||||
MenuSeparatorType,
|
||||
FormControlType,
|
||||
FrameType,
|
||||
CanvasType,
|
||||
LabelType,
|
||||
ButtonType,
|
||||
CheckboxType,
|
||||
RadioboxType,
|
||||
EditboxType,
|
||||
ListboxType,
|
||||
ComboboxType,
|
||||
ProgressbarType,
|
||||
SliderType,
|
||||
} type;
|
||||
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
uintptr_t handle();
|
||||
|
||||
Widget();
|
||||
~Widget();
|
||||
|
||||
protected:
|
||||
Widget(pWidget&);
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pWidget &p;
|
||||
};
|
||||
|
||||
class Window : private nall::base_from_member<pWindow&>, public Widget {
|
||||
public:
|
||||
enum Style {
|
||||
AutoCenter = 1 << 1,
|
||||
};
|
||||
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void close();
|
||||
void move(unsigned x, unsigned y);
|
||||
void resize(unsigned width, unsigned height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void fullscreen();
|
||||
void unfullscreen();
|
||||
unsigned get_width();
|
||||
unsigned get_height();
|
||||
void set_opacity(uint8_t opacity);
|
||||
void set_background_color(uint8_t r, uint8_t g, uint8_t b);
|
||||
void set_icon(unsigned width, unsigned height, const uint32_t *data);
|
||||
void set_status_text(const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void attach(Window &window, unsigned x, unsigned y);
|
||||
void attach(MenuGroup &menugroup);
|
||||
void attach(FormControl &formcontrol, unsigned x, unsigned y);
|
||||
void move(Window &window, unsigned x, unsigned y);
|
||||
void move(FormControl &formcontrol, unsigned x, unsigned y);
|
||||
|
||||
class Menubar {
|
||||
public:
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
pWindow &p;
|
||||
Menubar(pWindow&);
|
||||
} menu;
|
||||
|
||||
class Statusbar {
|
||||
public:
|
||||
void set_text(const char *text = "");
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
pWindow &p;
|
||||
Statusbar(pWindow&);
|
||||
} status;
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_close;
|
||||
nall::function<uintptr_t (event_t)> on_block;
|
||||
nall::function<uintptr_t (event_t)> on_input;
|
||||
|
||||
Window();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pWindow &p;
|
||||
};
|
||||
|
||||
class MenuControl : public nall::base_from_member<pMenuControl&>, public Widget {
|
||||
public:
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
MenuControl();
|
||||
|
||||
protected:
|
||||
MenuControl(pMenuControl&);
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuControl &p;
|
||||
};
|
||||
|
||||
class MenuGroup : public nall::base_from_member<pMenuGroup&>, public MenuControl {
|
||||
public:
|
||||
MenuGroup& create(const char *text);
|
||||
void attach(MenuControl &menucontrol);
|
||||
MenuGroup();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuGroup &p;
|
||||
};
|
||||
|
||||
class MenuItem : public nall::base_from_member<pMenuItem&>, public MenuControl {
|
||||
public:
|
||||
MenuItem& create(const char *text);
|
||||
MenuItem();
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_tick;
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuItem &p;
|
||||
};
|
||||
|
||||
class MenuCheckItem : public nall::base_from_member<pMenuCheckItem&>, public MenuControl {
|
||||
public:
|
||||
MenuCheckItem& create(const char *text);
|
||||
void check(bool = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
MenuCheckItem();
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_tick;
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuCheckItem &p;
|
||||
};
|
||||
|
||||
class MenuRadioItem : public nall::base_from_member<pMenuRadioItem&>, public MenuControl {
|
||||
public:
|
||||
MenuRadioItem& create(MenuRadioItemGroup &group, const char *text);
|
||||
void check();
|
||||
bool checked();
|
||||
MenuRadioItem();
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_tick;
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuRadioItem &p;
|
||||
};
|
||||
|
||||
class MenuSeparator : public nall::base_from_member<pMenuSeparator&>, public MenuControl {
|
||||
public:
|
||||
MenuSeparator& create();
|
||||
MenuSeparator();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuSeparator &p;
|
||||
};
|
||||
|
||||
class FormControl : private nall::base_from_member<pFormControl&>, public Widget {
|
||||
public:
|
||||
void resize(unsigned width, unsigned height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
FormControl();
|
||||
|
||||
protected:
|
||||
FormControl(pFormControl&);
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pFormControl &p;
|
||||
};
|
||||
|
||||
class Frame : private nall::base_from_member<pFrame&>, public FormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
Frame();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pFrame &p;
|
||||
};
|
||||
|
||||
class Canvas : private nall::base_from_member<pCanvas&>, public FormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height);
|
||||
void redraw();
|
||||
uint32_t* buffer();
|
||||
|
||||
Canvas();
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_input;
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pCanvas &p;
|
||||
};
|
||||
|
||||
class Label : private nall::base_from_member<pLabel&>, public FormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
Label();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pLabel &p;
|
||||
};
|
||||
|
||||
class Button : private nall::base_from_member<pButton&>, public FormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_tick;
|
||||
|
||||
Button();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pButton &p;
|
||||
};
|
||||
|
||||
class Checkbox : private nall::base_from_member<pCheckbox&>, public FormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check(bool = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_tick;
|
||||
|
||||
Checkbox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pCheckbox &p;
|
||||
};
|
||||
|
||||
class Radiobox : private nall::base_from_member<pRadiobox&>, public FormControl {
|
||||
public:
|
||||
void create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_tick;
|
||||
|
||||
Radiobox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pRadiobox &p;
|
||||
};
|
||||
|
||||
class Editbox : private nall::base_from_member<pEditbox&>, public FormControl {
|
||||
public:
|
||||
enum Style {
|
||||
Multiline = 1 << 1,
|
||||
Readonly = 1 << 2,
|
||||
|
||||
HorizontalScrollAuto = 0,
|
||||
HorizontalScrollAlways = 1 << 3,
|
||||
HorizontalScrollNever = 1 << 4,
|
||||
|
||||
VerticalScrollAuto = 0,
|
||||
VerticalScrollAlways = 1 << 5,
|
||||
VerticalScrollNever = 1 << 6,
|
||||
};
|
||||
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
unsigned get_text(char *text, unsigned length = -1U);
|
||||
void set_text(const char *text = "");
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_change;
|
||||
|
||||
Editbox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pEditbox &p;
|
||||
};
|
||||
|
||||
class Listbox : private nall::base_from_member<pListbox&>, public FormControl {
|
||||
public:
|
||||
enum Style {
|
||||
Header = 1 << 1,
|
||||
|
||||
HorizontalScrollAuto = 0,
|
||||
HorizontalScrollAlways = 1 << 2,
|
||||
HorizontalScrollNever = 1 << 3,
|
||||
|
||||
VerticalScrollAuto = 0,
|
||||
VerticalScrollAlways = 1 << 4,
|
||||
VerticalScrollNever = 1 << 5,
|
||||
};
|
||||
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = "");
|
||||
void autosize_columns();
|
||||
void set_column_width(unsigned column, unsigned width);
|
||||
void add_item(const char *text);
|
||||
void set_item(unsigned index, const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_change;
|
||||
nall::function<uintptr_t (event_t)> on_activate;
|
||||
|
||||
Listbox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pListbox &p;
|
||||
};
|
||||
|
||||
class Combobox : private nall::base_from_member<pCombobox&>, public FormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void add_item(const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_change;
|
||||
|
||||
Combobox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pCombobox &p;
|
||||
};
|
||||
|
||||
class Progressbar : private nall::base_from_member<pProgressbar&>, public FormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height);
|
||||
unsigned get_progress();
|
||||
void set_progress(unsigned progress);
|
||||
|
||||
Progressbar();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pProgressbar &p;
|
||||
};
|
||||
|
||||
class Slider : private nall::base_from_member<pSlider&>, public FormControl {
|
||||
public:
|
||||
enum Style {
|
||||
Horizontal = 0,
|
||||
Vertical = 1 << 1,
|
||||
};
|
||||
|
||||
void create(unsigned style, unsigned width, unsigned height, unsigned length);
|
||||
unsigned get_position();
|
||||
void set_position(unsigned position);
|
||||
|
||||
nall::function<uintptr_t (event_t)> on_change;
|
||||
|
||||
Slider();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pSlider &p;
|
||||
};
|
||||
|
||||
#undef pFriends
|
||||
|
||||
} //namespace libhiro
|
||||
|
||||
#endif //ifndef HIRO_H
|
|
@ -1,14 +0,0 @@
|
|||
void pButton::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE,
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||
}
|
||||
|
||||
void pButton::set_text(const char *text) {
|
||||
SetWindowText(hwnd, utf16(text));
|
||||
}
|
||||
|
||||
pButton::pButton(Button &self_) : pFormControl(self_), self(self_) {
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
class pButton : public pFormControl {
|
||||
public:
|
||||
Button &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pButton(Button&);
|
||||
};
|
|
@ -1,52 +0,0 @@
|
|||
void pCanvas::create(unsigned style, unsigned width, unsigned height) {
|
||||
hwnd = CreateWindow(L"hiro_window", L"", WS_CHILD,
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
resize(width, height);
|
||||
ShowWindow(hwnd, SW_NORMAL);
|
||||
}
|
||||
|
||||
void pCanvas::redraw() {
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint(hwnd, &ps);
|
||||
SetDIBitsToDevice(ps.hdc, 0, 0, iwidth, iheight, 0, 0, 0, iheight, (void*)ibuffer, &bmi, DIB_RGB_COLORS);
|
||||
EndPaint(hwnd, &ps);
|
||||
InvalidateRect(hwnd, 0, FALSE);
|
||||
}
|
||||
|
||||
uint32_t* pCanvas::buffer() {
|
||||
return ibuffer;
|
||||
}
|
||||
|
||||
pCanvas::pCanvas(Canvas &self_) : pFormControl(self_), self(self_) {
|
||||
ibuffer = 0;
|
||||
ipitch = 0;
|
||||
memset(&bmi, 0, sizeof(BITMAPINFO));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
}
|
||||
|
||||
pCanvas::~pCanvas() {
|
||||
if(ibuffer) free(ibuffer);
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
void pCanvas::resize(unsigned width, unsigned height) {
|
||||
if(ibuffer) free(ibuffer);
|
||||
|
||||
ipitch = width * sizeof(uint32_t);
|
||||
iwidth = width;
|
||||
iheight = height;
|
||||
ibuffer = (uint32_t*)malloc(ipitch * height);
|
||||
memset(ibuffer, 0, ipitch * height);
|
||||
|
||||
bmi.bmiHeader.biWidth = width;
|
||||
bmi.bmiHeader.biHeight = -height; //use negative height to tell GDI not to flip bitmap vertically
|
||||
bmi.bmiHeader.biSizeImage = ipitch * height;
|
||||
|
||||
pFormControl::resize(width, height);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
class pCanvas : public pFormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height);
|
||||
void redraw();
|
||||
uint32_t* buffer();
|
||||
|
||||
Canvas &self;
|
||||
pCanvas(Canvas&);
|
||||
~pCanvas();
|
||||
|
||||
/* internal */
|
||||
BITMAPINFO bmi;
|
||||
uint32_t *ibuffer;
|
||||
unsigned ipitch, iwidth, iheight;
|
||||
void resize(unsigned width, unsigned height);
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
void pCheckbox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_CHECKBOX,
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||
}
|
||||
|
||||
void pCheckbox::set_text(const char *text) {
|
||||
SetWindowText(hwnd, utf16(text));
|
||||
}
|
||||
|
||||
void pCheckbox::check(bool state) {
|
||||
SendMessage(hwnd, BM_SETCHECK, (WPARAM)(state ? TRUE : FALSE), 0);
|
||||
}
|
||||
|
||||
void pCheckbox::uncheck() {
|
||||
check(false);
|
||||
}
|
||||
|
||||
bool pCheckbox::checked() {
|
||||
return SendMessage(hwnd, BM_GETCHECK, 0, 0);
|
||||
}
|
||||
|
||||
pCheckbox::pCheckbox(Checkbox &self_) : pFormControl(self_), self(self_) {
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
class pCheckbox : public pFormControl {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check(bool state = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
|
||||
Checkbox &self;
|
||||
pCheckbox(Checkbox&);
|
||||
};
|
|
@ -1,38 +0,0 @@
|
|||
void pCombobox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"COMBOBOX", L"",
|
||||
WS_CHILD | WS_TABSTOP | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
|
||||
0, 0, width, 200,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||
|
||||
//fix combobox height
|
||||
//CreateWindow height parameter represents dropdown window height; auto-sizes control based on current font setting
|
||||
//GetWindowRect returns true height (~22px), CB_GETITEMHEIGHT returns text height (~16px)
|
||||
//difference = WindowHeight - CB_GETITEMHEIGHT
|
||||
//CB_SETITEMHEIGHT to height - difference, so that height matches requested height perfectly
|
||||
RECT rc;
|
||||
GetWindowRect(hwnd, &rc);
|
||||
unsigned adjusted_height = height - ((rc.bottom - rc.top) - SendMessage(hwnd, CB_GETITEMHEIGHT, (WPARAM)-1, 0));
|
||||
SendMessage(hwnd, CB_SETITEMHEIGHT, (WPARAM)-1, adjusted_height);
|
||||
}
|
||||
|
||||
void pCombobox::add_item(const char *text) {
|
||||
SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)(wchar_t*)utf16(text));
|
||||
if(SendMessage(hwnd, CB_GETCOUNT, 0, 0) == 1) set_selection(0);
|
||||
}
|
||||
|
||||
int pCombobox::get_selection() {
|
||||
return SendMessage(hwnd, CB_GETCURSEL, 0, 0);
|
||||
}
|
||||
|
||||
void pCombobox::set_selection(int index) {
|
||||
SendMessage(hwnd, CB_SETCURSEL, combobox_selection = index, 0);
|
||||
}
|
||||
|
||||
void pCombobox::reset() {
|
||||
SendMessage(hwnd, CB_RESETCONTENT, 0, 0);
|
||||
}
|
||||
|
||||
pCombobox::pCombobox(Combobox &self_) : pFormControl(self_), self(self_) {
|
||||
combobox_selection = 0;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
class pCombobox : public pFormControl {
|
||||
public:
|
||||
Combobox &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void add_item(const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
pCombobox(Combobox&);
|
||||
|
||||
/* internal */
|
||||
int combobox_selection;
|
||||
};
|
|
@ -1,84 +0,0 @@
|
|||
void pEditbox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
bool multiline = style & Editbox::Multiline;
|
||||
bool readonly = style & Editbox::Readonly;
|
||||
unsigned vscroll = (style & Editbox::VerticalScrollAlways) ? WS_VSCROLL :
|
||||
(style & Editbox::VerticalScrollNever ) ? 0 :
|
||||
ES_AUTOVSCROLL;
|
||||
unsigned hscroll = (style & Editbox::HorizontalScrollAlways) ? WS_HSCROLL :
|
||||
(style & Editbox::HorizontalScrollNever ) ? 0 :
|
||||
ES_AUTOHSCROLL;
|
||||
|
||||
autovscroll = (vscroll == ES_AUTOVSCROLL);
|
||||
|
||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", L"",
|
||||
WS_CHILD | WS_VISIBLE | vscroll | hscroll |
|
||||
(multiline == true ? ES_MULTILINE | ES_WANTRETURN : WS_TABSTOP) |
|
||||
(readonly == true ? ES_READONLY : 0),
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||
set_text(text);
|
||||
update();
|
||||
}
|
||||
|
||||
void pEditbox::resize(unsigned width, unsigned height) {
|
||||
pFormControl::resize(width, height);
|
||||
update();
|
||||
}
|
||||
|
||||
void pEditbox::set_text(const char *text) {
|
||||
string temp = text ? text : "";
|
||||
temp.replace("\r", "");
|
||||
temp.replace("\n", "\r\n");
|
||||
SetWindowText(hwnd, utf16(temp));
|
||||
update();
|
||||
}
|
||||
|
||||
unsigned pEditbox::get_text(char *text, unsigned length) {
|
||||
wchar_t *buffer = new wchar_t[length + 1];
|
||||
GetWindowText(hwnd, buffer, length);
|
||||
string temp = (const char*)utf8(buffer);
|
||||
delete[] buffer;
|
||||
temp.replace("\r", "");
|
||||
strlcpy(text, temp, length);
|
||||
return strlen(text);
|
||||
}
|
||||
|
||||
pEditbox::pEditbox(Editbox &self_) : pFormControl(self_), self(self_) {
|
||||
autovscroll = false;
|
||||
}
|
||||
|
||||
//========
|
||||
//internal
|
||||
//========
|
||||
|
||||
//WS_VSCROLL always shows the scrollbar;
|
||||
//ES_AUTOVSCROLL never shows the scrollbar but allows unlimited text;
|
||||
//no style disallows more text than what fits in the window.
|
||||
//
|
||||
//below routine simulates the effect of allowing unlimited text, but only
|
||||
//showing the scrollbar when it is needed. not sure how to simulate this effect
|
||||
//for horizontal scrolling at this time.
|
||||
//
|
||||
//below routine should be called whenever the font, text or window size is
|
||||
//modified.
|
||||
void pEditbox::update() {
|
||||
if(autovscroll == true) {
|
||||
//determine how many lines of text this control allows
|
||||
RECT rect;
|
||||
SendMessage(hwnd, EM_GETRECT, 0, (LPARAM)&rect);
|
||||
unsigned height = rect.bottom - rect.top;
|
||||
|
||||
//determine the height of a single line of text
|
||||
HDC hdc = GetDC(hwnd);
|
||||
SelectObject(hdc, phiro().default_font);
|
||||
DrawText(hdc, L"byuu", -1, &rect, DT_CALCRECT);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
unsigned lineheight = rect.bottom - rect.top;
|
||||
|
||||
//only show the scrollbar when there are more lines of text
|
||||
//than the control can show at once.
|
||||
unsigned linecount = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
|
||||
ShowScrollBar(hwnd, SB_VERT, linecount > (height / lineheight));
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
class pEditbox : public pFormControl {
|
||||
public:
|
||||
Editbox &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void resize(unsigned width, unsigned height);
|
||||
unsigned get_text(char *text, unsigned length = -1U);
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pEditbox(Editbox&);
|
||||
|
||||
//private:
|
||||
bool autovscroll;
|
||||
void update();
|
||||
};
|
|
@ -1,45 +0,0 @@
|
|||
void pFormControl::resize(unsigned width, unsigned height) {
|
||||
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
|
||||
}
|
||||
|
||||
void pFormControl::focus() {
|
||||
SetFocus(hwnd);
|
||||
}
|
||||
|
||||
bool pFormControl::focused() {
|
||||
return true; //fixme
|
||||
}
|
||||
|
||||
void pFormControl::enable(bool state) {
|
||||
EnableWindow(hwnd, state);
|
||||
}
|
||||
|
||||
void pFormControl::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pFormControl::enabled() {
|
||||
return !(GetWindowLong(hwnd, GWL_STYLE) & WS_DISABLED);
|
||||
}
|
||||
|
||||
uintptr_t pFormControl::handle() {
|
||||
return (uintptr_t)hwnd;
|
||||
}
|
||||
|
||||
pFormControl::pFormControl(FormControl &self_) : pWidget(self_), self(self_) {
|
||||
hwnd = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
void pFormControl::show(bool state) {
|
||||
ShowWindow(hwnd, state ? SW_NORMAL : SW_HIDE);
|
||||
}
|
||||
|
||||
void pFormControl::hide() {
|
||||
show(false);
|
||||
}
|
||||
|
||||
bool pFormControl::visible() {
|
||||
return GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
class pFormControl : public pWidget {
|
||||
public:
|
||||
virtual void resize(unsigned width, unsigned height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
uintptr_t handle();
|
||||
|
||||
virtual void show(bool = true);
|
||||
virtual void hide();
|
||||
virtual bool visible();
|
||||
|
||||
FormControl &self;
|
||||
pFormControl(FormControl&);
|
||||
|
||||
/* internal */
|
||||
HWND hwnd;
|
||||
};
|
|
@ -1,13 +0,0 @@
|
|||
void pFrame::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||
}
|
||||
|
||||
void pFrame::set_text(const char *text) {
|
||||
SetWindowText(hwnd, utf16(text));
|
||||
}
|
||||
|
||||
pFrame::pFrame(Frame &self_) : pFormControl(self_), self(self_) {
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
class pFrame : public pFormControl {
|
||||
public:
|
||||
Frame &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pFrame(Frame&);
|
||||
};
|
|
@ -1,444 +0,0 @@
|
|||
#include "hiro.hpp"
|
||||
#include "port.cpp"
|
||||
|
||||
namespace libhiro {
|
||||
|
||||
LRESULT CALLBACK phiro_wndproc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
#include "keymap.cpp"
|
||||
#include "widget.cpp"
|
||||
#include "window.cpp"
|
||||
#include "menucontrol.cpp"
|
||||
#include "menugroup.cpp"
|
||||
#include "menuitem.cpp"
|
||||
#include "menucheckitem.cpp"
|
||||
#include "menuradioitem.cpp"
|
||||
#include "menuseparator.cpp"
|
||||
#include "formcontrol.cpp"
|
||||
#include "frame.cpp"
|
||||
#include "canvas.cpp"
|
||||
#include "label.cpp"
|
||||
#include "button.cpp"
|
||||
#include "checkbox.cpp"
|
||||
#include "radiobox.cpp"
|
||||
#include "editbox.cpp"
|
||||
#include "listbox.cpp"
|
||||
#include "combobox.cpp"
|
||||
#include "progressbar.cpp"
|
||||
#include "slider.cpp"
|
||||
|
||||
void pHiro::init() {
|
||||
memset(&osversioninfo, 0, sizeof(OSVERSIONINFO));
|
||||
osversioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&osversioninfo);
|
||||
|
||||
WNDCLASS wc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
|
||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = phiro_wndproc;
|
||||
wc.lpszClassName = L"hiro_window";
|
||||
wc.lpszMenuName = 0;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
RegisterClass(&wc);
|
||||
|
||||
InitCommonControls();
|
||||
default_hwnd = CreateWindow(L"hiro_window", L"", WS_POPUP, 0, 0, 640, 480, 0, 0, GetModuleHandle(0), 0);
|
||||
default_font = create_font("Tahoma", 8);
|
||||
black_brush = CreateSolidBrush(RGB(0, 0, 0));
|
||||
}
|
||||
|
||||
void pHiro::term() {
|
||||
DeleteObject(black_brush);
|
||||
}
|
||||
|
||||
bool pHiro::run() {
|
||||
MSG msg;
|
||||
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||
//TODO: IsDialogMessage() does not clear keyboard buffer, but is required for tab key to work ...
|
||||
#if defined(HIRO_WIN_TABSTOP)
|
||||
if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) {
|
||||
#endif
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
#if defined(HIRO_WIN_TABSTOP)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return pending();
|
||||
}
|
||||
|
||||
bool pHiro::pending() {
|
||||
MSG msg;
|
||||
return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
|
||||
}
|
||||
|
||||
bool pHiro::folder_select(Window *focus, char *filename, const char *path) {
|
||||
wchar_t wfilename[_MAX_PATH] = L"";
|
||||
strcpy(filename, "");
|
||||
BROWSEINFO bi;
|
||||
bi.hwndOwner = focus ? focus->p.hwnd : 0;
|
||||
bi.pidlRoot = NULL;
|
||||
bi.pszDisplayName = wfilename;
|
||||
bi.lpszTitle = L"";
|
||||
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
|
||||
bi.lpfn = NULL;
|
||||
bi.lParam = 0;
|
||||
bi.iImage = 0;
|
||||
bool result = false;
|
||||
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
||||
if(pidl) {
|
||||
if(SHGetPathFromIDList(pidl, wfilename)) {
|
||||
result = true;
|
||||
IMalloc *imalloc = 0;
|
||||
if(SUCCEEDED(SHGetMalloc(&imalloc))) {
|
||||
imalloc->Free(pidl);
|
||||
imalloc->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
strcpy(filename, utf8(wfilename));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool pHiro::file_open(Window *focus, char *filename, const char *path, const char *filter) {
|
||||
string dir, f;
|
||||
dir = path ? path : "";
|
||||
dir.replace("/", "\\");
|
||||
|
||||
lstring type, part;
|
||||
type.split("\n", filter);
|
||||
for(int i = 0; i < type.size(); i++) {
|
||||
part.split("\t", type[i]);
|
||||
if(part.size() != 2) continue;
|
||||
|
||||
f.append(part[0]);
|
||||
f.append(" (");
|
||||
f.append(part[1]);
|
||||
f.append(")\t");
|
||||
part[1].replace(",", ";");
|
||||
f.append(part[1]);
|
||||
f.append("\t");
|
||||
}
|
||||
|
||||
utf16 wfilter(f);
|
||||
utf16 wdir(dir);
|
||||
wchar_t wfilename[_MAX_PATH] = L"";
|
||||
|
||||
wchar_t *p = wfilter;
|
||||
while(*p != L'\0') {
|
||||
if(*p == L'\t') *p = L'\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
OPENFILENAME ofn;
|
||||
strcpy(filename, "");
|
||||
memset(&ofn, 0, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = focus ? focus->p.hwnd : 0;
|
||||
ofn.lpstrFilter = wfilter;
|
||||
ofn.lpstrInitialDir = wdir;
|
||||
ofn.lpstrFile = wfilename;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
ofn.lpstrDefExt = L"";
|
||||
|
||||
bool result = GetOpenFileName(&ofn);
|
||||
strcpy(filename, utf8(wfilename));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool pHiro::file_save(Window *focus, char *filename, const char *path, const char *filter) {
|
||||
string dir, f;
|
||||
dir = path ? path : "";
|
||||
dir.replace("/", "\\");
|
||||
|
||||
lstring type, part;
|
||||
type.split("\n", filter);
|
||||
for(int i = 0; i < type.size(); i++) {
|
||||
part.split("\t", type[i]);
|
||||
if(part.size() != 2) continue;
|
||||
|
||||
f.append(part[0]);
|
||||
f.append(" (");
|
||||
f.append(part[1]);
|
||||
f.append(")\t");
|
||||
part[1].replace(",", ";");
|
||||
f.append(part[1]);
|
||||
f.append("\t");
|
||||
}
|
||||
|
||||
utf16 wfilter(f);
|
||||
utf16 wdir(dir);
|
||||
wchar_t wfilename[_MAX_PATH] = L"";
|
||||
|
||||
wchar_t *p = wfilter;
|
||||
while(*p != L'\0') {
|
||||
if(*p == L'\t') *p = L'\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
OPENFILENAME ofn;
|
||||
strcpy(filename, "");
|
||||
memset(&ofn, 0, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = focus ? focus->p.hwnd : 0;
|
||||
ofn.lpstrFilter = wfilter;
|
||||
ofn.lpstrInitialDir = wdir;
|
||||
ofn.lpstrFile = wfilename;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
ofn.lpstrDefExt = L"";
|
||||
|
||||
bool result = GetSaveFileName(&ofn);
|
||||
strcpy(filename, utf8(wfilename));
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned pHiro::screen_width() {
|
||||
return GetSystemMetrics(SM_CXSCREEN);
|
||||
}
|
||||
|
||||
unsigned pHiro::screen_height() {
|
||||
return GetSystemMetrics(SM_CYSCREEN);
|
||||
}
|
||||
|
||||
void pHiro::enable_screensaver() {
|
||||
is_screensaver_enabled = true;
|
||||
}
|
||||
|
||||
void pHiro::disable_screensaver() {
|
||||
is_screensaver_enabled = false;
|
||||
}
|
||||
|
||||
pHiro& pHiro::handle() {
|
||||
return hiro().p;
|
||||
}
|
||||
|
||||
pHiro::pHiro(Hiro &self_) : self(self_) {
|
||||
is_screensaver_enabled = true;
|
||||
}
|
||||
|
||||
pHiro& phiro() {
|
||||
return pHiro::handle();
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
HFONT pHiro::create_font(const char *name, unsigned size) {
|
||||
return CreateFont(
|
||||
-(size * 96.0 / 72.0 + 0.5), //96 = DPI
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
utf16(name)
|
||||
);
|
||||
}
|
||||
|
||||
Widget* pHiro::get_widget(unsigned instance) {
|
||||
Widget *widget = 0;
|
||||
for(unsigned i = 0; i < widget_list.size(); i++) {
|
||||
if(widget_list[i]->p.instance != instance) continue;
|
||||
widget = widget_list[i];
|
||||
break;
|
||||
}
|
||||
return widget;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK phiro_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
return phiro().wndproc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
LRESULT pHiro::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
pWidget *p = (pWidget*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
switch(msg) {
|
||||
case WM_SYSCOMMAND: {
|
||||
switch(wparam) {
|
||||
case SC_SCREENSAVE:
|
||||
case SC_MONITORPOWER: {
|
||||
if(is_screensaver_enabled == false) return FALSE;
|
||||
//fallthrough to DefWindowProc()
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WM_SIZE: {
|
||||
if(!p || p->self.type != Widget::WindowType) break;
|
||||
SendMessage(((pWindow*)p)->hstatus, WM_SIZE, 0, 0); //the control itself auto-sizes after receiving WM_SIZE
|
||||
} break;
|
||||
|
||||
case WM_CLOSE: {
|
||||
if(!p || p->self.type != Widget::WindowType) break;
|
||||
Window &w = ((pWindow*)p)->self;
|
||||
if(w.on_close) return (bool)w.on_close(event_t(event_t::Close, 0, &w));
|
||||
return TRUE; //true = destroy window
|
||||
} break;
|
||||
|
||||
case WM_ENTERMENULOOP: {
|
||||
if(!p || p->self.type != Widget::WindowType) break;
|
||||
Window &w = ((pWindow*)p)->self;
|
||||
if(w.on_block) w.on_block(event_t(event_t::Block, 0, &w));
|
||||
} break;
|
||||
|
||||
case WM_KEYDOWN: {
|
||||
if(!p || p->self.type != Widget::WindowType) break;
|
||||
Window &w = ((pWindow*)p)->self;
|
||||
if(w.on_input) w.on_input(event_t(event_t::Input, translate_key(wparam) + (1 << 16), &w));
|
||||
} break;
|
||||
|
||||
case WM_KEYUP: {
|
||||
if(!p || p->self.type != Widget::WindowType) break;
|
||||
Window &w = ((pWindow*)p)->self;
|
||||
if(w.on_input) w.on_input(event_t(event_t::Input, translate_key(wparam) + (0 << 16), &w));
|
||||
} break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN: {
|
||||
if(!p || p->self.type != Widget::CanvasType) break;
|
||||
Canvas &canvas = ((pCanvas*)p)->self;
|
||||
uintptr_t param = (msg == WM_LBUTTONDOWN ? mouse::button + 0 : mouse::button + 1) + (1 << 16);
|
||||
if(canvas.on_input) canvas.on_input(event_t(event_t::Input, param, &canvas));
|
||||
} break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP: {
|
||||
if(!p || p->self.type != Widget::CanvasType) break;
|
||||
Canvas &canvas = ((pCanvas*)p)->self;
|
||||
uintptr_t param = (msg == WM_LBUTTONUP ? mouse::button + 0 : mouse::button + 1) + (0 << 16);
|
||||
if(canvas.on_input) canvas.on_input(event_t(event_t::Input, param, &canvas));
|
||||
} break;
|
||||
|
||||
case WM_ERASEBKGND: {
|
||||
if(!p) break;
|
||||
HBRUSH brush = 0;
|
||||
if(p->self.type == Widget::WindowType) brush = ((pWindow*)p)->background;
|
||||
if(p->self.type == Widget::CanvasType) brush = phiro().black_brush;
|
||||
if(!brush) break;
|
||||
RECT rc;
|
||||
GetClientRect(hwnd, &rc);
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint(hwnd, &ps);
|
||||
FillRect(ps.hdc, &rc, brush);
|
||||
EndPaint(hwnd, &ps);
|
||||
return TRUE;
|
||||
} break;
|
||||
|
||||
case WM_PAINT: {
|
||||
if(p && p->self.type == Widget::CanvasType) ((pCanvas*)p)->redraw();
|
||||
} break;
|
||||
|
||||
case WM_COMMAND: {
|
||||
Widget *widget = get_widget(LOWORD(wparam));
|
||||
if(!widget) break;
|
||||
|
||||
switch(widget->type) {
|
||||
case Widget::MenuItemType: {
|
||||
MenuItem &w = (MenuItem&)*widget;
|
||||
if(w.on_tick) w.on_tick(event_t(event_t::Tick, 0, &w));
|
||||
} break;
|
||||
|
||||
case Widget::MenuCheckItemType: {
|
||||
MenuCheckItem &w = (MenuCheckItem&)*widget;
|
||||
w.check(!w.checked()); //invert check state
|
||||
if(w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||
} break;
|
||||
|
||||
case Widget::MenuRadioItemType: {
|
||||
MenuRadioItem &w = (MenuRadioItem&)*widget;
|
||||
bool checked = w.checked();
|
||||
w.check();
|
||||
if(!checked && w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||
} break;
|
||||
|
||||
case Widget::ButtonType: {
|
||||
Button &w = (Button&)*widget;
|
||||
if(w.on_tick) w.on_tick(event_t(event_t::Tick, 0, &w));
|
||||
} break;
|
||||
|
||||
case Widget::CheckboxType: {
|
||||
Checkbox &w = (Checkbox&)*widget;
|
||||
w.check(!w.checked()); //invert check state
|
||||
if(w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||
} break;
|
||||
|
||||
case Widget::RadioboxType: {
|
||||
Radiobox &w = (Radiobox&)*widget;
|
||||
bool checked = w.checked();
|
||||
w.check();
|
||||
if(!checked && w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||
} break;
|
||||
|
||||
case Widget::EditboxType: {
|
||||
Editbox &editbox = (Editbox&)*widget;
|
||||
if(HIWORD(wparam) == EN_CHANGE) {
|
||||
editbox.p.update(); //called to dynamically display vertical scrollbar if needed
|
||||
if(editbox.on_change) editbox.on_change(event_t(event_t::Change, 0, &editbox));
|
||||
}
|
||||
} break;
|
||||
|
||||
case Widget::ComboboxType: {
|
||||
Combobox &combobox = (Combobox&)*widget;
|
||||
if(HIWORD(wparam) == CBN_SELCHANGE) {
|
||||
if(combobox.p.combobox_selection == combobox.get_selection()) break;
|
||||
if(combobox.on_change) combobox.on_change(event_t(event_t::Change, combobox.p.combobox_selection = combobox.get_selection(), &combobox));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
case WM_VSCROLL: {
|
||||
Widget *widget = get_widget(GetDlgCtrlID((HWND)lparam));
|
||||
if(!widget) break;
|
||||
|
||||
switch(widget->type) {
|
||||
case Widget::SliderType: {
|
||||
Slider &slider = (Slider&)*widget;
|
||||
if(slider.p.slider_position == slider.get_position()) break;
|
||||
if(slider.on_change) slider.on_change(event_t(event_t::Change, slider.p.slider_position = slider.get_position(), &slider));
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WM_NOTIFY: {
|
||||
Widget *widget = get_widget(LOWORD(wparam));
|
||||
if(!widget) break;
|
||||
|
||||
switch(widget->type) {
|
||||
case Widget::ListboxType: {
|
||||
Listbox &listbox = (Listbox&)*widget;
|
||||
LPNMHDR nmhdr = (LPNMHDR)lparam;
|
||||
LPNMLISTVIEW nmlistview = (LPNMLISTVIEW)lparam;
|
||||
|
||||
if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) {
|
||||
//LVN_ITEMCHANGED is sent whenever an item gains or loses either focus or selection;
|
||||
//it does not send a special message to indicate that no items are focused or selected.
|
||||
//it will send two messages when a different item gains selection -- the first to remove
|
||||
//focus from the old item, the second to set selection to the new item.
|
||||
//hiro sends only one message whenever an item changed (eg gained selection),
|
||||
//including for deselection of all items. below code adapts win32 model to hiro model.
|
||||
//(focused means an item has a dotted outline box around it, but is not highlighted.)
|
||||
//(selected means an item is highlighted.)
|
||||
if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) {
|
||||
listbox.p.lostfocus = true;
|
||||
} else {
|
||||
if((!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED))
|
||||
|| (listbox.p.lostfocus == false && listbox.get_selection() == -1)) {
|
||||
if(listbox.on_change) listbox.on_change(event_t(event_t::Change, listbox.get_selection(), &listbox));
|
||||
}
|
||||
listbox.p.lostfocus = false;
|
||||
}
|
||||
} else if(nmhdr->code == LVN_ITEMACTIVATE) {
|
||||
if(listbox.on_activate) listbox.on_activate(event_t(event_t::Activate, listbox.get_selection(), &listbox));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
} //namespace libhiro
|
|
@ -1,97 +0,0 @@
|
|||
#ifndef HIRO_WIN_H
|
||||
#define HIRO_WIN_H
|
||||
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
#undef _WIN32_IE
|
||||
#undef NOMINMAX
|
||||
#undef _NO_OLDNAMES
|
||||
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define _WIN32_IE 0x0600
|
||||
#define NOMINMAX
|
||||
#define _NO_OLDNAMES
|
||||
|
||||
#define mkdir _mkdir
|
||||
#define UNICODE
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <shlobj.h>
|
||||
#undef mkdir
|
||||
|
||||
#include <nall/algorithm.hpp>
|
||||
using nall::min;
|
||||
using nall::max;
|
||||
|
||||
#include <nall/utf8.hpp>
|
||||
#define utf8 nall::utf8_t
|
||||
#define utf16 nall::utf16_t
|
||||
|
||||
extern int hiromain(int argc, const char *const argv[]);
|
||||
|
||||
namespace libhiro {
|
||||
|
||||
#include "widget.hpp"
|
||||
#include "window.hpp"
|
||||
#include "menucontrol.hpp"
|
||||
#include "menugroup.hpp"
|
||||
#include "menuitem.hpp"
|
||||
#include "menucheckitem.hpp"
|
||||
#include "menuradioitem.hpp"
|
||||
#include "menuseparator.hpp"
|
||||
#include "formcontrol.hpp"
|
||||
#include "frame.hpp"
|
||||
#include "canvas.hpp"
|
||||
#include "label.hpp"
|
||||
#include "button.hpp"
|
||||
#include "checkbox.hpp"
|
||||
#include "radiobox.hpp"
|
||||
#include "editbox.hpp"
|
||||
#include "listbox.hpp"
|
||||
#include "combobox.hpp"
|
||||
#include "progressbar.hpp"
|
||||
#include "slider.hpp"
|
||||
|
||||
class pHiro {
|
||||
public:
|
||||
Hiro &self;
|
||||
void init();
|
||||
void term();
|
||||
bool run();
|
||||
bool pending();
|
||||
|
||||
bool folder_select(Window *focus, char *filename, const char *path = "");
|
||||
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||
|
||||
unsigned screen_width();
|
||||
unsigned screen_height();
|
||||
|
||||
void enable_screensaver();
|
||||
void disable_screensaver();
|
||||
|
||||
static pHiro& handle();
|
||||
pHiro(Hiro&);
|
||||
|
||||
/* internal */
|
||||
OSVERSIONINFO osversioninfo;
|
||||
bool is_screensaver_enabled;
|
||||
HWND default_hwnd; //default parent window for all windowless controls
|
||||
HFONT default_font; //default font for all controls
|
||||
HBRUSH black_brush; //used for Canvas background
|
||||
HFONT create_font(const char *name, unsigned size);
|
||||
|
||||
array<Widget*> widget_list;
|
||||
Widget* get_widget(unsigned instance);
|
||||
LRESULT wndproc(HWND, UINT, WPARAM, LPARAM);
|
||||
uint16_t translate_key(unsigned key);
|
||||
};
|
||||
|
||||
pHiro& phiro();
|
||||
|
||||
} //namsepace libhiro
|
||||
|
||||
#endif //ifndef HIRO_WIN_H
|
|
@ -1,74 +0,0 @@
|
|||
uint16_t pHiro::translate_key(unsigned key) {
|
||||
switch(key) {
|
||||
case VK_ESCAPE: return keyboard::escape;
|
||||
|
||||
case VK_F1: return keyboard::f1;
|
||||
case VK_F2: return keyboard::f2;
|
||||
case VK_F3: return keyboard::f3;
|
||||
case VK_F4: return keyboard::f4;
|
||||
case VK_F5: return keyboard::f5;
|
||||
case VK_F6: return keyboard::f6;
|
||||
case VK_F7: return keyboard::f7;
|
||||
case VK_F8: return keyboard::f8;
|
||||
case VK_F9: return keyboard::f9;
|
||||
case VK_F10: return keyboard::f10;
|
||||
case VK_F11: return keyboard::f11;
|
||||
case VK_F12: return keyboard::f12;
|
||||
|
||||
case VK_TAB: return keyboard::tab;
|
||||
case VK_RETURN: return keyboard::return_;
|
||||
case VK_SPACE: return keyboard::spacebar;
|
||||
|
||||
case '0': return keyboard::num_0;
|
||||
case '1': return keyboard::num_1;
|
||||
case '2': return keyboard::num_2;
|
||||
case '3': return keyboard::num_3;
|
||||
case '4': return keyboard::num_4;
|
||||
case '5': return keyboard::num_5;
|
||||
case '6': return keyboard::num_6;
|
||||
case '7': return keyboard::num_7;
|
||||
case '8': return keyboard::num_8;
|
||||
case '9': return keyboard::num_9;
|
||||
|
||||
case VK_INSERT: return keyboard::insert;
|
||||
case VK_DELETE: return keyboard::delete_;
|
||||
case VK_HOME: return keyboard::home;
|
||||
case VK_END: return keyboard::end;
|
||||
case VK_PRIOR: return keyboard::page_up;
|
||||
case VK_NEXT: return keyboard::page_down;
|
||||
|
||||
case 'A': return keyboard::a;
|
||||
case 'B': return keyboard::b;
|
||||
case 'C': return keyboard::c;
|
||||
case 'D': return keyboard::d;
|
||||
case 'E': return keyboard::e;
|
||||
case 'F': return keyboard::f;
|
||||
case 'G': return keyboard::g;
|
||||
case 'H': return keyboard::h;
|
||||
case 'I': return keyboard::i;
|
||||
case 'J': return keyboard::j;
|
||||
case 'K': return keyboard::k;
|
||||
case 'L': return keyboard::l;
|
||||
case 'M': return keyboard::m;
|
||||
case 'N': return keyboard::n;
|
||||
case 'O': return keyboard::o;
|
||||
case 'P': return keyboard::p;
|
||||
case 'Q': return keyboard::q;
|
||||
case 'R': return keyboard::r;
|
||||
case 'S': return keyboard::s;
|
||||
case 'T': return keyboard::t;
|
||||
case 'U': return keyboard::u;
|
||||
case 'V': return keyboard::v;
|
||||
case 'W': return keyboard::w;
|
||||
case 'X': return keyboard::x;
|
||||
case 'Y': return keyboard::y;
|
||||
case 'Z': return keyboard::z;
|
||||
|
||||
case VK_UP: return keyboard::up;
|
||||
case VK_DOWN: return keyboard::down;
|
||||
case VK_LEFT: return keyboard::left;
|
||||
case VK_RIGHT: return keyboard::right;
|
||||
}
|
||||
|
||||
return keyboard::none;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
void pLabel::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
hwnd = CreateWindow(L"STATIC", utf16(text), WS_CHILD | WS_VISIBLE,
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||
}
|
||||
|
||||
void pLabel::set_text(const char *text) {
|
||||
SetWindowText(hwnd, utf16(text));
|
||||
}
|
||||
|
||||
pLabel::pLabel(Label &self_) : pFormControl(self_), self(self_) {
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
class pLabel : public pFormControl {
|
||||
public:
|
||||
Label &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pLabel(Label&);
|
||||
};
|
|
@ -1,98 +0,0 @@
|
|||
void pListbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) {
|
||||
bool header = style & Listbox::Header;
|
||||
unsigned hscroll = (style & Listbox::HorizontalScrollAlways) ? WS_HSCROLL :
|
||||
(style & Listbox::HorizontalScrollNever) ? 0 :
|
||||
0;
|
||||
unsigned vscroll = (style & Listbox::VerticalScrollAlways) ? WS_VSCROLL :
|
||||
(style & Listbox::VerticalScrollNever) ? 0 :
|
||||
0;
|
||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, L"",
|
||||
WS_CHILD | WS_TABSTOP | WS_VISIBLE |
|
||||
LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | vscroll | hscroll |
|
||||
(header ? 0 : LVS_NOCOLUMNHEADER),
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||
ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT);
|
||||
|
||||
lstring list;
|
||||
list.split("\t", columns ? columns : "");
|
||||
column_count = list.size();
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
LVCOLUMN column;
|
||||
column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM;
|
||||
column.fmt = LVCFMT_LEFT;
|
||||
column.iSubItem = list.size();
|
||||
utf16 ulist(list[i]);
|
||||
column.pszText = ulist;
|
||||
ListView_InsertColumn(hwnd, i, &column);
|
||||
}
|
||||
|
||||
if(text && *text) {
|
||||
list.split("\n", text);
|
||||
for(unsigned i = 0; i < list.size(); i++) add_item(list[i]);
|
||||
}
|
||||
autosize_columns();
|
||||
}
|
||||
|
||||
void pListbox::autosize_columns() {
|
||||
for(unsigned i = 0; i < column_count; i++) {
|
||||
ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE_USEHEADER);
|
||||
}
|
||||
}
|
||||
|
||||
void pListbox::set_column_width(unsigned column, unsigned width) {
|
||||
ListView_SetColumnWidth(hwnd, column, width);
|
||||
}
|
||||
|
||||
void pListbox::add_item(const char *text) {
|
||||
lstring list;
|
||||
list.split("\t", text ? text : "");
|
||||
LVITEM item;
|
||||
unsigned pos = ListView_GetItemCount(hwnd);
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = pos;
|
||||
item.iSubItem = 0;
|
||||
utf16 wtext(list[0]);
|
||||
item.pszText = wtext;
|
||||
ListView_InsertItem(hwnd, &item);
|
||||
|
||||
for(unsigned i = 1; i < list.size(); i++) {
|
||||
utf16 wtext(list[i]);
|
||||
ListView_SetItemText(hwnd, pos, i, wtext);
|
||||
}
|
||||
}
|
||||
|
||||
void pListbox::set_item(unsigned index, const char *text) {
|
||||
lstring list;
|
||||
list.split("\t", text ? text : "");
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
utf16 wtext(list[i]);
|
||||
ListView_SetItemText(hwnd, index, i, wtext);
|
||||
}
|
||||
}
|
||||
|
||||
int pListbox::get_selection() {
|
||||
unsigned count = ListView_GetItemCount(hwnd);
|
||||
for(unsigned i = 0; i < count; i++) {
|
||||
if(ListView_GetItemState(hwnd, i, LVIS_SELECTED)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pListbox::set_selection(int index) {
|
||||
unsigned count = ListView_GetItemCount(hwnd);
|
||||
for(unsigned i = 0; i < count; i++) {
|
||||
ListView_SetItemState(hwnd, i, LVIS_FOCUSED, (i == index) ? LVIS_FOCUSED : 0);
|
||||
ListView_SetItemState(hwnd, i, LVIS_SELECTED, (i == index) ? LVIS_SELECTED : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void pListbox::reset() {
|
||||
ListView_DeleteAllItems(hwnd);
|
||||
}
|
||||
|
||||
pListbox::pListbox(Listbox &self_) : pFormControl(self_), self(self_) {
|
||||
column_count = 0;
|
||||
lostfocus = false; //used for message parsing
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
class pListbox : public pFormControl {
|
||||
public:
|
||||
Listbox &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = "");
|
||||
void autosize_columns();
|
||||
void set_column_width(unsigned column, unsigned width);
|
||||
void add_item(const char *text);
|
||||
void set_item(unsigned index, const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
pListbox(Listbox&);
|
||||
|
||||
/* internal */
|
||||
unsigned column_count;
|
||||
bool lostfocus;
|
||||
};
|
|
@ -1,40 +0,0 @@
|
|||
void pMenuCheckItem::create(const char *text_) {
|
||||
text = strdup(text_);
|
||||
}
|
||||
|
||||
void pMenuCheckItem::check(bool state) {
|
||||
CheckMenuItem(parent, instance, state ? MF_CHECKED : MF_UNCHECKED);
|
||||
}
|
||||
|
||||
void pMenuCheckItem::uncheck() {
|
||||
check(false);
|
||||
}
|
||||
|
||||
bool pMenuCheckItem::checked() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof info);
|
||||
info.cbSize = sizeof info;
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, instance, false, &info);
|
||||
return info.fState & MFS_CHECKED;
|
||||
}
|
||||
|
||||
void pMenuCheckItem::enable(bool state) {
|
||||
EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED));
|
||||
}
|
||||
|
||||
void pMenuCheckItem::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pMenuCheckItem::enabled() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof info);
|
||||
info.cbSize = sizeof info;
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, instance, false, &info);
|
||||
return info.fState & MFS_ENABLED;
|
||||
}
|
||||
|
||||
pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) {
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
class pMenuCheckItem : public pMenuControl {
|
||||
public:
|
||||
void create(const char *text = "");
|
||||
void check(bool state = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
MenuCheckItem &self;
|
||||
pMenuCheckItem(MenuCheckItem&);
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
void pMenuControl::enable(bool) {
|
||||
}
|
||||
|
||||
void pMenuControl::disable() {
|
||||
}
|
||||
|
||||
bool pMenuControl::enabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
pMenuControl::pMenuControl(MenuControl &self_) : pWidget(self_), self(self_) {
|
||||
parent = 0;
|
||||
text = 0;
|
||||
}
|
||||
|
||||
pMenuControl::~pMenuControl() {
|
||||
if(text) free(text);
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
class pMenuControl : public pWidget {
|
||||
public:
|
||||
virtual void enable(bool = true);
|
||||
virtual void disable();
|
||||
virtual bool enabled();
|
||||
|
||||
MenuControl &self;
|
||||
pMenuControl(MenuControl&);
|
||||
virtual ~pMenuControl();
|
||||
|
||||
/* internal */
|
||||
HMENU parent;
|
||||
char *text;
|
||||
};
|
|
@ -1,48 +0,0 @@
|
|||
void pMenuGroup::create(const char *text_) {
|
||||
group = CreatePopupMenu();
|
||||
text = strdup(text_);
|
||||
}
|
||||
|
||||
void pMenuGroup::attach(MenuControl &menucontrol) {
|
||||
switch(menucontrol.type) {
|
||||
case Widget::MenuGroupType: {
|
||||
AppendMenu(group, MF_STRING | MF_POPUP, (unsigned)((MenuGroup&)menucontrol).p.group, utf16(menucontrol.p.text));
|
||||
} break;
|
||||
|
||||
case Widget::MenuItemType:
|
||||
case Widget::MenuCheckItemType:
|
||||
case Widget::MenuRadioItemType: {
|
||||
AppendMenu(group, MF_STRING, menucontrol.p.instance, utf16(menucontrol.p.text));
|
||||
if(menucontrol.type == Widget::MenuRadioItemType && ((MenuRadioItem&)menucontrol).p.create_checked) {
|
||||
CheckMenuItem(group, menucontrol.p.instance, MF_CHECKED);
|
||||
}
|
||||
} break;
|
||||
|
||||
case Widget::MenuSeparatorType: {
|
||||
AppendMenu(group, MF_SEPARATOR, menucontrol.p.instance, L"");
|
||||
} break;
|
||||
}
|
||||
|
||||
menucontrol.p.parent = group;
|
||||
}
|
||||
|
||||
void pMenuGroup::enable(bool state) {
|
||||
EnableMenuItem(parent, (unsigned)group, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED));
|
||||
}
|
||||
|
||||
void pMenuGroup::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pMenuGroup::enabled() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof info);
|
||||
info.cbSize = sizeof info;
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, (unsigned)group, false, &info);
|
||||
return info.fState & MFS_ENABLED;
|
||||
}
|
||||
|
||||
pMenuGroup::pMenuGroup(MenuGroup &self_) : pMenuControl(self_), self(self_) {
|
||||
group = 0;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
class pMenuGroup : public pMenuControl {
|
||||
public:
|
||||
MenuGroup &self;
|
||||
void create(const char *text);
|
||||
void attach(MenuControl &menucontrol);
|
||||
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
pMenuGroup(MenuGroup&);
|
||||
|
||||
/* internal */
|
||||
HMENU group;
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
void pMenuItem::create(const char *text_) {
|
||||
text = strdup(text_);
|
||||
}
|
||||
|
||||
void pMenuItem::enable(bool state) {
|
||||
EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED));
|
||||
}
|
||||
|
||||
void pMenuItem::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pMenuItem::enabled() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof info);
|
||||
info.cbSize = sizeof info;
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, instance, false, &info);
|
||||
return info.fState & MFS_ENABLED;
|
||||
}
|
||||
|
||||
pMenuItem::pMenuItem(MenuItem &self_) : pMenuControl(self_), self(self_) {
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
class pMenuItem : public pMenuControl {
|
||||
public:
|
||||
void create(const char *text = "");
|
||||
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
MenuItem &self;
|
||||
pMenuItem(MenuItem&);
|
||||
};
|
|
@ -1,41 +0,0 @@
|
|||
void pMenuRadioItem::create(MenuRadioItemGroup &group_, const char *text_) {
|
||||
group = group_;
|
||||
text = strdup(text_);
|
||||
create_checked = (group[0] == &self);
|
||||
}
|
||||
|
||||
void pMenuRadioItem::check() {
|
||||
for(unsigned i = 0; i < group.size(); i++) {
|
||||
CheckMenuItem(parent, group[i]->p.instance, (group[i] == &self) ? MF_CHECKED : MF_UNCHECKED);
|
||||
}
|
||||
}
|
||||
|
||||
bool pMenuRadioItem::checked() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof info);
|
||||
info.cbSize = sizeof info;
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, instance, false, &info);
|
||||
return info.fState & MFS_CHECKED;
|
||||
}
|
||||
|
||||
void pMenuRadioItem::enable(bool state) {
|
||||
EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED));
|
||||
}
|
||||
|
||||
void pMenuRadioItem::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pMenuRadioItem::enabled() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof info);
|
||||
info.cbSize = sizeof info;
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, instance, false, &info);
|
||||
return info.fState & MFS_ENABLED;
|
||||
}
|
||||
|
||||
pMenuRadioItem::pMenuRadioItem(MenuRadioItem &self_) : pMenuControl(self_), self(self_) {
|
||||
create_checked = false;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
class pMenuRadioItem : public pMenuControl {
|
||||
public:
|
||||
void create(MenuRadioItemGroup &group, const char *text = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
MenuRadioItem &self;
|
||||
pMenuRadioItem(MenuRadioItem&);
|
||||
|
||||
/* internal */
|
||||
MenuRadioItemGroup group;
|
||||
bool create_checked;
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
void pMenuSeparator::create() {
|
||||
}
|
||||
|
||||
void pMenuSeparator::enable(bool state) {
|
||||
EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED));
|
||||
}
|
||||
|
||||
void pMenuSeparator::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pMenuSeparator::enabled() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof info);
|
||||
info.cbSize = sizeof info;
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, instance, false, &info);
|
||||
return info.fState & MFS_ENABLED;
|
||||
}
|
||||
|
||||
pMenuSeparator::pMenuSeparator(MenuSeparator &self_) : pMenuControl(self_), self(self_) {
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
class pMenuSeparator : public pMenuControl {
|
||||
public:
|
||||
MenuSeparator &self;
|
||||
void create();
|
||||
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
pMenuSeparator(MenuSeparator&);
|
||||
};
|
|
@ -1,40 +0,0 @@
|
|||
char* realpath(const char *file_name, char *resolved_name) {
|
||||
wchar_t filename[_MAX_PATH] = L"";
|
||||
_wfullpath(filename, utf16(file_name), _MAX_PATH);
|
||||
strcpy(resolved_name, utf8(filename));
|
||||
return resolved_name;
|
||||
}
|
||||
|
||||
char* userpath(char *output) {
|
||||
wchar_t path[_MAX_PATH] = L"";
|
||||
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path);
|
||||
strcpy(output, utf8(path));
|
||||
return output;
|
||||
}
|
||||
|
||||
int mkdir(const char *path) {
|
||||
return _wmkdir(utf16(path));
|
||||
}
|
||||
|
||||
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
||||
//argv[] is in 7-bit ANSI format; Unicode characters are converted to '?'s.
|
||||
//this needs to be converted to UTF-8, eg for realpath(argv[0]) to work.
|
||||
int argc;
|
||||
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
char **argv = new char*[argc];
|
||||
for(unsigned i = 0; i < argc; i++) {
|
||||
argv[i] = new char[_MAX_PATH];
|
||||
strcpy(argv[i], utf8(wargv[i]));
|
||||
}
|
||||
|
||||
libhiro::hiro().init();
|
||||
int result = hiromain(argc, argv);
|
||||
libhiro::hiro().term();
|
||||
|
||||
for(unsigned i = 0; i < argc; i++) {
|
||||
delete[] argv[i];
|
||||
}
|
||||
delete[] argv;
|
||||
|
||||
return result;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
void pProgressbar::create(unsigned style, unsigned width, unsigned height) {
|
||||
hwnd = CreateWindow(PROGRESS_CLASS, L"", WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
|
||||
SendMessage(hwnd, PBM_SETSTEP, MAKEWPARAM(1, 0), 0);
|
||||
}
|
||||
|
||||
unsigned pProgressbar::get_progress() {
|
||||
unsigned progress = SendMessage(hwnd, PBM_GETPOS, 0, 0);
|
||||
return max(0U, min(progress, 100U));
|
||||
}
|
||||
|
||||
void pProgressbar::set_progress(unsigned progress) {
|
||||
progress = max(0U, min(progress, 100U));
|
||||
SendMessage(hwnd, PBM_SETPOS, (WPARAM)progress, 0);
|
||||
}
|
||||
|
||||
pProgressbar::pProgressbar(Progressbar &self_) : pFormControl(self_), self(self_) {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
class pProgressbar : public pFormControl {
|
||||
public:
|
||||
Progressbar &self;
|
||||
void create(unsigned style, unsigned width, unsigned height);
|
||||
unsigned get_progress();
|
||||
void set_progress(unsigned progress);
|
||||
|
||||
pProgressbar(Progressbar&);
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
void pRadiobox::create(RadioboxGroup &group_, unsigned style, unsigned width, unsigned height, const char *text) {
|
||||
group = group_;
|
||||
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_RADIOBUTTON,
|
||||
0, 0, width, height, phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||
if(group[0] == &self) check();
|
||||
}
|
||||
|
||||
void pRadiobox::set_text(const char *text) {
|
||||
SetWindowText(hwnd, utf16(text));
|
||||
}
|
||||
|
||||
void pRadiobox::check() {
|
||||
for(unsigned i = 0; i < group.size(); i++) {
|
||||
SendMessage(group[i]->p.hwnd, BM_SETCHECK, (WPARAM)(group[i] == &self), 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool pRadiobox::checked() {
|
||||
return SendMessage(hwnd, BM_GETCHECK, 0, 0);
|
||||
}
|
||||
|
||||
pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self_), self(self_) {
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
class pRadiobox : public pFormControl {
|
||||
public:
|
||||
void create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
Radiobox &self;
|
||||
pRadiobox(Radiobox&);
|
||||
|
||||
/* internal */
|
||||
RadioboxGroup group;
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
void pSlider::create(unsigned style, unsigned width, unsigned height, unsigned length) {
|
||||
if(length < 1) length = 1;
|
||||
|
||||
hwnd = CreateWindow(TRACKBAR_CLASS, L"",
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | TBS_NOTICKS | TBS_BOTH |
|
||||
(style & Slider::Vertical ? TBS_VERT : TBS_HORZ),
|
||||
0, 0, width, height,
|
||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, TBM_SETRANGE, (WPARAM)true, (LPARAM)MAKELONG(0, length - 1));
|
||||
SendMessage(hwnd, TBM_SETPAGESIZE, 0, (LPARAM)(length >> 3));
|
||||
SendMessage(hwnd, TBM_SETPOS, (WPARAM)true, (LPARAM)0);
|
||||
}
|
||||
|
||||
unsigned pSlider::get_position() {
|
||||
return SendMessage(hwnd, TBM_GETPOS, 0, 0);
|
||||
}
|
||||
|
||||
void pSlider::set_position(unsigned position) {
|
||||
SendMessage(hwnd, TBM_SETPOS, (WPARAM)true, (LPARAM)(slider_position = position));
|
||||
}
|
||||
|
||||
pSlider::pSlider(Slider &self_) : pFormControl(self_), self(self_) {
|
||||
slider_position = 0;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
class pSlider : public pFormControl {
|
||||
public:
|
||||
Slider &self;
|
||||
void create(unsigned style, unsigned width, unsigned height, unsigned length);
|
||||
unsigned get_position();
|
||||
void set_position(unsigned position);
|
||||
|
||||
pSlider(Slider&);
|
||||
|
||||
/* internal */
|
||||
unsigned slider_position;
|
||||
};
|
|
@ -1,27 +0,0 @@
|
|||
void pWidget::show(bool state) {
|
||||
}
|
||||
|
||||
void pWidget::hide() {
|
||||
}
|
||||
|
||||
bool pWidget::visible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
uintptr_t pWidget::handle() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pWidget::pWidget(Widget &self_) : self(self_) {
|
||||
instance = instance_counter++;
|
||||
phiro().widget_list.add(&self);
|
||||
}
|
||||
|
||||
pWidget::~pWidget() {
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
//100 is the standard start index for control IDs in the Windows API
|
||||
//avoids duplicate IDs when they are not explicitly set (and are thus 0)
|
||||
unsigned pWidget::instance_counter = 100;
|
|
@ -1,19 +0,0 @@
|
|||
class pWidget {
|
||||
public:
|
||||
Widget &self;
|
||||
virtual void show(bool = true);
|
||||
virtual void hide();
|
||||
virtual bool visible();
|
||||
virtual uintptr_t handle();
|
||||
|
||||
pWidget(Widget&);
|
||||
virtual ~pWidget();
|
||||
|
||||
/* internal */
|
||||
|
||||
//Windows API controls often require a unique ID for each control to identify it.
|
||||
//Simulate this with an instance counter, so that each Widget has a unique ID.
|
||||
//In each pWidget() constructor, instance = instance_counter++; is called.
|
||||
static unsigned instance_counter;
|
||||
unsigned instance;
|
||||
};
|
|
@ -1,334 +0,0 @@
|
|||
void pWindow::create(unsigned style, unsigned width_, unsigned height_, const char *text) {
|
||||
auto_center = style & Window::AutoCenter;
|
||||
|
||||
RECT rc;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
|
||||
|
||||
hwnd = CreateWindowEx(0, L"hiro_window", utf16(text),
|
||||
WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
|
||||
rc.left, rc.top, width_, height_,
|
||||
0, 0, GetModuleHandle(0), 0);
|
||||
hwndr = CreateWindowEx(0, L"hiro_window", utf16(text),
|
||||
WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
|
||||
rc.left, rc.top, width_, height_,
|
||||
0, 0, GetModuleHandle(0), 0);
|
||||
hmenu = CreateMenu();
|
||||
hstatus = CreateWindowEx(0, STATUSCLASSNAME, L"",
|
||||
WS_CHILD, 0, 0, 0, 0, hwnd, 0, GetModuleHandle(0), 0);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
|
||||
resize(width_, height_);
|
||||
}
|
||||
|
||||
void pWindow::close() {
|
||||
CloseWindow(hwnd);
|
||||
}
|
||||
|
||||
void pWindow::move(unsigned x, unsigned y) {
|
||||
if(is_fullscreen == true) return;
|
||||
SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
void pWindow::resize(unsigned width_, unsigned height_) {
|
||||
int screen_width = GetSystemMetrics(SM_CXSCREEN);
|
||||
int screen_height = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
if(is_fullscreen == true) {
|
||||
SetWindowPos(hwnd, 0, 0, 0, screen_width, screen_height, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
return;
|
||||
}
|
||||
|
||||
width = width_;
|
||||
height = height_;
|
||||
|
||||
//set requested window size to hidden window, calculate the difference between
|
||||
//requested and actual client size area, and then adjust width so that new
|
||||
//width, height values will set requested client area size.
|
||||
//AdjustWindowRect() does not properly calculate the height of multi-line menus,
|
||||
//and thusly is not used.
|
||||
SetWindowPos(hwndr, 0, 0, 0, width_, height_, SWP_NOMOVE | SWP_NOZORDER);
|
||||
RECT rc;
|
||||
GetClientRect(hwndr, &rc);
|
||||
width_ += width_ - (rc.right - rc.left);
|
||||
height_ += height_ - (rc.bottom - rc.top);
|
||||
|
||||
if(status.visible()) {
|
||||
//statusbar does not count as part of window client area width, height
|
||||
GetClientRect(hstatus, &rc);
|
||||
height_ += rc.bottom - rc.top;
|
||||
}
|
||||
|
||||
//if window is larger than the screen size, Windows will hide the window entirely.
|
||||
//therefore, window must be constrained to fit within the current screen size.
|
||||
|
||||
int x, y;
|
||||
if(width_ <= screen_width) {
|
||||
x = (screen_width - width_) >> 1;
|
||||
} else {
|
||||
x = 0;
|
||||
width_ = screen_width;
|
||||
}
|
||||
|
||||
if(height_ <= screen_height) {
|
||||
y = (screen_height - height_) >> 1;
|
||||
} else {
|
||||
y = 0;
|
||||
height_ = screen_height;
|
||||
}
|
||||
|
||||
SetWindowPos(hwnd, 0, x, y, width_, height_, (auto_center ? 0 : SWP_NOMOVE) | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
void pWindow::focus() {
|
||||
if(visible() == false) show();
|
||||
SetFocus(hwnd);
|
||||
}
|
||||
|
||||
bool pWindow::focused() {
|
||||
return GetForegroundWindow() == hwnd;
|
||||
}
|
||||
|
||||
void pWindow::show(bool state) {
|
||||
if(state == true) {
|
||||
ShowWindow(hwnd, SW_NORMAL);
|
||||
SetFocus(hwnd);
|
||||
} else {
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
void pWindow::hide() {
|
||||
show(false);
|
||||
}
|
||||
|
||||
bool pWindow::visible() {
|
||||
return GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE;
|
||||
}
|
||||
|
||||
void pWindow::fullscreen() {
|
||||
if(is_fullscreen == true) return;
|
||||
is_fullscreen = true;
|
||||
SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
|
||||
resize(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
|
||||
}
|
||||
|
||||
void pWindow::unfullscreen() {
|
||||
if(is_fullscreen == false) return;
|
||||
is_fullscreen = false;
|
||||
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE);
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
unsigned pWindow::get_width() {
|
||||
RECT rc;
|
||||
GetClientRect(hwnd, &rc);
|
||||
return rc.right - rc.left;
|
||||
}
|
||||
|
||||
unsigned pWindow::get_height() {
|
||||
RECT rc;
|
||||
GetClientRect(hwnd, &rc);
|
||||
if(status.visible() == false) return rc.bottom - rc.top;
|
||||
//do not include statusbar in client area height
|
||||
RECT src;
|
||||
GetClientRect(hstatus, &src);
|
||||
return (rc.bottom - rc.top) - (src.bottom - src.top);
|
||||
}
|
||||
|
||||
void pWindow::set_opacity(uint8_t opacity_) {
|
||||
opacity = opacity_;
|
||||
if(!hwnd) return;
|
||||
|
||||
if(opacity != 255) {
|
||||
//enable translucency
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
|
||||
SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA);
|
||||
} else {
|
||||
//disable transluceny
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
|
||||
SetLayeredWindowAttributes(hwnd, 0, 0, 0);
|
||||
}
|
||||
|
||||
InvalidateRect(hwnd, 0, TRUE);
|
||||
}
|
||||
|
||||
void pWindow::set_background_color(uint8_t r, uint8_t g, uint8_t b) {
|
||||
if(background) DeleteObject(background);
|
||||
background = CreateSolidBrush(RGB(r, g, b));
|
||||
}
|
||||
|
||||
void pWindow::set_icon(unsigned width, unsigned height, const uint32_t *data) {
|
||||
if(hicon) DestroyIcon(hicon);
|
||||
|
||||
uint8_t *mask = (uint8_t*)malloc(width * height / 8);
|
||||
memset(mask, 0, width * height / 8);
|
||||
uint8_t *icon = (uint8_t*)malloc(width * height * 4);
|
||||
memcpy(icon, data, width * height * 4);
|
||||
|
||||
if((phiro().osversioninfo.dwMajorVersion < 5)
|
||||
|| (phiro().osversioninfo.dwMajorVersion == 5 && phiro().osversioninfo.dwMinorVersion < 1)) {
|
||||
//5.1 and above represents Windows XP or later, which supports 32-bit icons.
|
||||
//5.0 and below represents Windows 2000 or earlier, which does not support 32-bit icons.
|
||||
//if running Win2k or prior, alpha channel will be ignored;
|
||||
//so scale color intensity by alpha level, which gives icons a black background.
|
||||
//this is because an alpha of 0 (fully transparent) results in a color of 0 (black).
|
||||
//without this step and alpha ignored, icons lose appearance of anti-aliasing.
|
||||
for(unsigned i = 0; i < width * height; i++) {
|
||||
uint8_t a = icon[i * 4 + 3];
|
||||
uint8_t r = uint8_t(1.0 / 256.0 * a * icon[i * 4 + 2]);
|
||||
uint8_t g = uint8_t(1.0 / 256.0 * a * icon[i * 4 + 1]);
|
||||
uint8_t b = uint8_t(1.0 / 256.0 * a * icon[i * 4 + 0]);
|
||||
icon[i * 4 + 3] = 0xff; //ignored anyway, but just to be safe ...
|
||||
icon[i * 4 + 2] = max(0, min(255, r)); //clamp 0 <= color <= 255 ...
|
||||
icon[i * 4 + 1] = max(0, min(255, g)); //not required, but again ...
|
||||
icon[i * 4 + 0] = max(0, min(255, b)); //it's better to be safe.
|
||||
}
|
||||
}
|
||||
|
||||
hicon = CreateIcon(GetModuleHandle(0), width, height, 1, 32, (const BYTE*)mask, (const BYTE*)icon);
|
||||
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon);
|
||||
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicon);
|
||||
|
||||
free(mask);
|
||||
free(icon);
|
||||
}
|
||||
|
||||
void pWindow::set_text(const char *text) {
|
||||
SetWindowText(hwnd, utf16(text));
|
||||
}
|
||||
|
||||
void pWindow::attach(Window &window, unsigned x, unsigned y) {
|
||||
if(!window.p.hwnd) return;
|
||||
|
||||
//toplevel window size is larger, because it includes window borders
|
||||
//read size of window without window borders, and resize upon attach
|
||||
RECT rc;
|
||||
GetClientRect(window.p.hwnd, &rc);
|
||||
|
||||
ShowWindow(window.p.hwnd, SW_HIDE);
|
||||
SetWindowLong(window.p.hwnd, GWL_STYLE, WS_CHILD);
|
||||
SetWindowLong(window.p.hwnd, GWL_EXSTYLE, WS_EX_CONTROLPARENT);
|
||||
SetParent(window.p.hwnd, hwnd);
|
||||
SetWindowPos(window.p.hwnd, 0, x, y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
ShowWindow(window.p.hwnd, SW_NORMAL);
|
||||
}
|
||||
|
||||
void pWindow::attach(MenuGroup &menugroup) {
|
||||
AppendMenu(hmenu, MF_STRING | MF_POPUP, (unsigned)menugroup.p.group, utf16(menugroup.p.text));
|
||||
if(menu_visible() == false) menu_show();
|
||||
}
|
||||
|
||||
void pWindow::attach(FormControl &formcontrol, unsigned x, unsigned y) {
|
||||
SetWindowPos(formcontrol.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||||
SetParent(formcontrol.p.hwnd, hwnd);
|
||||
//SetParent() sets Z-order to topmost ...
|
||||
//this causes WS_TABSTOP property to run through controls "backward"
|
||||
//by inverting this, the later a control is attached, the later the tab key moves to it
|
||||
SetWindowPos(formcontrol.p.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
|
||||
}
|
||||
|
||||
void pWindow::move(Window &window, unsigned x, unsigned y) {
|
||||
SetWindowPos(window.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
void pWindow::move(FormControl &formcontrol, unsigned x, unsigned y) {
|
||||
SetWindowPos(formcontrol.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
/* pWindow -> Menubar */
|
||||
|
||||
void pWindow::Menubar::show(bool state) {
|
||||
p.menu_show(state);
|
||||
}
|
||||
|
||||
void pWindow::Menubar::hide() {
|
||||
p.menu_hide();
|
||||
}
|
||||
|
||||
bool pWindow::Menubar::visible() {
|
||||
return p.menu_visible();
|
||||
}
|
||||
|
||||
pWindow::Menubar::Menubar(pWindow &p_) : p(p_) {
|
||||
}
|
||||
|
||||
/* pWindow -> Statusbar */
|
||||
|
||||
void pWindow::Statusbar::set_text(const char *text) {
|
||||
p.status_set_text(text);
|
||||
}
|
||||
|
||||
void pWindow::Statusbar::show(bool state) {
|
||||
p.status_show(state);
|
||||
}
|
||||
|
||||
void pWindow::Statusbar::hide() {
|
||||
p.status_hide();
|
||||
}
|
||||
|
||||
bool pWindow::Statusbar::visible() {
|
||||
return p.status_visible();
|
||||
}
|
||||
|
||||
pWindow::Statusbar::Statusbar(pWindow &p_) : p(p_) {
|
||||
}
|
||||
|
||||
pWindow::pWindow(Window &self_) : pWidget(self_), self(self_), menu(*this), status(*this) {
|
||||
hwnd = 0;
|
||||
hwndr = 0;
|
||||
hicon = 0;
|
||||
hmenu = 0;
|
||||
background = 0;
|
||||
opacity = 255;
|
||||
is_fullscreen = false;
|
||||
auto_center = false;
|
||||
width = 0;
|
||||
height = 0;
|
||||
}
|
||||
|
||||
pWindow::~pWindow() {
|
||||
if(hicon) DestroyIcon(hicon);
|
||||
if(background) DeleteObject(background);
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
uintptr_t pWindow::handle() {
|
||||
return (uintptr_t)hwnd;
|
||||
}
|
||||
|
||||
void pWindow::menu_show(bool state) {
|
||||
if(state) {
|
||||
SetMenu(hwnd, hmenu);
|
||||
SetMenu(hwndr, hmenu);
|
||||
} else {
|
||||
SetMenu(hwnd, 0);
|
||||
SetMenu(hwndr, 0);
|
||||
}
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
void pWindow::menu_hide() {
|
||||
menu_show(false);
|
||||
}
|
||||
|
||||
bool pWindow::menu_visible() {
|
||||
return GetMenu(hwnd);
|
||||
}
|
||||
|
||||
void pWindow::status_set_text(const char *text) {
|
||||
SendMessage(hstatus, SB_SETTEXT, 0, (LPARAM)(wchar_t*)utf16(text));
|
||||
}
|
||||
|
||||
void pWindow::status_show(bool state) {
|
||||
ShowWindow(hstatus, state ? SW_SHOWNORMAL : SW_HIDE);
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
void pWindow::status_hide() {
|
||||
status_show(false);
|
||||
}
|
||||
|
||||
bool pWindow::status_visible() {
|
||||
return GetWindowLong(hstatus, GWL_STYLE) & WS_VISIBLE;
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
class pWindow : public pWidget {
|
||||
public:
|
||||
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||
void close();
|
||||
void move(unsigned x, unsigned y);
|
||||
void resize(unsigned width, unsigned height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void fullscreen();
|
||||
void unfullscreen();
|
||||
unsigned get_width();
|
||||
unsigned get_height();
|
||||
void set_opacity(uint8_t opacity);
|
||||
void set_background_color(uint8_t r, uint8_t g, uint8_t b);
|
||||
void set_icon(unsigned width, unsigned height, const uint32_t *data);
|
||||
void set_text(const char *text = "");
|
||||
void attach(Window &window, unsigned x, unsigned y);
|
||||
void attach(MenuGroup &menugroup);
|
||||
void attach(FormControl &formcontrol, unsigned x, unsigned y);
|
||||
void move(Window &window, unsigned x, unsigned y);
|
||||
void move(FormControl &formcontrol, unsigned x, unsigned y);
|
||||
|
||||
class Statusbar {
|
||||
public:
|
||||
void set_text(const char *text = "");
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
pWindow &p;
|
||||
Statusbar(pWindow&);
|
||||
} status;
|
||||
|
||||
class Menubar {
|
||||
public:
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
pWindow &p;
|
||||
Menubar(pWindow&);
|
||||
} menu;
|
||||
|
||||
Window &self;
|
||||
pWindow(Window&);
|
||||
~pWindow();
|
||||
|
||||
/* internal */
|
||||
HWND hwnd;
|
||||
HWND hwndr; //hidden window, used as resize assistant
|
||||
HICON hicon;
|
||||
HMENU hmenu;
|
||||
HWND hstatus;
|
||||
HBRUSH background;
|
||||
uint8_t opacity;
|
||||
bool is_fullscreen;
|
||||
bool auto_center;
|
||||
unsigned width, height;
|
||||
|
||||
uintptr_t handle();
|
||||
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
void menu_show(bool = true);
|
||||
void menu_hide();
|
||||
bool menu_visible();
|
||||
|
||||
void status_set_text(const char *text = "");
|
||||
void status_show(bool = true);
|
||||
void status_hide();
|
||||
bool status_visible();
|
||||
};
|
|
@ -8,9 +8,11 @@
|
|||
#include <nall/stdint.hpp>
|
||||
|
||||
namespace nall {
|
||||
struct keyboard {
|
||||
enum { input_none = 0 };
|
||||
|
||||
template<int number = -1> struct keyboard {
|
||||
enum {
|
||||
none,
|
||||
none = keyboard<number - 1>::limit,
|
||||
escape, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
|
||||
print_screen, scroll_lock, pause, tilde,
|
||||
num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0,
|
||||
|
@ -29,54 +31,92 @@ namespace nall {
|
|||
};
|
||||
};
|
||||
|
||||
struct mouse {
|
||||
enum { buttons = 8 };
|
||||
|
||||
template<> struct keyboard<-1> {
|
||||
enum { count = 16 };
|
||||
enum {
|
||||
none = keyboard::limit,
|
||||
none,
|
||||
escape, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
|
||||
print_screen, scroll_lock, pause, tilde,
|
||||
num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0,
|
||||
dash, equal, backspace,
|
||||
insert, delete_, home, end, page_up, page_down,
|
||||
a, b, c, d, e, f, g, h, i, j, k, l, m,
|
||||
n, o, p, q, r, s, t, u, v, w, x, y, z,
|
||||
lbracket, rbracket, backslash, semicolon, apostrophe, comma, period, slash,
|
||||
pad_1, pad_2, pad_3, pad_4, pad_5, pad_6, pad_7, pad_8, pad_9, pad_0,
|
||||
point, enter, add, subtract, multiply, divide,
|
||||
num_lock, caps_lock,
|
||||
up, down, left, right,
|
||||
tab, return_, spacebar,
|
||||
lctrl, rctrl, lalt, ralt, lshift, rshift, lsuper, rsuper, menu,
|
||||
length, //number of syms per keyboard
|
||||
limit = 0,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned keyboard_number, unsigned keyboard_enum) {
|
||||
if(keyboard_number >= count) return input_none;
|
||||
return limit + keyboard_number * length + keyboard_enum;
|
||||
}
|
||||
};
|
||||
|
||||
template<int number = -1> struct mouse {
|
||||
enum { buttons = 8 };
|
||||
enum {
|
||||
none = mouse<number - 1>::limit,
|
||||
x, y, z,
|
||||
button,
|
||||
limit = button + buttons,
|
||||
};
|
||||
};
|
||||
|
||||
template<int number = -1> struct joypad {
|
||||
enum { axes = 8 };
|
||||
enum { buttons = 96 };
|
||||
template<> struct mouse<-1> {
|
||||
enum { count = 16, buttons = 8 };
|
||||
enum {
|
||||
none,
|
||||
x, y, z,
|
||||
button,
|
||||
length = button + buttons - none, //number of syms per mouse
|
||||
limit = keyboard<keyboard<>::count - 1>::limit,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned mouse_number, unsigned mouse_enum) {
|
||||
if(mouse_number >= count) return input_none;
|
||||
return limit + mouse_number * length + mouse_enum;
|
||||
}
|
||||
};
|
||||
|
||||
template<int number = -1> struct joypad {
|
||||
enum { hats = 8, axes = 32, buttons = 96 };
|
||||
enum {
|
||||
none = joypad<number - 1>::limit,
|
||||
up, down, left, right,
|
||||
axis,
|
||||
hat,
|
||||
axis = hat + hats,
|
||||
button = axis + axes,
|
||||
limit = button + buttons,
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct joypad<-1> {
|
||||
enum { count = 16 };
|
||||
enum { axes = 8 };
|
||||
enum { buttons = 96 };
|
||||
|
||||
enum { count = 16, hats = 8, axes = 32, buttons = 96 };
|
||||
enum { hat_center = 0, hat_up = 1, hat_right = 2, hat_down = 4, hat_left = 8 };
|
||||
enum {
|
||||
none,
|
||||
up, down, left, right,
|
||||
axis,
|
||||
hat,
|
||||
axis = hat + hats,
|
||||
button = axis + axes,
|
||||
length = button + buttons - none, //number of syms per joypad
|
||||
limit = mouse::limit,
|
||||
limit = mouse<mouse<>::count - 1>::limit,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned joypad_number, unsigned joypad_enum) {
|
||||
if(joypad_number >= count) return keyboard::none;
|
||||
if(joypad_number >= count) return input_none;
|
||||
return limit + joypad_number * length + joypad_enum;
|
||||
}
|
||||
};
|
||||
|
||||
enum { input_limit = joypad<joypad<>::count - 1>::limit };
|
||||
|
||||
static const char sym_table[][64] = {
|
||||
//keyboard
|
||||
static const char keysym[][64] = {
|
||||
"none",
|
||||
"escape", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
|
||||
"print_screen", "scroll_lock", "pause", "tilde",
|
||||
|
@ -92,24 +132,37 @@ namespace nall {
|
|||
"up", "down", "left", "right",
|
||||
"tab", "return", "spacebar",
|
||||
"lctrl", "rctrl", "lalt", "ralt", "lshift", "rshift", "lsuper", "rsuper", "menu",
|
||||
"keyboard.limit",
|
||||
|
||||
//mouse
|
||||
"mouse.x", "mouse.y", "mouse.z",
|
||||
"mouse.button00", "mouse.button01", "mouse.button02", "mouse.button03",
|
||||
"mouse.button04", "mouse.button05", "mouse.button06", "mouse.button07",
|
||||
"mouse.limit",
|
||||
"limit",
|
||||
};
|
||||
|
||||
static const char* input_find(uint16_t key) {
|
||||
if(key < mouse::limit) return sym_table[key];
|
||||
|
||||
static char buffer[64];
|
||||
for(unsigned j = 0; j < 16; j++) {
|
||||
if(key == joypad<>::index(j, joypad<>::up)) { sprintf(buffer, "joypad%.2d.up", j); return buffer; }
|
||||
if(key == joypad<>::index(j, joypad<>::down)) { sprintf(buffer, "joypad%.2d.down", j); return buffer; }
|
||||
if(key == joypad<>::index(j, joypad<>::left)) { sprintf(buffer, "joypad%.2d.left", j); return buffer; }
|
||||
if(key == joypad<>::index(j, joypad<>::right)) { sprintf(buffer, "joypad%.2d.right", j); return buffer; }
|
||||
|
||||
for(unsigned k = 0; k < keyboard<>::count; k++) {
|
||||
if(key >= keyboard<>::index(k, keyboard<>::none) && key < keyboard<>::index(k, keyboard<>::length)) {
|
||||
sprintf(buffer, "keyboard%.2d.%s", k, keysym[key - keyboard<>::index(k, keyboard<>::none)]);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned m = 0; m < mouse<>::count; m++) {
|
||||
if(key == mouse<>::index(m, mouse<>::x)) { sprintf(buffer, "mouse%.2d.x", m); return buffer; }
|
||||
if(key == mouse<>::index(m, mouse<>::y)) { sprintf(buffer, "mouse%.2d.y", m); return buffer; }
|
||||
if(key == mouse<>::index(m, mouse<>::z)) { sprintf(buffer, "mouse%.2d.z", m); return buffer; }
|
||||
|
||||
if(key >= mouse<>::index(m, mouse<>::button + 0)
|
||||
&& key < mouse<>::index(m, mouse<>::button + mouse<>::buttons)) {
|
||||
sprintf(buffer, "mouse%.2d.button%.2d", m, key - mouse<>::index(m, mouse<>::button));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned j = 0; j < joypad<>::count; j++) {
|
||||
if(key >= joypad<>::index(j, joypad<>::hat + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::hat + joypad<>::hats)) {
|
||||
sprintf(buffer, "joypad%.2d.hat%.2d", j, key - joypad<>::index(j, joypad<>::hat));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
if(key >= joypad<>::index(j, joypad<>::axis + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::axis + joypad<>::axes)) {
|
||||
|
@ -133,39 +186,77 @@ namespace nall {
|
|||
}
|
||||
|
||||
static uint16_t input_find(const char *key) {
|
||||
for(unsigned i = 0; i < mouse::limit; i++) {
|
||||
if(!strcmp(sym_table[i], key)) return i;
|
||||
if(!memcmp(key, "keyboard", 8)) {
|
||||
key += 8;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t k = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(k >= keyboard<>::count) return input_none;
|
||||
key += 2;
|
||||
|
||||
if(*key++ != '.') return input_none;
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) {
|
||||
if(!strcmp(key, keysym[i])) return keyboard<>::index(k, i);
|
||||
}
|
||||
}
|
||||
|
||||
if(memcmp(key, "joypad", 6)) return keyboard::none;
|
||||
key += 6;
|
||||
if(!*key || !*(key + 1)) return keyboard::none;
|
||||
uint8_t j = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(j > 15) return keyboard::none;
|
||||
|
||||
key += 2;
|
||||
if(!strcmp(key, ".up")) return joypad<>::index(j, joypad<>::up);
|
||||
if(!strcmp(key, ".down")) return joypad<>::index(j, joypad<>::down);
|
||||
if(!strcmp(key, ".left")) return joypad<>::index(j, joypad<>::left);
|
||||
if(!strcmp(key, ".right")) return joypad<>::index(j, joypad<>::right);
|
||||
|
||||
if(!memcmp(key, ".axis", 5)) {
|
||||
if(!memcmp(key, "mouse", 5)) {
|
||||
key += 5;
|
||||
if(!*key || !*(key + 1)) return keyboard::none;
|
||||
uint8_t axis = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(axis >= joypad<>::axes) return keyboard::none;
|
||||
return joypad<>::index(j, joypad<>::axis + axis);
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t m = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(m >= mouse<>::count) return input_none;
|
||||
key += 2;
|
||||
|
||||
if(!strcmp(key, ".x")) return mouse<>::index(m, mouse<>::x);
|
||||
if(!strcmp(key, ".y")) return mouse<>::index(m, mouse<>::y);
|
||||
if(!strcmp(key, ".z")) return mouse<>::index(m, mouse<>::z);
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= mouse<>::buttons) return input_none;
|
||||
return mouse<>::index(m, mouse<>::button + button);
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return keyboard::none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= joypad<>::buttons) return keyboard::none;
|
||||
return joypad<>::index(j, joypad<>::button + button);
|
||||
if(!memcmp(key, "joypad", 6)) {
|
||||
key += 6;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t j = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(j >= joypad<>::count) return input_none;
|
||||
key += 2;
|
||||
|
||||
if(!memcmp(key, ".hat", 4)) {
|
||||
key += 4;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t hat = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(hat >= joypad<>::hats) return input_none;
|
||||
return joypad<>::index(j, joypad<>::hat + hat);
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".axis", 5)) {
|
||||
key += 5;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t axis = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(axis >= joypad<>::axes) return input_none;
|
||||
return joypad<>::index(j, joypad<>::axis + axis);
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= joypad<>::buttons) return input_none;
|
||||
return joypad<>::index(j, joypad<>::button + button);
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
|
||||
return keyboard::none;
|
||||
return input_none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ public:
|
|||
KeyboardSupport,
|
||||
MouseSupport,
|
||||
JoypadSupport,
|
||||
AnalogAxisResistance,
|
||||
};
|
||||
|
||||
virtual bool cap(Setting) { return false; }
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue