mirror of https://github.com/bsnes-emu/bsnes.git
Update to v106r48 release.
byuu says: The problems with the Windows and Qt4 ports have all been resolved, although there's a fairly gross hack on a few Qt widgets to not destruct once Application::quit() is called to avoid a double free crash (I'm unsure where Qt is destructing the widgets internally.) The Cocoa port compiles again at least, though it's bound to have endless problems. I improved the Label painting in the GTK ports, which fixes the background color on labels inside TabFrame widgets. I've optimized the Makefile system even further. I added a "redo state" command to bsnes, which is created whenever you load the undo state. There are also hotkeys for both now, although I don't think they're really something you want to map hotkeys to. I moved the nall::Locale object inside hiro::Application, so that it can be used to translate the BrowserDialog and MessageDialog window strings. I improved the Super Game Boy emulation of `MLT_REQ`, fixing Pokemon Yellow's custom border and probably more stuff. Lots of other small fixes and improvements. Things are finally stable once again after the harrowing layout redesign catastrophe. Errata: - ICD::joypID should be set to 3 on reset(). joypWrite() may as well take uint1 instead of bool. - hiro/Qt: remove pWindow::setMaximumSize() comment; found a workaround for it - nall/GNUmakefile: don't set object.path if it's already set (allow overrides before including the file)
This commit is contained in:
parent
6090c63958
commit
393c2395bb
|
@ -1,22 +1,21 @@
|
||||||
name := genius
|
name := genius
|
||||||
build := stable
|
build := stable
|
||||||
|
flags += -I..
|
||||||
|
|
||||||
nall.path := ../nall
|
nall.path := ../nall
|
||||||
include $(nall.path)/GNUmakefile
|
include $(nall.path)/GNUmakefile
|
||||||
|
|
||||||
object.path := obj
|
|
||||||
flags += -I..
|
|
||||||
|
|
||||||
hiro.path := ../hiro
|
hiro.path := ../hiro
|
||||||
hiro.resource := data/$(name).rc
|
hiro.resource := data/$(name).rc
|
||||||
include $(hiro.path)/GNUmakefile
|
include $(hiro.path)/GNUmakefile
|
||||||
|
|
||||||
objects := obj/hiro.o $(if $(call streq,$(platform),windows),obj/hiro-resource.o)
|
objects := obj/genius.o
|
||||||
objects += obj/genius.o
|
|
||||||
|
|
||||||
all: $(objects)
|
obj/genius.o: genius.cpp
|
||||||
|
|
||||||
|
all: $(hiro.objects) $(objects)
|
||||||
$(info Linking out/$(name) ...)
|
$(info Linking out/$(name) ...)
|
||||||
+@$(strip $(compiler) -o out/$(name) $(objects) $(options) $(hiro.options))
|
+@$(compiler) -o out/$(name) $(hiro.objects) $(objects) $(hiro.options) $(options)
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
rm -rf out/$(name).app
|
rm -rf out/$(name).app
|
||||||
mkdir -p out/$(name).app/Contents/MacOS/
|
mkdir -p out/$(name).app/Contents/MacOS/
|
||||||
|
@ -26,16 +25,14 @@ ifeq ($(platform),macos)
|
||||||
sips -s format icns data/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
|
sips -s format icns data/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj/genius.o: genius.cpp genius.hpp
|
verbose: hiro.verbose nall.verbose all;
|
||||||
$(info Compiling $< ...)
|
|
||||||
@$(compiler) $(flags.cpp) $(flags) -o obj/genius.o -c genius.cpp
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
rm -rf out/$(name).app
|
rm -rf out/$(name).app
|
||||||
endif
|
endif
|
||||||
$(call rm,obj/*)
|
$(call delete,obj/*)
|
||||||
$(call rm,out/*)
|
$(call delete,out/*)
|
||||||
|
|
||||||
install:
|
install:
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
|
target := bsnes
|
||||||
|
binary := application
|
||||||
build := performance
|
build := performance
|
||||||
openmp := true
|
openmp := true
|
||||||
|
flags += -I. -I..
|
||||||
|
|
||||||
nall.path := ../nall
|
nall.path := ../nall
|
||||||
include $(nall.path)/GNUmakefile
|
include $(nall.path)/GNUmakefile
|
||||||
|
|
||||||
binary := application
|
|
||||||
target := bsnes
|
|
||||||
objects := libco emulator audio video resource
|
|
||||||
object.path := obj
|
|
||||||
flags += -I. -I..
|
|
||||||
|
|
||||||
ifeq ($(platform),windows)
|
ifeq ($(platform),windows)
|
||||||
ifeq ($(binary),application)
|
ifeq ($(binary),application)
|
||||||
link += -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32
|
link += -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32
|
||||||
|
@ -37,18 +34,7 @@ else
|
||||||
$(error "unsupported platform")
|
$(error "unsupported platform")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
compile = \
|
objects := libco emulator audio video resource
|
||||||
$(strip \
|
|
||||||
$(if $(filter %.c,$<), \
|
|
||||||
$(compiler) $(flags.c) $(flags) $1 -c $< -o $@ -MMD -MP -MF $(@:.o=.d), \
|
|
||||||
$(if $(filter %.cpp,$<), \
|
|
||||||
$(compiler) $(flags.cpp) $(flags) $1 -c $< -o $@ -MMD -MP -MF $(@:.o=.d) \
|
|
||||||
)) \
|
|
||||||
)
|
|
||||||
|
|
||||||
%.o: $<
|
|
||||||
$(info Compiling $< ...)
|
|
||||||
@$(call compile)
|
|
||||||
|
|
||||||
obj/libco.o: ../libco/libco.c
|
obj/libco.o: ../libco/libco.c
|
||||||
obj/emulator.o: emulator/emulator.cpp
|
obj/emulator.o: emulator/emulator.cpp
|
||||||
|
@ -61,5 +47,5 @@ include $(ui)/GNUmakefile
|
||||||
-include obj/*.d
|
-include obj/*.d
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(call rm,out/*)
|
$(call delete,out/*)
|
||||||
$(call rm,obj/*)
|
$(call delete,obj/*)
|
||||||
|
|
|
@ -13,7 +13,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "106.47";
|
static const string Version = "106.48";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "https://byuu.org/";
|
static const string Website = "https://byuu.org/";
|
||||||
|
|
|
@ -41,7 +41,6 @@ struct CPU : Processor::LR35902, Thread, MMIO {
|
||||||
bool p15 = 0;
|
bool p15 = 0;
|
||||||
bool p14 = 0;
|
bool p14 = 0;
|
||||||
uint8 joyp;
|
uint8 joyp;
|
||||||
uint8 mltReq;
|
|
||||||
|
|
||||||
//$ff01 SB
|
//$ff01 SB
|
||||||
uint8 serialData;
|
uint8 serialData;
|
||||||
|
|
|
@ -29,7 +29,9 @@ auto CPU::joypPoll() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
status.joyp = 0x0f;
|
status.joyp = 0x0f;
|
||||||
if(status.p15 == 1 && status.p14 == 1) status.joyp -= status.mltReq;
|
if(status.p15 == 1 && status.p14 == 1 && Model::SuperGameBoy()) {
|
||||||
|
status.joyp = superGameBoy->joypRead();
|
||||||
|
}
|
||||||
if(status.p15 == 0) status.joyp &= button ^ 0x0f;
|
if(status.p15 == 0) status.joyp &= button ^ 0x0f;
|
||||||
if(status.p14 == 0) status.joyp &= dpad ^ 0x0f;
|
if(status.p14 == 0) status.joyp &= dpad ^ 0x0f;
|
||||||
if(status.joyp != 0x0f) raise(Interrupt::Joypad);
|
if(status.joyp != 0x0f) raise(Interrupt::Joypad);
|
||||||
|
|
|
@ -10,7 +10,6 @@ auto CPU::serialize(serializer& s) -> void {
|
||||||
s.integer(status.p15);
|
s.integer(status.p15);
|
||||||
s.integer(status.p14);
|
s.integer(status.p14);
|
||||||
s.integer(status.joyp);
|
s.integer(status.joyp);
|
||||||
s.integer(status.mltReq);
|
|
||||||
|
|
||||||
s.integer(status.serialData);
|
s.integer(status.serialData);
|
||||||
s.integer(status.serialBits);
|
s.integer(status.serialBits);
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct SuperGameBoyInterface {
|
||||||
|
|
||||||
virtual auto lcdScanline() -> void = 0;
|
virtual auto lcdScanline() -> void = 0;
|
||||||
virtual auto lcdOutput(uint2 color) -> void = 0;
|
virtual auto lcdOutput(uint2 color) -> void = 0;
|
||||||
|
virtual auto joypRead() -> uint4 = 0;
|
||||||
virtual auto joypWrite(bool p15, bool p14) -> void = 0;
|
virtual auto joypWrite(bool p15, bool p14) -> void = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ auto ICD::reset() -> void {
|
||||||
writeAddress = 0;
|
writeAddress = 0;
|
||||||
|
|
||||||
packetSize = 0;
|
packetSize = 0;
|
||||||
joypID = 3;
|
joypID = 0;
|
||||||
joyp15Lock = 0;
|
joyp15Lock = 0;
|
||||||
joyp14Lock = 0;
|
joyp14Lock = 0;
|
||||||
pulseLock = true;
|
pulseLock = true;
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct ICD : Emulator::Platform, GameBoy::SuperGameBoyInterface, Thread {
|
||||||
//interface.cpp
|
//interface.cpp
|
||||||
auto lcdScanline() -> void override;
|
auto lcdScanline() -> void override;
|
||||||
auto lcdOutput(uint2 color) -> void override;
|
auto lcdOutput(uint2 color) -> void override;
|
||||||
|
auto joypRead() -> uint4 override;
|
||||||
auto joypWrite(bool p15, bool p14) -> void override;
|
auto joypWrite(bool p15, bool p14) -> void override;
|
||||||
|
|
||||||
//io.cpp
|
//io.cpp
|
||||||
|
|
|
@ -10,18 +10,26 @@ auto ICD::lcdOutput(uint2 color) -> void {
|
||||||
uint y = writeAddress / 160;
|
uint y = writeAddress / 160;
|
||||||
uint x = writeAddress % 160;
|
uint x = writeAddress % 160;
|
||||||
uint addr = writeBank * 512 + y * 2 + x / 8 * 16;
|
uint addr = writeBank * 512 + y * 2 + x / 8 * 16;
|
||||||
output[addr + 0] = (output[addr + 0] << 1) | (bool)(color & 1);
|
output[addr + 0] = (output[addr + 0] << 1) | color.bit(0);
|
||||||
output[addr + 1] = (output[addr + 1] << 1) | (bool)(color & 2);
|
output[addr + 1] = (output[addr + 1] << 1) | color.bit(1);
|
||||||
writeAddress = (writeAddress + 1) % 1280;
|
writeAddress = (writeAddress + 1) % 1280;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto ICD::joypRead() -> uint4 {
|
||||||
|
return 0xf - joypID;
|
||||||
|
}
|
||||||
|
|
||||||
auto ICD::joypWrite(bool p15, bool p14) -> void {
|
auto ICD::joypWrite(bool p15, bool p14) -> void {
|
||||||
//joypad handling
|
//joypad handling
|
||||||
if(p15 == 1 && p14 == 1) {
|
if(p15 == 1 && p14 == 1) {
|
||||||
if(joyp15Lock == 0 && joyp14Lock == 0) {
|
if(joyp15Lock == 0 && joyp14Lock == 0) {
|
||||||
joyp15Lock = 1;
|
joyp15Lock = 1;
|
||||||
joyp14Lock = 1;
|
joyp14Lock = 1;
|
||||||
joypID = (joypID + 1) & 3;
|
joypID++;
|
||||||
|
if(mltReq == 0) joypID &= 0; //1-player mode
|
||||||
|
if(mltReq == 1) joypID &= 1; //2-player mode
|
||||||
|
if(mltReq == 2) joypID &= 3; //4-player mode (unverified; but the most likely behavior)
|
||||||
|
if(mltReq == 3) joypID &= 3; //4-player mode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +73,7 @@ auto ICD::joypWrite(bool p15, bool p14) -> void {
|
||||||
if(p15 == 1 && p14 == 0) {
|
if(p15 == 1 && p14 == 0) {
|
||||||
if((joypPacket[0] >> 3) == 0x11) {
|
if((joypPacket[0] >> 3) == 0x11) {
|
||||||
mltReq = joypPacket[1] & 3;
|
mltReq = joypPacket[1] & 3;
|
||||||
if(mltReq == 2) mltReq = 3;
|
joypID = 3; //required: the next time P14==1 && P15==1; increment and start from ID=0 (Joypad 1)
|
||||||
joypID = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(packetSize < 64) packet[packetSize++] = joypPacket;
|
if(packetSize < 64) packet[packetSize++] = joypPacket;
|
||||||
|
|
|
@ -3,10 +3,8 @@ auto ICD::audioSample(const double* samples, uint channels) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ICD::inputPoll(uint port, uint device, uint id) -> int16 {
|
auto ICD::inputPoll(uint port, uint device, uint id) -> int16 {
|
||||||
GameBoy::cpu.status.mltReq = joypID & mltReq;
|
uint8 data = 0x00;
|
||||||
|
switch(joypID) {
|
||||||
uint data = 0x00;
|
|
||||||
switch(joypID & mltReq) {
|
|
||||||
case 0: data = ~r6004; break;
|
case 0: data = ~r6004; break;
|
||||||
case 1: data = ~r6005; break;
|
case 1: data = ~r6005; break;
|
||||||
case 2: data = ~r6006; break;
|
case 2: data = ~r6006; break;
|
||||||
|
@ -14,14 +12,14 @@ auto ICD::inputPoll(uint port, uint device, uint id) -> int16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch((GameBoy::Input)id) {
|
switch((GameBoy::Input)id) {
|
||||||
case GameBoy::Input::Start: return (bool)(data & 0x80);
|
case GameBoy::Input::Right: return data.bit(0);
|
||||||
case GameBoy::Input::Select: return (bool)(data & 0x40);
|
case GameBoy::Input::Left: return data.bit(1);
|
||||||
case GameBoy::Input::B: return (bool)(data & 0x20);
|
case GameBoy::Input::Up: return data.bit(2);
|
||||||
case GameBoy::Input::A: return (bool)(data & 0x10);
|
case GameBoy::Input::Down: return data.bit(3);
|
||||||
case GameBoy::Input::Down: return (bool)(data & 0x08);
|
case GameBoy::Input::A: return data.bit(4);
|
||||||
case GameBoy::Input::Up: return (bool)(data & 0x04);
|
case GameBoy::Input::B: return data.bit(5);
|
||||||
case GameBoy::Input::Left: return (bool)(data & 0x02);
|
case GameBoy::Input::Select: return data.bit(6);
|
||||||
case GameBoy::Input::Right: return (bool)(data & 0x01);
|
case GameBoy::Input::Start: return data.bit(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -5,35 +5,16 @@ include sfc/GNUmakefile
|
||||||
include gb/GNUmakefile
|
include gb/GNUmakefile
|
||||||
include processor/GNUmakefile
|
include processor/GNUmakefile
|
||||||
|
|
||||||
objects := ruby hiro $(if $(call streq,$(platform),windows),hiro-resource) $(objects)
|
hiro.path := ../hiro
|
||||||
objects += ui-bsnes ui-program ui-input ui-presentation
|
hiro.resource := $(ui)/resource/bsnes.rc
|
||||||
objects += ui-settings ui-tools ui-resource
|
include $(hiro.path)/GNUmakefile
|
||||||
objects := $(objects:%=obj/%.o)
|
|
||||||
|
|
||||||
ifeq ($(platform),windows)
|
|
||||||
ruby += video.wgl video.direct3d video.directdraw video.gdi
|
|
||||||
ruby += audio.asio audio.wasapi audio.xaudio2 audio.directsound
|
|
||||||
ruby += input.windows
|
|
||||||
else ifeq ($(platform),macos)
|
|
||||||
ruby += video.cgl
|
|
||||||
ruby += audio.openal
|
|
||||||
ruby += input.quartz input.carbon
|
|
||||||
else ifeq ($(platform),linux)
|
|
||||||
ruby += video.glx video.xvideo video.xshm
|
|
||||||
ruby += audio.oss audio.alsa audio.openal audio.pulseaudio audio.pulseaudiosimple audio.ao
|
|
||||||
ruby += input.sdl input.xlib input.udev
|
|
||||||
else ifeq ($(platform),bsd)
|
|
||||||
ruby += video.glx video.xvideo video.xshm
|
|
||||||
ruby += audio.oss audio.openal
|
|
||||||
ruby += input.sdl input.xlib
|
|
||||||
endif
|
|
||||||
|
|
||||||
ruby.path := ../ruby
|
ruby.path := ../ruby
|
||||||
include $(ruby.path)/GNUmakefile
|
include $(ruby.path)/GNUmakefile
|
||||||
|
|
||||||
hiro.path := ../hiro
|
objects += ui-bsnes ui-program ui-input ui-presentation
|
||||||
hiro.resource := $(ui)/resource/bsnes.rc
|
objects += ui-settings ui-tools ui-resource
|
||||||
include $(hiro.path)/GNUmakefile
|
objects := $(objects:%=obj/%.o)
|
||||||
|
|
||||||
obj/ui-bsnes.o: $(ui)/bsnes.cpp
|
obj/ui-bsnes.o: $(ui)/bsnes.cpp
|
||||||
obj/ui-program.o: $(ui)/program/program.cpp
|
obj/ui-program.o: $(ui)/program/program.cpp
|
||||||
|
@ -43,10 +24,9 @@ obj/ui-settings.o: $(ui)/settings/settings.cpp
|
||||||
obj/ui-tools.o: $(ui)/tools/tools.cpp
|
obj/ui-tools.o: $(ui)/tools/tools.cpp
|
||||||
obj/ui-resource.o: $(ui)/resource/resource.cpp
|
obj/ui-resource.o: $(ui)/resource/resource.cpp
|
||||||
|
|
||||||
# targets
|
all: $(hiro.objects) $(ruby.objects) $(objects)
|
||||||
all: $(objects)
|
|
||||||
$(info Linking out/$(name) ...)
|
$(info Linking out/$(name) ...)
|
||||||
+@$(strip $(compiler) -o out/$(name) $(objects) $(options) $(ruby.options) $(hiro.options))
|
+@$(compiler) -o out/$(name) $(hiro.objects) $(ruby.objects) $(objects) $(hiro.options) $(ruby.options) $(options)
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
rm -rf out/$(name).app
|
rm -rf out/$(name).app
|
||||||
mkdir -p out/$(name).app/Contents/MacOS/
|
mkdir -p out/$(name).app/Contents/MacOS/
|
||||||
|
@ -56,6 +36,8 @@ ifeq ($(platform),macos)
|
||||||
sips -s format icns $(ui)/resource/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
|
sips -s format icns $(ui)/resource/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
verbose: hiro.verbose ruby.verbose nall.verbose all;
|
||||||
|
|
||||||
install:
|
install:
|
||||||
ifeq ($(shell id -un),root)
|
ifeq ($(shell id -un),root)
|
||||||
$(error "make install should not be run as root")
|
$(error "make install should not be run as root")
|
||||||
|
|
|
@ -4,7 +4,6 @@ unique_pointer<Video> video;
|
||||||
unique_pointer<Audio> audio;
|
unique_pointer<Audio> audio;
|
||||||
unique_pointer<Input> input;
|
unique_pointer<Input> input;
|
||||||
unique_pointer<Emulator::Interface> emulator;
|
unique_pointer<Emulator::Interface> emulator;
|
||||||
Locale ns;
|
|
||||||
|
|
||||||
auto locate(string name) -> string {
|
auto locate(string name) -> string {
|
||||||
string location = {Path::program(), name};
|
string location = {Path::program(), name};
|
||||||
|
@ -21,14 +20,15 @@ auto locate(string name) -> string {
|
||||||
|
|
||||||
#include <nall/main.hpp>
|
#include <nall/main.hpp>
|
||||||
auto nall::main(string_vector arguments) -> void {
|
auto nall::main(string_vector arguments) -> void {
|
||||||
ns.scan(locate("locales/"));
|
string locale; // = "日本語";
|
||||||
ns.select("日本語");
|
|
||||||
for(auto argument : arguments) {
|
for(auto argument : arguments) {
|
||||||
if(argument.beginsWith("--locale=")) {
|
if(argument.beginsWith("--locale=")) {
|
||||||
ns.select(argument.trimLeft("--locale=", 1L));
|
locale = argument.trimLeft("--locale=", 1L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Application::setName("bsnes");
|
Application::setName("bsnes");
|
||||||
|
Application::locale().scan(locate("locales/"));
|
||||||
|
Application::locale().select(locale);
|
||||||
emulator = new SuperFamicom::Interface;
|
emulator = new SuperFamicom::Interface;
|
||||||
new Program(arguments);
|
new Program(arguments);
|
||||||
Application::run();
|
Application::run();
|
||||||
|
|
|
@ -11,7 +11,6 @@ extern unique_pointer<Input> input;
|
||||||
#include <emulator/emulator.hpp>
|
#include <emulator/emulator.hpp>
|
||||||
extern unique_pointer<Emulator::Interface> emulator;
|
extern unique_pointer<Emulator::Interface> emulator;
|
||||||
|
|
||||||
extern Locale ns;
|
|
||||||
#include "program/program.hpp"
|
#include "program/program.hpp"
|
||||||
#include "input/input.hpp"
|
#include "input/input.hpp"
|
||||||
#include "presentation/presentation.hpp"
|
#include "presentation/presentation.hpp"
|
||||||
|
|
|
@ -24,6 +24,14 @@ auto InputManager::bindHotkeys() -> void {
|
||||||
program->loadState({"quick/slot ", stateSlot});
|
program->loadState({"quick/slot ", stateSlot});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
hotkeys.append(InputHotkey("Load Undo State").onPress([&] {
|
||||||
|
program->loadState("quick/undo");
|
||||||
|
}));
|
||||||
|
|
||||||
|
hotkeys.append(InputHotkey("Load Redo State").onPress([&] {
|
||||||
|
program->loadState("quick/redo");
|
||||||
|
}));
|
||||||
|
|
||||||
hotkeys.append(InputHotkey("Increment State Slot").onPress([&] {
|
hotkeys.append(InputHotkey("Increment State Slot").onPress([&] {
|
||||||
if(--stateSlot < 1) stateSlot = 9;
|
if(--stateSlot < 1) stateSlot = 9;
|
||||||
program->showMessage({"Selected state slot ", stateSlot});
|
program->showMessage({"Selected state slot ", stateSlot});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
AboutWindow::AboutWindow() : Locale::Namespace(ns, "About") {
|
AboutWindow::AboutWindow() {
|
||||||
aboutWindow = this;
|
aboutWindow = this;
|
||||||
|
|
||||||
setTitle(tr("About {0} ...", "bsnes"));
|
setTitle({tr("About {0}", "bsnes"), " ..."});
|
||||||
setBackgroundColor({255, 255, 240});
|
setBackgroundColor({255, 255, 240});
|
||||||
layout.setPadding(10);
|
layout.setPadding(10);
|
||||||
auto logo = image{Resource::Logo};
|
auto logo = image{Resource::Logo};
|
||||||
|
@ -9,14 +9,17 @@ AboutWindow::AboutWindow() : Locale::Namespace(ns, "About") {
|
||||||
canvas.setIcon(logo);
|
canvas.setIcon(logo);
|
||||||
tableLayout.setFont(Font().setBold());
|
tableLayout.setFont(Font().setBold());
|
||||||
tableLayout.setSize({2, 4});
|
tableLayout.setSize({2, 4});
|
||||||
tableLayout.column(0).setSpacing(3);
|
tableLayout.column(0).setSpacing(4);
|
||||||
versionLabel.setText(tr("Version:")).setAlignment(1.0);
|
tableLayout.row(0).setSpacing(2);
|
||||||
|
tableLayout.row(1).setSpacing(2);
|
||||||
|
tableLayout.row(2).setSpacing(2);
|
||||||
|
versionLabel.setText({tr("Version"), ":"}).setAlignment(1.0);
|
||||||
versionValue.setText(Emulator::Version);
|
versionValue.setText(Emulator::Version);
|
||||||
authorLabel.setText(tr("Author:")).setAlignment(1.0);
|
authorLabel.setText({tr("Author"), ":"}).setAlignment(1.0);
|
||||||
authorValue.setText(Emulator::Author);
|
authorValue.setText(Emulator::Author);
|
||||||
licenseLabel.setText(tr("License:")).setAlignment(1.0);
|
licenseLabel.setText({tr("License"), ":"}).setAlignment(1.0);
|
||||||
licenseValue.setText(Emulator::License);
|
licenseValue.setText(Emulator::License);
|
||||||
websiteLabel.setText(tr("Website:")).setAlignment(1.0);
|
websiteLabel.setText({tr("Website"), ":"}).setAlignment(1.0);
|
||||||
websiteValue.setText(Emulator::Website);
|
websiteValue.setText(Emulator::Website);
|
||||||
|
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
|
|
|
@ -3,24 +3,24 @@
|
||||||
unique_pointer<AboutWindow> aboutWindow;
|
unique_pointer<AboutWindow> aboutWindow;
|
||||||
unique_pointer<Presentation> presentation;
|
unique_pointer<Presentation> presentation;
|
||||||
|
|
||||||
Presentation::Presentation() : Locale::Namespace(ns, "Presentation") {
|
Presentation::Presentation() {
|
||||||
presentation = this;
|
presentation = this;
|
||||||
|
|
||||||
systemMenu.setText(tr("System"));
|
systemMenu.setText(tr("System"));
|
||||||
loadGame.setIcon(Icon::Action::Open).setText("Load Game ...").onActivate([&] {
|
loadGame.setIcon(Icon::Action::Open).setText({tr("Load Game"), " ..."}).onActivate([&] {
|
||||||
program->load();
|
program->load();
|
||||||
});
|
});
|
||||||
loadRecentGame.setIcon(Icon::Action::Open).setText("Load Recent Game");
|
loadRecentGame.setIcon(Icon::Action::Open).setText(tr("Load Recent Game"));
|
||||||
updateRecentGames();
|
updateRecentGames();
|
||||||
resetSystem.setIcon(Icon::Action::Refresh).setText("Reset System").setEnabled(false).onActivate([&] {
|
resetSystem.setIcon(Icon::Action::Refresh).setText(tr("Reset System")).setEnabled(false).onActivate([&] {
|
||||||
program->reset();
|
program->reset();
|
||||||
});
|
});
|
||||||
unloadGame.setIcon(Icon::Action::Remove).setText("Unload Game").setEnabled(false).onActivate([&] {
|
unloadGame.setIcon(Icon::Action::Remove).setText(tr("Unload Game")).setEnabled(false).onActivate([&] {
|
||||||
program->unload();
|
program->unload();
|
||||||
});
|
});
|
||||||
controllerPort1.setIcon(Icon::Device::Joypad).setText("Controller Port 1");
|
controllerPort1.setIcon(Icon::Device::Joypad).setText(tr("Controller Port 1"));
|
||||||
controllerPort2.setIcon(Icon::Device::Joypad).setText("Controller Port 2");
|
controllerPort2.setIcon(Icon::Device::Joypad).setText(tr("Controller Port 2"));
|
||||||
expansionPort.setIcon(Icon::Device::Storage).setText("Expansion Port");
|
expansionPort.setIcon(Icon::Device::Storage).setText(tr("Expansion Port"));
|
||||||
for(auto& port : emulator->ports) {
|
for(auto& port : emulator->ports) {
|
||||||
Menu* menu = nullptr;
|
Menu* menu = nullptr;
|
||||||
if(port.name == "Controller Port 1") menu = &controllerPort1;
|
if(port.name == "Controller Port 1") menu = &controllerPort1;
|
||||||
|
@ -33,7 +33,7 @@ Presentation::Presentation() : Locale::Namespace(ns, "Presentation") {
|
||||||
if(port.name != "Expansion Port" && device.name == "None") continue;
|
if(port.name != "Expansion Port" && device.name == "None") continue;
|
||||||
if(port.name == "Expansion Port" && device.name == "21fx") continue;
|
if(port.name == "Expansion Port" && device.name == "21fx") continue;
|
||||||
MenuRadioItem item{menu};
|
MenuRadioItem item{menu};
|
||||||
item.setText(device.name).onActivate([=] {
|
item.setText(tr(device.name)).onActivate([=] {
|
||||||
auto path = string{"Emulator/", port.name}.replace(" ", "");
|
auto path = string{"Emulator/", port.name}.replace(" ", "");
|
||||||
settings(path).setValue(device.name);
|
settings(path).setValue(device.name);
|
||||||
emulator->connect(port.id, device.id);
|
emulator->connect(port.id, device.id);
|
||||||
|
@ -53,7 +53,7 @@ Presentation::Presentation() : Locale::Namespace(ns, "Presentation") {
|
||||||
devices.objects<MenuRadioItem>()(0).doActivate();
|
devices.objects<MenuRadioItem>()(0).doActivate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
quit.setIcon(Icon::Action::Quit).setText("Quit").onActivate([&] { program->quit(); });
|
quit.setIcon(Icon::Action::Quit).setText(tr("Quit")).onActivate([&] { program->quit(); });
|
||||||
|
|
||||||
settingsMenu.setText(tr("Settings"));
|
settingsMenu.setText(tr("Settings"));
|
||||||
sizeMenu.setIcon(Icon::Emblem::Image).setText("Size");
|
sizeMenu.setIcon(Icon::Emblem::Image).setText("Size");
|
||||||
|
@ -132,6 +132,9 @@ Presentation::Presentation() : Locale::Namespace(ns, "Presentation") {
|
||||||
loadState.append(MenuItem().setIcon(Icon::Edit::Undo).setText("Undo Last Save").onActivate([&] {
|
loadState.append(MenuItem().setIcon(Icon::Edit::Undo).setText("Undo Last Save").onActivate([&] {
|
||||||
program->loadState("quick/undo");
|
program->loadState("quick/undo");
|
||||||
}));
|
}));
|
||||||
|
loadState.append(MenuItem().setIcon(Icon::Edit::Redo).setText("Redo Last Undo").onActivate([&] {
|
||||||
|
program->loadState("quick/redo");
|
||||||
|
}));
|
||||||
speedMenu.setIcon(Icon::Device::Clock).setText("Speed");
|
speedMenu.setIcon(Icon::Device::Clock).setText("Speed");
|
||||||
speedSlowest.setText("50% (Slowest)").setProperty("multiplier", "2.0").onActivate([&] { program->updateAudioFrequency(); });
|
speedSlowest.setText("50% (Slowest)").setProperty("multiplier", "2.0").onActivate([&] { program->updateAudioFrequency(); });
|
||||||
speedSlow.setText("75% (Slow)").setProperty("multiplier", "1.333").onActivate([&] { program->updateAudioFrequency(); });
|
speedSlow.setText("75% (Slow)").setProperty("multiplier", "1.333").onActivate([&] { program->updateAudioFrequency(); });
|
||||||
|
@ -153,10 +156,10 @@ Presentation::Presentation() : Locale::Namespace(ns, "Presentation") {
|
||||||
manifestViewer.setIcon(Icon::Emblem::Text).setText("Manifest Viewer ...").onActivate([&] { toolsWindow->show(2); });
|
manifestViewer.setIcon(Icon::Emblem::Text).setText("Manifest Viewer ...").onActivate([&] { toolsWindow->show(2); });
|
||||||
|
|
||||||
helpMenu.setText(tr("Help"));
|
helpMenu.setText(tr("Help"));
|
||||||
documentation.setIcon(Icon::Application::Browser).setText("Documentation ...").onActivate([&] {
|
documentation.setIcon(Icon::Application::Browser).setText({tr("Documentation"), " ..."}).onActivate([&] {
|
||||||
invoke("https://doc.byuu.org/bsnes/");
|
invoke("https://doc.byuu.org/bsnes/");
|
||||||
});
|
});
|
||||||
about.setIcon(Icon::Prompt::Question).setText("About ...").onActivate([&] {
|
about.setIcon(Icon::Prompt::Question).setText({tr("About"), " ..."}).onActivate([&] {
|
||||||
aboutWindow->setCentered(*this).setVisible().setFocused();
|
aboutWindow->setCentered(*this).setVisible().setFocused();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -245,7 +248,7 @@ auto Presentation::updateStatusIcon() -> void {
|
||||||
auto Presentation::drawIcon(uint32_t* output, uint length, uint width, uint height) -> void {
|
auto Presentation::drawIcon(uint32_t* output, uint length, uint width, uint height) -> void {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int ox = width - 144;
|
int ox = width - 144;
|
||||||
int oy = height - 128;
|
int oy = height - 128;
|
||||||
if(ox >= 0 && oy >= 0) {
|
if(ox >= 0 && oy >= 0) {
|
||||||
image icon{Resource::Icon};
|
image icon{Resource::Icon};
|
||||||
|
@ -259,11 +262,8 @@ auto Presentation::drawIcon(uint32_t* output, uint length, uint width, uint heig
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Presentation::clearViewport() -> void {
|
auto Presentation::clearViewport() -> void {
|
||||||
if(!visible() && !video) return;
|
if(!emulator->loaded()) viewportLayout.setPadding();
|
||||||
|
if(!visible() || !video) return;
|
||||||
if(!emulator->loaded()) {
|
|
||||||
viewportLayout.setPadding();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t* output;
|
uint32_t* output;
|
||||||
uint length;
|
uint length;
|
||||||
|
@ -288,7 +288,7 @@ auto Presentation::resizeViewport() -> void {
|
||||||
uint height = (settings["View/OverscanCropping"].boolean() ? 224.0 : 240.0);
|
uint height = (settings["View/OverscanCropping"].boolean() ? 224.0 : 240.0);
|
||||||
uint viewportWidth, viewportHeight;
|
uint viewportWidth, viewportHeight;
|
||||||
|
|
||||||
if(!fullScreen()) {
|
if(visible() && !fullScreen()) {
|
||||||
uint widthMultiplier = windowWidth / width;
|
uint widthMultiplier = windowWidth / width;
|
||||||
uint heightMultiplier = windowHeight / height;
|
uint heightMultiplier = windowHeight / height;
|
||||||
uint multiplier = max(1, min(widthMultiplier, heightMultiplier));
|
uint multiplier = max(1, min(widthMultiplier, heightMultiplier));
|
||||||
|
@ -300,8 +300,8 @@ auto Presentation::resizeViewport() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!visible() || !video) return;
|
|
||||||
if(!emulator->loaded()) return clearViewport();
|
if(!emulator->loaded()) return clearViewport();
|
||||||
|
if(!video) return;
|
||||||
|
|
||||||
if(settings["View/Output"].text() == "Center") {
|
if(settings["View/Output"].text() == "Center") {
|
||||||
uint widthMultiplier = windowWidth / width;
|
uint widthMultiplier = windowWidth / width;
|
||||||
|
@ -450,14 +450,14 @@ auto Presentation::updateRecentGames() -> void {
|
||||||
program->load();
|
program->load();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
item.setText("<empty>");
|
item.setText(tr("Empty"));
|
||||||
item.setEnabled(false);
|
item.setEnabled(false);
|
||||||
}
|
}
|
||||||
loadRecentGame.append(item);
|
loadRecentGame.append(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadRecentGame.append(MenuSeparator());
|
loadRecentGame.append(MenuSeparator());
|
||||||
loadRecentGame.append(MenuItem().setIcon(Icon::Edit::Clear).setText("Clear List").onActivate([&] {
|
loadRecentGame.append(MenuItem().setIcon(Icon::Edit::Clear).setText(tr("Clear List")).onActivate([&] {
|
||||||
for(auto index : range(RecentGames)) {
|
for(auto index : range(RecentGames)) {
|
||||||
settings({"Game/Recent/", 1 + index}).setValue("");
|
settings({"Game/Recent/", 1 + index}).setValue("");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
struct AboutWindow : Locale::Namespace, Window {
|
struct AboutWindow : Window {
|
||||||
|
Application::Namespace tr{"AboutWindow"};
|
||||||
|
|
||||||
AboutWindow();
|
AboutWindow();
|
||||||
|
|
||||||
VerticalLayout layout{this};
|
VerticalLayout layout{this};
|
||||||
|
@ -17,7 +19,9 @@ struct AboutWindow : Locale::Namespace, Window {
|
||||||
Label websiteValue{&tableLayout, Size{~0, 0}};
|
Label websiteValue{&tableLayout, Size{~0, 0}};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Presentation : Locale::Namespace, Window {
|
struct Presentation : Window {
|
||||||
|
Application::Namespace tr{"Presentation"};
|
||||||
|
|
||||||
enum : uint { RecentGames = 9, QuickStates = 9 };
|
enum : uint { RecentGames = 9, QuickStates = 9 };
|
||||||
enum : uint { StatusHeight = 24 };
|
enum : uint { StatusHeight = 24 };
|
||||||
|
|
||||||
|
@ -103,7 +107,7 @@ struct Presentation : Locale::Namespace, Window {
|
||||||
Canvas statusIcon{&statusLayout, Size{16, ~0}, 0};
|
Canvas statusIcon{&statusLayout, Size{16, ~0}, 0};
|
||||||
Label spacerLeft{&statusLayout, Size{4, ~0}, 0};
|
Label spacerLeft{&statusLayout, Size{4, ~0}, 0};
|
||||||
Label statusLeft{&statusLayout, Size{~0, ~0}, 0};
|
Label statusLeft{&statusLayout, Size{~0, ~0}, 0};
|
||||||
Label statusRight{&statusLayout, Size{80, ~0}, 0};
|
Label statusRight{&statusLayout, Size{100, ~0}, 0};
|
||||||
Label spacerRight{&statusLayout, Size{8, ~0}, 0};
|
Label spacerRight{&statusLayout, Size{8, ~0}, 0};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ auto Program::load() -> void {
|
||||||
program->loadState("quick/undo");
|
program->loadState("quick/undo");
|
||||||
}
|
}
|
||||||
showMessage({
|
showMessage({
|
||||||
verified() ? "Verified" : "Unverified", " game loaded",
|
verified() ? "Verified game loaded" : "Game loaded",
|
||||||
appliedPatch() ? " and patch applied" : ""
|
appliedPatch() ? " and patch applied" : ""
|
||||||
});
|
});
|
||||||
presentation->setTitle(emulator->title());
|
presentation->setTitle(emulator->title());
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "hacks.cpp"
|
#include "hacks.cpp"
|
||||||
unique_pointer<Program> program;
|
unique_pointer<Program> program;
|
||||||
|
|
||||||
Program::Program(string_vector arguments) : Locale::Namespace(ns, "Program") {
|
Program::Program(string_vector arguments) {
|
||||||
program = this;
|
program = this;
|
||||||
Emulator::platform = this;
|
Emulator::platform = this;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
struct Program : Locale::Namespace, Emulator::Platform {
|
struct Program : Emulator::Platform {
|
||||||
|
Application::Namespace tr{"Program"};
|
||||||
|
|
||||||
//program.cpp
|
//program.cpp
|
||||||
Program(string_vector arguments);
|
Program(string_vector arguments);
|
||||||
auto main() -> void;
|
auto main() -> void;
|
||||||
|
@ -51,6 +53,7 @@ struct Program : Locale::Namespace, Emulator::Platform {
|
||||||
auto loadState(string filename) -> bool;
|
auto loadState(string filename) -> bool;
|
||||||
auto saveState(string filename) -> bool;
|
auto saveState(string filename) -> bool;
|
||||||
auto saveUndoState() -> bool;
|
auto saveUndoState() -> bool;
|
||||||
|
auto saveRedoState() -> bool;
|
||||||
auto removeState(string filename) -> bool;
|
auto removeState(string filename) -> bool;
|
||||||
auto renameState(string from, string to) -> bool;
|
auto renameState(string from, string to) -> bool;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ auto Program::loadState(string filename) -> bool {
|
||||||
string location = {statePath(), filename, ".bst"};
|
string location = {statePath(), filename, ".bst"};
|
||||||
if(!file::exists(location)) return showMessage({"[", prefix, "] not found"}), false;
|
if(!file::exists(location)) return showMessage({"[", prefix, "] not found"}), false;
|
||||||
if(filename != "quick/undo") saveUndoState();
|
if(filename != "quick/undo") saveUndoState();
|
||||||
|
if(filename == "quick/undo") saveRedoState();
|
||||||
memory = file::read(location);
|
memory = file::read(location);
|
||||||
} else {
|
} else {
|
||||||
string location = {filename, ".bst"};
|
string location = {filename, ".bst"};
|
||||||
|
@ -96,6 +97,15 @@ auto Program::saveUndoState() -> bool {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Program::saveRedoState() -> bool {
|
||||||
|
auto statusTime = this->statusTime;
|
||||||
|
auto statusMessage = this->statusMessage;
|
||||||
|
auto result = saveState("quick/redo");
|
||||||
|
this->statusTime = statusTime;
|
||||||
|
this->statusMessage = statusMessage;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
auto Program::removeState(string filename) -> bool {
|
auto Program::removeState(string filename) -> bool {
|
||||||
if(!emulator->loaded()) return false;
|
if(!emulator->loaded()) return false;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,35 @@
|
||||||
locale
|
locale
|
||||||
language: 日本語
|
language: 日本語
|
||||||
|
|
||||||
|
namespace: MessageDialog
|
||||||
|
map
|
||||||
|
input: Yes
|
||||||
|
value: はい
|
||||||
|
map
|
||||||
|
input: No
|
||||||
|
value: いいえ
|
||||||
|
map
|
||||||
|
input: Cancel
|
||||||
|
value: キャンセル
|
||||||
|
|
||||||
|
namespace: BrowserDialog
|
||||||
|
map
|
||||||
|
input: Open
|
||||||
|
value: 開く
|
||||||
|
map
|
||||||
|
input: Save
|
||||||
|
value: 保存
|
||||||
|
map
|
||||||
|
input: Select
|
||||||
|
value: 選択
|
||||||
|
map
|
||||||
|
input: Cancel
|
||||||
|
value: キャンセル
|
||||||
|
|
||||||
namespace: Program
|
namespace: Program
|
||||||
|
map
|
||||||
|
input: Unloaded
|
||||||
|
value: アンロードされる
|
||||||
map
|
map
|
||||||
input: Paused
|
input: Paused
|
||||||
value: ポーズ
|
value: ポーズ
|
||||||
|
@ -10,6 +38,60 @@ namespace: Presentation
|
||||||
map
|
map
|
||||||
input: System
|
input: System
|
||||||
value: システム
|
value: システム
|
||||||
|
map
|
||||||
|
input: Load Game
|
||||||
|
value: ゲームを読み込み
|
||||||
|
map
|
||||||
|
input: Load Recent Game
|
||||||
|
value: 最新ゲームを読み込み
|
||||||
|
map
|
||||||
|
input: Empty
|
||||||
|
value: なし
|
||||||
|
map
|
||||||
|
input: Clear List
|
||||||
|
value: 全部を消す
|
||||||
|
map
|
||||||
|
input: Reset System
|
||||||
|
value: システムをリセット
|
||||||
|
map
|
||||||
|
input: Unload Game
|
||||||
|
value: ゲームをアンロード
|
||||||
|
map
|
||||||
|
input: Controller Port 1
|
||||||
|
value: コントローラポート1
|
||||||
|
map
|
||||||
|
input: Controller Port 2
|
||||||
|
value: コントローラポート2
|
||||||
|
map
|
||||||
|
input: Expansion Port
|
||||||
|
value: 拡張ポート
|
||||||
|
map
|
||||||
|
input: Gamepad
|
||||||
|
value: ゲームパッド
|
||||||
|
map
|
||||||
|
input: Mouse
|
||||||
|
value: マウス
|
||||||
|
map
|
||||||
|
input: Super Multitap
|
||||||
|
value: スーパーマルチタップ
|
||||||
|
map
|
||||||
|
input: Super Scope
|
||||||
|
value: スーパースコップ
|
||||||
|
map
|
||||||
|
input: Justifier
|
||||||
|
value: 1挺のジャスティファイアー
|
||||||
|
map
|
||||||
|
input: Justifiers
|
||||||
|
value: 2挺のジャスティファイアー
|
||||||
|
map
|
||||||
|
input: None
|
||||||
|
value: なし
|
||||||
|
map
|
||||||
|
input: Satellaview
|
||||||
|
value: サテラビュー
|
||||||
|
map
|
||||||
|
input: Quit
|
||||||
|
value: 終了
|
||||||
map
|
map
|
||||||
input: Settings
|
input: Settings
|
||||||
value: 設定
|
value: 設定
|
||||||
|
@ -19,22 +101,27 @@ namespace: Presentation
|
||||||
map
|
map
|
||||||
input: Help
|
input: Help
|
||||||
value: ヘルプ
|
value: ヘルプ
|
||||||
|
map
|
||||||
|
input: Documentation
|
||||||
|
value: オンラインマニュアル
|
||||||
|
map
|
||||||
|
input: About
|
||||||
|
value: 情報
|
||||||
|
|
||||||
namespace: About
|
namespace: AboutWindow
|
||||||
map
|
map
|
||||||
input: About {0} ...
|
input: About {0}
|
||||||
value: {0}について ...
|
value: {0}について
|
||||||
|
map
|
||||||
map
|
input: Version
|
||||||
input: Version:
|
value: バージョン
|
||||||
value: バージョン:
|
map
|
||||||
map
|
input: Author
|
||||||
input: Author:
|
value: 作者
|
||||||
value: 作者:
|
map
|
||||||
map
|
input: License
|
||||||
input: License:
|
value: ライセンス
|
||||||
value: ライセンス:
|
map
|
||||||
map
|
input: Website
|
||||||
input: Website:
|
value: 公式サイト
|
||||||
value: 公式サイト:
|
|
||||||
|
|
||||||
|
|
|
@ -11,35 +11,16 @@ include gba/GNUmakefile
|
||||||
include ws/GNUmakefile
|
include ws/GNUmakefile
|
||||||
include processor/GNUmakefile
|
include processor/GNUmakefile
|
||||||
|
|
||||||
objects := ruby hiro $(if $(call streq,$(platform),windows),hiro-resource) $(objects)
|
hiro.path := ../hiro
|
||||||
objects += ui-higan ui-program ui-input
|
hiro.resource := $(ui)/resource/higan.rc
|
||||||
objects += ui-settings ui-tools ui-presentation ui-resource
|
include $(hiro.path)/GNUmakefile
|
||||||
objects := $(objects:%=obj/%.o)
|
|
||||||
|
|
||||||
ifeq ($(platform),windows)
|
|
||||||
ruby += video.wgl video.direct3d video.directdraw video.gdi
|
|
||||||
ruby += audio.asio audio.wasapi audio.xaudio2 audio.directsound
|
|
||||||
ruby += input.windows
|
|
||||||
else ifeq ($(platform),macos)
|
|
||||||
ruby += video.cgl
|
|
||||||
ruby += audio.openal
|
|
||||||
ruby += input.quartz input.carbon
|
|
||||||
else ifeq ($(platform),linux)
|
|
||||||
ruby += video.glx video.xvideo video.xshm
|
|
||||||
ruby += audio.oss audio.alsa audio.openal audio.pulseaudio audio.pulseaudiosimple audio.ao
|
|
||||||
ruby += input.sdl input.xlib input.udev
|
|
||||||
else ifeq ($(platform),bsd)
|
|
||||||
ruby += video.glx video.xvideo video.xshm
|
|
||||||
ruby += audio.oss audio.openal
|
|
||||||
ruby += input.sdl input.xlib
|
|
||||||
endif
|
|
||||||
|
|
||||||
ruby.path := ../ruby
|
ruby.path := ../ruby
|
||||||
include $(ruby.path)/GNUmakefile
|
include $(ruby.path)/GNUmakefile
|
||||||
|
|
||||||
hiro.path := ../hiro
|
objects += ui-higan ui-program ui-input
|
||||||
hiro.resource := $(ui)/resource/higan.rc
|
objects += ui-settings ui-tools ui-presentation ui-resource
|
||||||
include $(hiro.path)/GNUmakefile
|
objects := $(objects:%=obj/%.o)
|
||||||
|
|
||||||
obj/ui-higan.o: $(ui)/higan.cpp
|
obj/ui-higan.o: $(ui)/higan.cpp
|
||||||
obj/ui-program.o: $(ui)/program/program.cpp
|
obj/ui-program.o: $(ui)/program/program.cpp
|
||||||
|
@ -49,10 +30,9 @@ obj/ui-tools.o: $(ui)/tools/tools.cpp
|
||||||
obj/ui-presentation.o: $(ui)/presentation/presentation.cpp
|
obj/ui-presentation.o: $(ui)/presentation/presentation.cpp
|
||||||
obj/ui-resource.o: $(ui)/resource/resource.cpp
|
obj/ui-resource.o: $(ui)/resource/resource.cpp
|
||||||
|
|
||||||
# targets
|
all: $(hiro.objects) $(ruby.objects) $(objects)
|
||||||
all: $(objects)
|
|
||||||
$(info Linking out/$(name) ...)
|
$(info Linking out/$(name) ...)
|
||||||
+@$(strip $(compiler) -o out/$(name) $(objects) $(options) $(ruby.options) $(hiro.options))
|
+@$(compiler) -o out/$(name) $(hiro.objects) $(ruby.objects) $(objects) $(hiro.options) $(ruby.options) $(options)
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
rm -rf out/$(name).app
|
rm -rf out/$(name).app
|
||||||
mkdir -p out/$(name).app/Contents/MacOS/
|
mkdir -p out/$(name).app/Contents/MacOS/
|
||||||
|
@ -62,6 +42,8 @@ ifeq ($(platform),macos)
|
||||||
sips -s format icns $(ui)/resource/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
|
sips -s format icns $(ui)/resource/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
verbose: hiro.verbose ruby.verbose nall.verbose all;
|
||||||
|
|
||||||
install:
|
install:
|
||||||
ifeq ($(shell id -un),root)
|
ifeq ($(shell id -un),root)
|
||||||
$(error "make install should not be run as root")
|
$(error "make install should not be run as root")
|
||||||
|
|
|
@ -63,16 +63,24 @@ ifneq ($(filter $(platform),linux bsd),)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(object.path)/hiro.o: $(hiro.path)/hiro.cpp $(call rwildcard,$(hiro.path)) $(call rwildcard,$(nall.path))
|
|
||||||
$(if $(filter qt%,$(hiro)),$(info Compiling $(hiro.path)/qt/qt.moc ...))
|
|
||||||
$(if $(filter qt%,$(hiro)),@$(moc) -i -o $(hiro.path)/qt/qt.moc $(hiro.path)/qt/qt.hpp)
|
|
||||||
$(info Compiling $< ...)
|
|
||||||
@$(compiler) $(flags) $(hiro.flags) -c $< -o $@
|
|
||||||
|
|
||||||
ifeq ($(hiro.resource),)
|
ifeq ($(hiro.resource),)
|
||||||
hiro.resource := $(hiro.path)/windows/hiro.rc
|
hiro.resource := $(hiro.path)/windows/hiro.rc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
hiro.objects := \
|
||||||
|
$(object.path)/hiro-$(hiro).o \
|
||||||
|
$(if $(filter windows,$(hiro)),$(object.path)/hiro-resource.o)
|
||||||
|
|
||||||
|
$(object.path)/hiro-$(hiro).o: $(hiro.path)/hiro.cpp
|
||||||
|
$(if $(filter qt%,$(hiro)),$(info Compiling $(hiro.path)/qt/qt.moc ...))
|
||||||
|
$(if $(filter qt%,$(hiro)),@$(moc) -i -o $(hiro.path)/qt/qt.moc $(hiro.path)/qt/qt.hpp)
|
||||||
|
$(info Compiling $< ...)
|
||||||
|
@$(compiler) $(hiro.flags) $(flags) $(flags.deps) -c $< -o $@
|
||||||
|
|
||||||
$(object.path)/hiro-resource.o: $(hiro.resource)
|
$(object.path)/hiro-resource.o: $(hiro.resource)
|
||||||
$(if $(filter windows,$(hiro)),$(info Compiling $< ...))
|
$(info Compiling $< ...)
|
||||||
$(if $(filter windows,$(hiro)),@$(windres) $< $@)
|
@$(windres) $< $@
|
||||||
|
|
||||||
|
hiro.verbose:
|
||||||
|
$(info hiro Target:)
|
||||||
|
$(info $([space]) $(hiro))
|
||||||
|
|
|
@ -5,7 +5,10 @@ namespace hiro {
|
||||||
auto pDesktop::size() -> Size {
|
auto pDesktop::size() -> Size {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSRect primary = [[[NSScreen screens] objectAtIndex:0] frame];
|
NSRect primary = [[[NSScreen screens] objectAtIndex:0] frame];
|
||||||
return {(int)primary.size.width, (int)primary.size.height};
|
return {
|
||||||
|
(int)primary.size.width,
|
||||||
|
(int)primary.size.height
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +16,12 @@ auto pDesktop::workspace() -> Geometry {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
auto screen = Desktop::size();
|
auto screen = Desktop::size();
|
||||||
NSRect area = [[[NSScreen screens] objectAtIndex:0] visibleFrame];
|
NSRect area = [[[NSScreen screens] objectAtIndex:0] visibleFrame];
|
||||||
return {(int)area.origin.x, (int)(screen.height() - area.size.height - area.origin.y), (int)area.size.width, (int)area.size.height};
|
return {
|
||||||
|
(int)area.origin.x,
|
||||||
|
(int)area.origin.y,
|
||||||
|
(int)area.size.width,
|
||||||
|
(int)area.size.height
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,33 @@ auto pMonitor::dpi(uint monitor) -> Position {
|
||||||
auto pMonitor::geometry(uint monitor) -> Geometry {
|
auto pMonitor::geometry(uint monitor) -> Geometry {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSRect rectangle = [[[NSScreen screens] objectAtIndex:monitor] frame];
|
NSRect rectangle = [[[NSScreen screens] objectAtIndex:monitor] frame];
|
||||||
return {(int)rectangle.origin.x, (int)rectangle.origin.y, (int)rectangle.size.width, (int)rectangle.size.height};
|
return {
|
||||||
|
(int)rectangle.origin.x,
|
||||||
|
(int)rectangle.origin.y,
|
||||||
|
(int)rectangle.size.width,
|
||||||
|
(int)rectangle.size.height
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pMonitor::primary() -> uint {
|
auto pMonitor::primary() -> uint {
|
||||||
//on OS X, the primary monitor is always the first monitor
|
//on macOS, the primary monitor is always the first monitor
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto pMonitor::workspace(uint monitor) -> Geometry {
|
||||||
|
@autoreleasepool {
|
||||||
|
NSRect size = [[[NSScreen screens] objectAtIndex:monitor] frame];
|
||||||
|
NSRect area = [[[NSScreen screens] objectAtIndex:monitor] visibleFrame];
|
||||||
|
return {
|
||||||
|
(int)area.origin.x,
|
||||||
|
(int)area.origin.y,
|
||||||
|
(int)area.size.width,
|
||||||
|
(int)area.size.height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,6 +7,7 @@ struct pMonitor {
|
||||||
static auto dpi(uint monitor) -> Position;
|
static auto dpi(uint monitor) -> Position;
|
||||||
static auto geometry(uint monitor) -> Geometry;
|
static auto geometry(uint monitor) -> Geometry;
|
||||||
static auto primary() -> uint;
|
static auto primary() -> uint;
|
||||||
|
static auto workspace(uint monitor) -> Geometry;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,3 @@
|
||||||
namespace hiro {
|
|
||||||
struct pFont;
|
|
||||||
struct pWindow;
|
|
||||||
struct pMenu;
|
|
||||||
struct pLayout;
|
|
||||||
struct pWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Declare(Name, Base) \
|
#define Declare(Name, Base) \
|
||||||
p##Name(m##Name& reference) : p##Base(reference) {} \
|
p##Name(m##Name& reference) : p##Base(reference) {} \
|
||||||
auto self() const -> m##Name& { return (m##Name&)reference; } \
|
auto self() const -> m##Name& { return (m##Name&)reference; } \
|
||||||
|
|
|
@ -39,14 +39,14 @@ auto pFrame::remove(sSizable sizable) -> void {
|
||||||
|
|
||||||
auto pFrame::setEnabled(bool enabled) -> void {
|
auto pFrame::setEnabled(bool enabled) -> void {
|
||||||
pWidget::setEnabled(enabled);
|
pWidget::setEnabled(enabled);
|
||||||
if(auto& sizable = _sizable()) sizable->setEnabled(sizable->self().enabled(true));
|
if(auto sizable = _sizable()) sizable->setEnabled(sizable->self().enabled(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pFrame::setFont(const Font& font) -> void {
|
auto pFrame::setFont(const Font& font) -> void {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaView setTitleFont:pFont::create(font)];
|
[cocoaView setTitleFont:pFont::create(font)];
|
||||||
}
|
}
|
||||||
if(auto& sizable = _sizable()) sizable->setFont(sizable->self().font(true));
|
if(auto sizable = _sizable()) sizable->setFont(sizable->self().font(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pFrame::setGeometry(Geometry geometry) -> void {
|
auto pFrame::setGeometry(Geometry geometry) -> void {
|
||||||
|
@ -56,7 +56,7 @@ auto pFrame::setGeometry(Geometry geometry) -> void {
|
||||||
geometry.x() - 3, geometry.y() - (empty ? size.height() - 2 : 1),
|
geometry.x() - 3, geometry.y() - (empty ? size.height() - 2 : 1),
|
||||||
geometry.width() + 6, geometry.height() + (empty ? size.height() + 2 : 5)
|
geometry.width() + 6, geometry.height() + (empty ? size.height() + 2 : 5)
|
||||||
});
|
});
|
||||||
if(auto& sizable = state().sizable) {
|
if(auto sizable = _sizable()) {
|
||||||
sizable->setGeometry({
|
sizable->setGeometry({
|
||||||
geometry.x() + 1, geometry.y() + (empty ? 1 : size.height() - 2),
|
geometry.x() + 1, geometry.y() + (empty ? 1 : size.height() - 2),
|
||||||
geometry.width() - 2, geometry.height() - (empty ? 1 : size.height() - 1)
|
geometry.width() - 2, geometry.height() - (empty ? 1 : size.height() - 1)
|
||||||
|
@ -72,14 +72,14 @@ auto pFrame::setText(const string& text) -> void {
|
||||||
|
|
||||||
auto pFrame::setVisible(bool visible) -> void {
|
auto pFrame::setVisible(bool visible) -> void {
|
||||||
pWidget::setVisible(visible);
|
pWidget::setVisible(visible);
|
||||||
if(auto& sizable = _sizable()) sizable->setVisible(sizable->self().visible(true));
|
if(auto sizable = _sizable()) sizable->setVisible(sizable->self().visible(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pFrame::_sizable() -> maybe<pSizable&> {
|
auto pFrame::_sizable() -> maybe<pSizable&> {
|
||||||
if(auto sizable = state().sizable) {
|
if(auto sizable = state().sizable) {
|
||||||
if(auto self = sizable->self()) return *self;
|
if(auto self = sizable->self()) return *self;
|
||||||
}
|
}
|
||||||
return nothing;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) tabView:(NSTabView*)tabView didSelectTabViewItem:(NSTabViewItem*)tabViewItem {
|
-(void) tabView:(NSTabView*)tabView didSelectTabViewItem:(NSTabViewItem*)tabViewItem {
|
||||||
tabFrame->self()->_synchronizeLayout();
|
tabFrame->self()->_synchronizeSizable();
|
||||||
tabFrame->doChange();
|
tabFrame->doChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +104,8 @@ auto pTabFrame::remove(sTabFrameItem item) -> void {
|
||||||
auto pTabFrame::setEnabled(bool enabled) -> void {
|
auto pTabFrame::setEnabled(bool enabled) -> void {
|
||||||
pWidget::setEnabled(enabled);
|
pWidget::setEnabled(enabled);
|
||||||
for(auto& item : state().items) {
|
for(auto& item : state().items) {
|
||||||
if(auto& layout = item->state.layout) {
|
if(auto& sizable = item->state.sizable) {
|
||||||
if(auto self = layout->self()) self->setEnabled(layout->enabled(true));
|
if(auto self = sizable->self()) self->setEnabled(sizable->enabled(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,8 +113,8 @@ auto pTabFrame::setEnabled(bool enabled) -> void {
|
||||||
auto pTabFrame::setFont(const Font& font) -> void {
|
auto pTabFrame::setFont(const Font& font) -> void {
|
||||||
pWidget::setFont(font);
|
pWidget::setFont(font);
|
||||||
for(auto& item : state().items) {
|
for(auto& item : state().items) {
|
||||||
if(auto& layout = item->state.layout) {
|
if(auto& sizable = item->state.sizable) {
|
||||||
if(auto self = layout->self()) self->setFont(layout->font(true));
|
if(auto self = sizable->self()) self->setFont(sizable->font(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,11 +129,11 @@ auto pTabFrame::setGeometry(Geometry geometry) -> void {
|
||||||
geometry.width() - 2, geometry.height() - 32
|
geometry.width() - 2, geometry.height() - 32
|
||||||
});
|
});
|
||||||
for(auto& item : state().items) {
|
for(auto& item : state().items) {
|
||||||
if(auto& layout = item->state.layout) {
|
if(auto& sizable = item->state.sizable) {
|
||||||
layout->setGeometry(geometry);
|
sizable->setGeometry(geometry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_synchronizeLayout();
|
_synchronizeSizable();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTabFrame::setNavigation(Navigation navigation) -> void {
|
auto pTabFrame::setNavigation(Navigation navigation) -> void {
|
||||||
|
@ -142,20 +142,20 @@ auto pTabFrame::setNavigation(Navigation navigation) -> void {
|
||||||
auto pTabFrame::setVisible(bool visible) -> void {
|
auto pTabFrame::setVisible(bool visible) -> void {
|
||||||
pWidget::setVisible(visible);
|
pWidget::setVisible(visible);
|
||||||
for(auto& item : state().items) {
|
for(auto& item : state().items) {
|
||||||
if(auto& layout = item->state.layout) {
|
if(auto& sizable = item->state.sizable) {
|
||||||
if(auto self = layout->self()) self->setVisible(layout->visible(true));
|
if(auto self = sizable->self()) self->setVisible(sizable->visible(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTabFrame::_synchronizeLayout() -> void {
|
auto pTabFrame::_synchronizeSizable() -> void {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSTabViewItem* tabViewItem = [cocoaView selectedTabViewItem];
|
NSTabViewItem* tabViewItem = [cocoaView selectedTabViewItem];
|
||||||
int selected = tabViewItem ? [cocoaView indexOfTabViewItem:tabViewItem] : -1;
|
int selected = tabViewItem ? [cocoaView indexOfTabViewItem:tabViewItem] : -1;
|
||||||
for(auto& item : state().items) {
|
for(auto& item : state().items) {
|
||||||
item->state.selected = item->offset() == selected;
|
item->state.selected = item->offset() == selected;
|
||||||
if(auto& layout = item->state.layout) {
|
if(auto& sizable = item->state.sizable) {
|
||||||
if(auto self = layout->self()) self->setVisible(layout->visible(true) && item->selected());
|
if(auto self = sizable->self()) self->setVisible(sizable->visible(true) && item->selected());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ struct pTabFrame : pWidget {
|
||||||
auto setNavigation(Navigation navigation) -> void;
|
auto setNavigation(Navigation navigation) -> void;
|
||||||
auto setVisible(bool visible) -> void override;
|
auto setVisible(bool visible) -> void override;
|
||||||
|
|
||||||
auto _synchronizeLayout() -> void;
|
auto _synchronizeSizable() -> void;
|
||||||
|
|
||||||
CocoaTabFrame* cocoaTabFrame = nullptr;
|
CocoaTabFrame* cocoaTabFrame = nullptr;
|
||||||
vector<CocoaTabFrameItem*> tabs;
|
vector<CocoaTabFrameItem*> tabs;
|
||||||
|
|
|
@ -406,7 +406,7 @@ auto pTableView::_width(uint column) -> uint {
|
||||||
uint width = 1;
|
uint width = 1;
|
||||||
if(!header->column(column).visible()) return width;
|
if(!header->column(column).visible()) return width;
|
||||||
if(header->visible()) width = max(width, _columnWidth(column));
|
if(header->visible()) width = max(width, _columnWidth(column));
|
||||||
for(auto row : range(state().items)) {
|
for(auto row : range(state().items.size())) {
|
||||||
width = max(width, _cellWidth(row, column));
|
width = max(width, _cellWidth(row, column));
|
||||||
}
|
}
|
||||||
return width;
|
return width;
|
||||||
|
|
|
@ -217,7 +217,7 @@ auto pWindow::append(sMenuBar menuBar) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::append(sSizable sizable) -> void {
|
auto pWindow::append(sSizable sizable) -> void {
|
||||||
layout->setGeometry(self().geometry().setPosition(0, 0));
|
sizable->setGeometry(self().geometry().setPosition());
|
||||||
statusBarReposition();
|
statusBarReposition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,8 +320,8 @@ auto pWindow::setGeometry(Geometry geometry) -> void {
|
||||||
display:YES
|
display:YES
|
||||||
];
|
];
|
||||||
|
|
||||||
if(auto& layout = state().layout) {
|
if(auto& sizable = state().sizable) {
|
||||||
layout->setGeometry(self().geometry().setPosition(0, 0));
|
sizable->setGeometry(self().geometry().setPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
statusBarReposition();
|
statusBarReposition();
|
||||||
|
@ -402,8 +402,8 @@ auto pWindow::sizeEvent() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto& layout = state().layout) {
|
if(auto& sizable = state().sizable) {
|
||||||
layout->setGeometry(self().geometry().setPosition(0, 0));
|
sizable->setGeometry(self().geometry().setPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
statusBarReposition();
|
statusBarReposition();
|
||||||
|
|
|
@ -10,6 +10,10 @@ auto Application::font() -> Font {
|
||||||
return state.font;
|
return state.font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Application::locale() -> Locale& {
|
||||||
|
return state.locale;
|
||||||
|
}
|
||||||
|
|
||||||
auto Application::modal() -> bool {
|
auto Application::modal() -> bool {
|
||||||
return state.modal > 0;
|
return state.modal > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <nall/directory.hpp>
|
#include <nall/directory.hpp>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
#include <nall/image.hpp>
|
#include <nall/image.hpp>
|
||||||
|
#include <nall/locale.hpp>
|
||||||
#include <nall/maybe.hpp>
|
#include <nall/maybe.hpp>
|
||||||
#include <nall/path.hpp>
|
#include <nall/path.hpp>
|
||||||
#include <nall/range.hpp>
|
#include <nall/range.hpp>
|
||||||
|
@ -16,6 +17,7 @@
|
||||||
|
|
||||||
using nall::function;
|
using nall::function;
|
||||||
using nall::image;
|
using nall::image;
|
||||||
|
using nall::Locale;
|
||||||
using nall::maybe;
|
using nall::maybe;
|
||||||
using nall::nothing;
|
using nall::nothing;
|
||||||
using nall::set;
|
using nall::set;
|
||||||
|
@ -373,6 +375,7 @@ struct Application {
|
||||||
|
|
||||||
static auto doMain() -> void;
|
static auto doMain() -> void;
|
||||||
static auto font() -> Font;
|
static auto font() -> Font;
|
||||||
|
static auto locale() -> Locale&;
|
||||||
static auto modal() -> bool;
|
static auto modal() -> bool;
|
||||||
static auto name() -> string;
|
static auto name() -> string;
|
||||||
static auto onMain(const function<void ()>& callback = {}) -> void;
|
static auto onMain(const function<void ()>& callback = {}) -> void;
|
||||||
|
@ -405,9 +408,14 @@ struct Application {
|
||||||
static auto onQuit(const function<void ()>& callback = {}) -> void;
|
static auto onQuit(const function<void ()>& callback = {}) -> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Namespace : Locale::Namespace {
|
||||||
|
Namespace(const string& value) : Locale::Namespace(Application::locale(), value) {}
|
||||||
|
};
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
struct State {
|
struct State {
|
||||||
Font font;
|
Font font;
|
||||||
|
Locale locale;
|
||||||
int modal = 0;
|
int modal = 0;
|
||||||
string name;
|
string name;
|
||||||
function<void ()> onMain;
|
function<void ()> onMain;
|
||||||
|
|
|
@ -3,16 +3,50 @@
|
||||||
//shared functionality used for pObject on all platforms
|
//shared functionality used for pObject on all platforms
|
||||||
|
|
||||||
struct mLock {
|
struct mLock {
|
||||||
auto locked() const -> bool { return locks || Application::state.quit; }
|
|
||||||
auto lock() -> void { ++locks; }
|
|
||||||
auto unlock() -> void { --locks; }
|
|
||||||
|
|
||||||
struct Handle {
|
struct Handle {
|
||||||
Handle(const mLock& self) : self(self) { ++self.locks; }
|
Handle(const mLock* self) : self(self) {
|
||||||
~Handle() { --self.locks; }
|
if(self) {
|
||||||
const mLock& self;
|
++self->locks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Handle() {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto release() -> bool {
|
||||||
|
if(self) {
|
||||||
|
--self->locks;
|
||||||
|
self = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mLock* self = nullptr;
|
||||||
};
|
};
|
||||||
auto acquire() const -> Handle { return {*this}; }
|
|
||||||
|
auto acquired() const -> bool {
|
||||||
|
return locks || Application::state.quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto acquire() const -> Handle {
|
||||||
|
return {this};
|
||||||
|
}
|
||||||
|
|
||||||
|
//deprecated C-style manual functions
|
||||||
|
//prefer RAII acquire() functionality instead in newly written code
|
||||||
|
auto locked() const -> bool {
|
||||||
|
return acquired();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock() -> void {
|
||||||
|
++locks;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto unlock() -> void {
|
||||||
|
--locks;
|
||||||
|
}
|
||||||
|
|
||||||
mutable int locks = 0;
|
mutable int locks = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#if defined(Hiro_BrowserDialog)
|
#if defined(Hiro_BrowserDialog)
|
||||||
|
|
||||||
struct BrowserDialogWindow {
|
struct BrowserDialogWindow {
|
||||||
|
Application::Namespace tr{"BrowserDialog"};
|
||||||
|
|
||||||
BrowserDialogWindow(BrowserDialog::State& state) : state(state) {}
|
BrowserDialogWindow(BrowserDialog::State& state) : state(state) {}
|
||||||
auto accept() -> void;
|
auto accept() -> void;
|
||||||
auto activate() -> void;
|
auto activate() -> void;
|
||||||
|
@ -171,10 +173,10 @@ auto BrowserDialogWindow::run() -> BrowserDialog::Response {
|
||||||
fileName.setBackgroundColor(acceptButton.enabled() ? Color{} : Color{255, 224, 224});
|
fileName.setBackgroundColor(acceptButton.enabled() ? Color{} : Color{255, 224, 224});
|
||||||
});
|
});
|
||||||
acceptButton.onActivate([&] { accept(); });
|
acceptButton.onActivate([&] { accept(); });
|
||||||
if(state.action.beginsWith("open")) acceptButton.setText("Open");
|
if(state.action.beginsWith("open")) acceptButton.setText(tr("Open"));
|
||||||
if(state.action.beginsWith("save")) acceptButton.setText("Save");
|
if(state.action.beginsWith("save")) acceptButton.setText(tr("Save"));
|
||||||
if(state.action.beginsWith("select")) acceptButton.setText("Select");
|
if(state.action.beginsWith("select")) acceptButton.setText(tr("Select"));
|
||||||
cancelButton.setText("Cancel").onActivate([&] { window.setModal(false); });
|
cancelButton.setText(tr("Cancel")).onActivate([&] { window.setModal(false); });
|
||||||
|
|
||||||
if(!state.filters) state.filters.append("All|*");
|
if(!state.filters) state.filters.append("All|*");
|
||||||
for(auto& filter : state.filters) {
|
for(auto& filter : state.filters) {
|
||||||
|
|
|
@ -129,7 +129,7 @@ auto mFixedLayoutCell::setVisible(bool visible) -> type& {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mFixedLayoutCell::sizable() const -> Sizable {
|
auto mFixedLayoutCell::sizable() const -> Sizable {
|
||||||
return state.sizable;
|
return state.sizable ? state.sizable : Sizable();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mFixedLayoutCell::synchronize() -> type& {
|
auto mFixedLayoutCell::synchronize() -> type& {
|
||||||
|
|
|
@ -99,8 +99,6 @@ auto mHorizontalLayout::setFont(const Font& font) -> type& {
|
||||||
|
|
||||||
auto mHorizontalLayout::setGeometry(Geometry geometry) -> type& {
|
auto mHorizontalLayout::setGeometry(Geometry geometry) -> type& {
|
||||||
mSizable::setGeometry(geometry);
|
mSizable::setGeometry(geometry);
|
||||||
auto window = parentWindow(true);
|
|
||||||
if(!window || !window->visible()) return *this;
|
|
||||||
|
|
||||||
geometry.setX(geometry.x() + padding().x());
|
geometry.setX(geometry.x() + padding().x());
|
||||||
geometry.setY(geometry.y() + padding().y());
|
geometry.setY(geometry.y() + padding().y());
|
||||||
|
@ -259,7 +257,7 @@ auto mHorizontalLayoutCell::setVisible(bool visible) -> type& {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mHorizontalLayoutCell::sizable() const -> Sizable {
|
auto mHorizontalLayoutCell::sizable() const -> Sizable {
|
||||||
return state.sizable;
|
return state.sizable ? state.sizable : Sizable();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mHorizontalLayoutCell::size() const -> Size {
|
auto mHorizontalLayoutCell::size() const -> Size {
|
||||||
|
|
|
@ -44,6 +44,8 @@ auto MessageDialog::warning(const string_vector& buttons) -> string {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MessageDialog::_run() -> string {
|
auto MessageDialog::_run() -> string {
|
||||||
|
Application::Namespace tr{"MessageDialog"};
|
||||||
|
|
||||||
Window window;
|
Window window;
|
||||||
VerticalLayout layout{&window};
|
VerticalLayout layout{&window};
|
||||||
HorizontalLayout messageLayout{&layout, Size{~0, 0}, 5};
|
HorizontalLayout messageLayout{&layout, Size{~0, 0}, 5};
|
||||||
|
@ -57,14 +59,17 @@ auto MessageDialog::_run() -> string {
|
||||||
messageText.setText(state.text);
|
messageText.setText(state.text);
|
||||||
for(auto n : range(state.buttons.size())) {
|
for(auto n : range(state.buttons.size())) {
|
||||||
Button button{&controlLayout, Size{80, 0}, 5};
|
Button button{&controlLayout, Size{80, 0}, 5};
|
||||||
button.onActivate([&, n] { state.response = state.buttons[n]; window.setModal(false); });
|
button.onActivate([&, n] {
|
||||||
button.setText(state.buttons[n]);
|
state.response = state.buttons[n];
|
||||||
|
window.setModal(false);
|
||||||
|
});
|
||||||
|
button.setText(tr(state.buttons[n]));
|
||||||
button.setFocused(); //the last button will have effective focus
|
button.setFocused(); //the last button will have effective focus
|
||||||
}
|
}
|
||||||
|
|
||||||
signed widthMessage = 5 + 16 + 5 + Font().size(state.text).width() + 5;
|
int widthMessage = 5 + 16 + 5 + Font().size(state.text).width() + 5;
|
||||||
signed widthButtons = 5 + state.buttons.size() * 85;
|
int widthButtons = 5 + state.buttons.size() * 85;
|
||||||
signed width = max(320, widthMessage, widthButtons);
|
int width = max(320, widthMessage, widthButtons);
|
||||||
|
|
||||||
window.onClose([&] { window.setModal(false); });
|
window.onClose([&] { window.setModal(false); });
|
||||||
window.setTitle(state.title);
|
window.setTitle(state.title);
|
||||||
|
|
|
@ -134,8 +134,6 @@ auto mTableLayout::setFont(const Font& font) -> type& {
|
||||||
|
|
||||||
auto mTableLayout::setGeometry(Geometry geometry) -> type& {
|
auto mTableLayout::setGeometry(Geometry geometry) -> type& {
|
||||||
mSizable::setGeometry(geometry);
|
mSizable::setGeometry(geometry);
|
||||||
auto window = parentWindow(true);
|
|
||||||
if(!window || !window->visible()) return *this;
|
|
||||||
|
|
||||||
geometry.setX(geometry.x() + padding().x());
|
geometry.setX(geometry.x() + padding().x());
|
||||||
geometry.setY(geometry.y() + padding().y());
|
geometry.setY(geometry.y() + padding().y());
|
||||||
|
@ -394,7 +392,7 @@ auto mTableLayoutCell::setVisible(bool visible) -> type& {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mTableLayoutCell::sizable() const -> Sizable {
|
auto mTableLayoutCell::sizable() const -> Sizable {
|
||||||
return state.sizable;
|
return state.sizable ? state.sizable : Sizable();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mTableLayoutCell::size() const -> Size {
|
auto mTableLayoutCell::size() const -> Size {
|
||||||
|
|
|
@ -109,8 +109,6 @@ auto mVerticalLayout::setFont(const Font& font) -> type& {
|
||||||
|
|
||||||
auto mVerticalLayout::setGeometry(Geometry geometry) -> type& {
|
auto mVerticalLayout::setGeometry(Geometry geometry) -> type& {
|
||||||
mSizable::setGeometry(geometry);
|
mSizable::setGeometry(geometry);
|
||||||
auto window = parentWindow(true);
|
|
||||||
if(!window || !window->visible()) return *this;
|
|
||||||
|
|
||||||
geometry.setX(geometry.x() + padding().x());
|
geometry.setX(geometry.x() + padding().x());
|
||||||
geometry.setY(geometry.y() + padding().y());
|
geometry.setY(geometry.y() + padding().y());
|
||||||
|
@ -269,7 +267,7 @@ auto mVerticalLayoutCell::setVisible(bool visible) -> type& {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mVerticalLayoutCell::sizable() const -> Sizable {
|
auto mVerticalLayoutCell::sizable() const -> Sizable {
|
||||||
return state.sizable;
|
return state.sizable ? state.sizable : Sizable();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mVerticalLayoutCell::size() const -> Size {
|
auto mVerticalLayoutCell::size() const -> Size {
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
namespace hiro {
|
|
||||||
struct pWindow;
|
|
||||||
struct pMenu;
|
|
||||||
struct pLayout;
|
|
||||||
struct pWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Declare(Name, Base) \
|
#define Declare(Name, Base) \
|
||||||
p##Name(m##Name& reference) : p##Base(reference) {} \
|
p##Name(m##Name& reference) : p##Base(reference) {} \
|
||||||
auto self() const -> m##Name& { return (m##Name&)reference; } \
|
auto self() const -> m##Name& { return (m##Name&)reference; } \
|
||||||
|
|
|
@ -39,6 +39,7 @@ auto pFrame::setFont(const Font& font) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pFrame::setGeometry(Geometry geometry) -> void {
|
auto pFrame::setGeometry(Geometry geometry) -> void {
|
||||||
|
pWidget::setGeometry(geometry);
|
||||||
if(auto& sizable = state().sizable) {
|
if(auto& sizable = state().sizable) {
|
||||||
Size size = pFont::size(self().font(true), state().text);
|
Size size = pFont::size(self().font(true), state().text);
|
||||||
if(!state().text) size.setHeight(10);
|
if(!state().text) size.setHeight(10);
|
||||||
|
|
|
@ -2,6 +2,50 @@
|
||||||
|
|
||||||
namespace hiro {
|
namespace hiro {
|
||||||
|
|
||||||
|
static auto Label_draw(GtkWidget* widget, cairo_t* context, pLabel* p) -> int {
|
||||||
|
auto color = p->state().backgroundColor;
|
||||||
|
if(auto window = p->self().parentWindow(true)) {
|
||||||
|
if(!color) color = window->backgroundColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(color) {
|
||||||
|
double red = (double)color.red() / 255.0;
|
||||||
|
double green = (double)color.green() / 255.0;
|
||||||
|
double blue = (double)color.blue() / 255.0;
|
||||||
|
double alpha = (double)color.alpha() / 255.0;
|
||||||
|
|
||||||
|
if(gdk_screen_is_composited(gdk_screen_get_default())
|
||||||
|
&& gdk_screen_get_rgba_visual(gdk_screen_get_default())
|
||||||
|
) {
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
#if HIRO_GTK==3
|
||||||
|
auto style = gtk_widget_get_style_context(widget);
|
||||||
|
if(auto tabFrame = p->self().parentTabFrame(true)) {
|
||||||
|
if(auto self = tabFrame->self()) style = gtk_widget_get_style_context(self->gtkWidget);
|
||||||
|
}
|
||||||
|
GtkAllocation allocation;
|
||||||
|
gtk_widget_get_allocation(widget, &allocation);
|
||||||
|
gtk_render_background(style, context, 0, 0, allocation.width, allocation.height);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto Label_expose(GtkWidget* widget, GdkEvent* event, pLabel* p) -> int {
|
||||||
|
cairo_t* context = gdk_cairo_create(gtk_widget_get_window(widget));
|
||||||
|
Label_draw(widget, context, p);
|
||||||
|
cairo_destroy(context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto pLabel::construct() -> void {
|
auto pLabel::construct() -> void {
|
||||||
gtkWidget = gtk_event_box_new();
|
gtkWidget = gtk_event_box_new();
|
||||||
subWidget = gtk_label_new("");
|
subWidget = gtk_label_new("");
|
||||||
|
@ -13,6 +57,12 @@ auto pLabel::construct() -> void {
|
||||||
setForegroundColor(state().foregroundColor);
|
setForegroundColor(state().foregroundColor);
|
||||||
setText(state().text);
|
setText(state().text);
|
||||||
|
|
||||||
|
#if HIRO_GTK==2
|
||||||
|
g_signal_connect(G_OBJECT(subWidget), "expose-event", G_CALLBACK(Label_expose), (gpointer)this);
|
||||||
|
#elif HIRO_GTK==3
|
||||||
|
g_signal_connect(G_OBJECT(subWidget), "draw", G_CALLBACK(Label_draw), (gpointer)this);
|
||||||
|
#endif
|
||||||
|
|
||||||
pWidget::construct();
|
pWidget::construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,9 +86,9 @@ auto pLabel::setAlignment(Alignment alignment) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLabel::setBackgroundColor(Color color) -> void {
|
auto pLabel::setBackgroundColor(Color color) -> void {
|
||||||
if(!color) color = self().parentWindow(true)->backgroundColor();
|
//GTK3 will paint the wrong background color when a label is inside of a TabFrame
|
||||||
auto gdkColor = CreateColor(color);
|
//this is caused by the GtkEventBox wrapper that is required to paint custom backgrounds
|
||||||
gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
//handle background painting via "draw" or "expose-event" signals instead
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLabel::setForegroundColor(Color color) -> void {
|
auto pLabel::setForegroundColor(Color color) -> void {
|
||||||
|
|
|
@ -157,8 +157,7 @@ auto pTabFrame::setFont(const Font& font) -> void {
|
||||||
|
|
||||||
auto pTabFrame::setGeometry(Geometry geometry) -> void {
|
auto pTabFrame::setGeometry(Geometry geometry) -> void {
|
||||||
pWidget::setGeometry(geometry);
|
pWidget::setGeometry(geometry);
|
||||||
|
geometry.setPosition();
|
||||||
geometry.setPosition(0, 0);
|
|
||||||
if(state().navigation == Navigation::Top || state().navigation == Navigation::Bottom) {
|
if(state().navigation == Navigation::Top || state().navigation == Navigation::Bottom) {
|
||||||
geometry.setWidth(geometry.width() - 6);
|
geometry.setWidth(geometry.width() - 6);
|
||||||
geometry.setHeight(geometry.height() - (15 + _tabHeight()));
|
geometry.setHeight(geometry.height() - (15 + _tabHeight()));
|
||||||
|
|
|
@ -66,7 +66,7 @@ GtkSelectionData* data, unsigned type, unsigned timestamp, pWindow* p) -> void {
|
||||||
static auto Window_getPreferredWidth(GtkWidget* widget, int* minimalWidth, int* naturalWidth) -> void {
|
static auto Window_getPreferredWidth(GtkWidget* widget, int* minimalWidth, int* naturalWidth) -> void {
|
||||||
if(auto p = (pWindow*)g_object_get_data(G_OBJECT(widget), "hiro::window")) {
|
if(auto p = (pWindow*)g_object_get_data(G_OBJECT(widget), "hiro::window")) {
|
||||||
*minimalWidth = 1;
|
*minimalWidth = 1;
|
||||||
*naturalWidth = 1; //p->state().geometry.width();
|
*naturalWidth = p->state().geometry.width();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ static auto Window_sizeRequest(GtkWidget* widget, GtkRequisition* requisition, p
|
||||||
static auto Window_stateEvent(GtkWidget* widget, GdkEvent* event, pWindow* p) -> void {
|
static auto Window_stateEvent(GtkWidget* widget, GdkEvent* event, pWindow* p) -> void {
|
||||||
p->_synchronizeState();
|
p->_synchronizeState();
|
||||||
|
|
||||||
/*if(event->type == GDK_WINDOW_STATE) {
|
if(event->type == GDK_WINDOW_STATE) {
|
||||||
auto windowStateEvent = (GdkEventWindowState*)event;
|
auto windowStateEvent = (GdkEventWindowState*)event;
|
||||||
if(windowStateEvent->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
|
if(windowStateEvent->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
|
||||||
p->state().maximized = windowStateEvent->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
|
p->state().maximized = windowStateEvent->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
|
||||||
|
@ -122,7 +122,7 @@ static auto Window_stateEvent(GtkWidget* widget, GdkEvent* event, pWindow* p) ->
|
||||||
if(windowStateEvent->changed_mask & GDK_WINDOW_STATE_ICONIFIED) {
|
if(windowStateEvent->changed_mask & GDK_WINDOW_STATE_ICONIFIED) {
|
||||||
p->state().minimized = windowStateEvent->new_window_state & GDK_WINDOW_STATE_ICONIFIED;
|
p->state().minimized = windowStateEvent->new_window_state & GDK_WINDOW_STATE_ICONIFIED;
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::construct() -> void {
|
auto pWindow::construct() -> void {
|
||||||
|
@ -191,7 +191,7 @@ auto pWindow::construct() -> void {
|
||||||
g_signal_connect(G_OBJECT(formContainer), "size-request", G_CALLBACK(Window_sizeRequest), (gpointer)this);
|
g_signal_connect(G_OBJECT(formContainer), "size-request", G_CALLBACK(Window_sizeRequest), (gpointer)this);
|
||||||
#elif HIRO_GTK==3
|
#elif HIRO_GTK==3
|
||||||
auto widgetClass = GTK_WIDGET_GET_CLASS(formContainer);
|
auto widgetClass = GTK_WIDGET_GET_CLASS(formContainer);
|
||||||
widgetClass->get_preferred_width = Window_getPreferredWidth;
|
widgetClass->get_preferred_width = Window_getPreferredWidth;
|
||||||
widgetClass->get_preferred_height = Window_getPreferredHeight;
|
widgetClass->get_preferred_height = Window_getPreferredHeight;
|
||||||
#endif
|
#endif
|
||||||
g_signal_connect(G_OBJECT(widget), "window-state-event", G_CALLBACK(Window_stateEvent), (gpointer)this);
|
g_signal_connect(G_OBJECT(widget), "window-state-event", G_CALLBACK(Window_stateEvent), (gpointer)this);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef HIRO_CPP
|
#ifndef HIRO_CPP
|
||||||
#define HIRO_CPP
|
#define HIRO_CPP
|
||||||
|
|
||||||
#define foreach(T, ...) ([&] { for(auto& $ : T) { __VA_ARGS__; }}())
|
|
||||||
|
|
||||||
#include "components.hpp"
|
#include "components.hpp"
|
||||||
#include "core/core.cpp"
|
#include "core/core.cpp"
|
||||||
#include "extension/extension.cpp"
|
#include "extension/extension.cpp"
|
||||||
|
|
|
@ -23,6 +23,7 @@ auto pMenuRadioItem::construct() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pMenuRadioItem::destruct() -> void {
|
auto pMenuRadioItem::destruct() -> void {
|
||||||
|
if(Application::state.quit) return; //TODO: hack
|
||||||
delete qtMenuRadioItem;
|
delete qtMenuRadioItem;
|
||||||
delete qtActionGroup;
|
delete qtActionGroup;
|
||||||
qtMenuRadioItem = nullptr;
|
qtMenuRadioItem = nullptr;
|
||||||
|
@ -47,6 +48,7 @@ auto pMenuRadioItem::setGroup(sGroup group) -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_setState();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pMenuRadioItem::setText(const string& text) -> void {
|
auto pMenuRadioItem::setText(const string& text) -> void {
|
||||||
|
|
|
@ -23,6 +23,7 @@ auto pMenu::construct() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pMenu::destruct() -> void {
|
auto pMenu::destruct() -> void {
|
||||||
|
if(Application::state.quit) return; //TODO: hack
|
||||||
delete qtMenu;
|
delete qtMenu;
|
||||||
qtMenu = nullptr;
|
qtMenu = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,10 @@
|
||||||
#include "widget/check-label.cpp"
|
#include "widget/check-label.cpp"
|
||||||
#include "widget/combo-button.cpp"
|
#include "widget/combo-button.cpp"
|
||||||
#include "widget/combo-button-item.cpp"
|
#include "widget/combo-button-item.cpp"
|
||||||
#include "widget/console.cpp"
|
|
||||||
#include "widget/frame.cpp"
|
#include "widget/frame.cpp"
|
||||||
#include "widget/hex-edit.cpp"
|
#include "widget/hex-edit.cpp"
|
||||||
#include "widget/horizontal-scroll-bar.cpp"
|
#include "widget/horizontal-scroll-bar.cpp"
|
||||||
#include "widget/horizontal-slider.cpp"
|
#include "widget/horizontal-slider.cpp"
|
||||||
#include "widget/icon-view.cpp"
|
|
||||||
#include "widget/label.cpp"
|
#include "widget/label.cpp"
|
||||||
#include "widget/line-edit.cpp"
|
#include "widget/line-edit.cpp"
|
||||||
#include "widget/progress-bar.cpp"
|
#include "widget/progress-bar.cpp"
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include "settings.hpp"
|
|
||||||
|
|
||||||
#define Declare(Name, Base) \
|
#define Declare(Name, Base) \
|
||||||
p##Name(m##Name& reference) : p##Base(reference) {} \
|
p##Name(m##Name& reference) : p##Base(reference) {} \
|
||||||
auto self() const -> m##Name& { return (m##Name&)reference; } \
|
auto self() const -> m##Name& { return (m##Name&)reference; } \
|
||||||
|
@ -8,6 +6,7 @@
|
||||||
auto destruct() -> void override; \
|
auto destruct() -> void override; \
|
||||||
|
|
||||||
#include "application.hpp"
|
#include "application.hpp"
|
||||||
|
#include "settings.hpp"
|
||||||
#include "font.hpp"
|
#include "font.hpp"
|
||||||
#include "desktop.hpp"
|
#include "desktop.hpp"
|
||||||
#include "monitor.hpp"
|
#include "monitor.hpp"
|
||||||
|
|
|
@ -15,6 +15,10 @@ static auto CreateBrush(Color color) -> QBrush {
|
||||||
return color ? QColor(color.red(), color.green(), color.blue()) : QBrush();
|
return color ? QColor(color.red(), color.green(), color.blue()) : QBrush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static auto CreateColor(Color color, QColor fallback = {}) -> QColor {
|
||||||
|
return color ? QColor(color.red(), color.green(), color.blue()) : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
static auto CreateIcon(const image& icon, bool scale = false) -> QIcon {
|
static auto CreateIcon(const image& icon, bool scale = false) -> QIcon {
|
||||||
if(!icon) return QIcon();
|
if(!icon) return QIcon();
|
||||||
auto qtBuffer = icon;
|
auto qtBuffer = icon;
|
||||||
|
|
|
@ -18,7 +18,7 @@ auto pCanvas::destruct() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pCanvas::minimumSize() const -> Size {
|
auto pCanvas::minimumSize() const -> Size {
|
||||||
if(auto& icon = state().icon) return {(int)icon.width(), (int)icon.height()};
|
if(auto& icon = state().icon) return {icon.width(), icon.height()};
|
||||||
return {0, 0};
|
return {0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ auto pComboButton::construct() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pComboButton::destruct() -> void {
|
auto pComboButton::destruct() -> void {
|
||||||
|
if(Application::state.quit) return; //TODO: hack
|
||||||
delete qtComboButton;
|
delete qtComboButton;
|
||||||
qtWidget = qtComboButton = nullptr;
|
qtWidget = qtComboButton = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
#if defined(Hiro_Console)
|
|
||||||
|
|
||||||
namespace hiro {
|
|
||||||
|
|
||||||
void pConsole::print(string text) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::reset() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::setBackgroundColor(Color color) {
|
|
||||||
QPalette palette = qtConsole->palette();
|
|
||||||
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
|
|
||||||
qtConsole->setPalette(palette);
|
|
||||||
qtConsole->setAutoFillBackground(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::setForegroundColor(Color color) {
|
|
||||||
QPalette palette = qtConsole->palette();
|
|
||||||
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
|
|
||||||
qtConsole->setPalette(palette);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::setPrompt(string prompt) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::constructor() {
|
|
||||||
qtWidget = qtConsole = new QtConsole(*this);
|
|
||||||
|
|
||||||
pWidget::synchronizeState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::destructor() {
|
|
||||||
delete qtConsole;
|
|
||||||
qtWidget = qtConsole = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::orphan() {
|
|
||||||
destructor();
|
|
||||||
constructor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::keyPressEvent(QKeyEvent* event) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::QtConsole::keyPressEvent(QKeyEvent* event) {
|
|
||||||
self.keyPressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pConsole::QtConsole::keyPressEventAcknowledge(QKeyEvent* event) {
|
|
||||||
QTextEdit::keyPressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -22,6 +22,8 @@ auto pHexEdit::construct() -> void {
|
||||||
qtScrollBar->connect(qtScrollBar, SIGNAL(actionTriggered(int)), SLOT(onScroll()));
|
qtScrollBar->connect(qtScrollBar, SIGNAL(actionTriggered(int)), SLOT(onScroll()));
|
||||||
|
|
||||||
pWidget::construct();
|
pWidget::construct();
|
||||||
|
setBackgroundColor(state().backgroundColor);
|
||||||
|
setForegroundColor(state().foregroundColor);
|
||||||
_setState();
|
_setState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +41,12 @@ auto pHexEdit::setAddress(unsigned address) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pHexEdit::setBackgroundColor(Color color) -> void {
|
auto pHexEdit::setBackgroundColor(Color color) -> void {
|
||||||
_setState();
|
static auto defaultColor = qtHexEdit->palette().color(QPalette::Base);
|
||||||
|
|
||||||
|
auto palette = qtHexEdit->palette();
|
||||||
|
palette.setColor(QPalette::Base, CreateColor(color, defaultColor));
|
||||||
|
qtHexEdit->setPalette(palette);
|
||||||
|
qtHexEdit->setAutoFillBackground((bool)color);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pHexEdit::setColumns(unsigned columns) -> void {
|
auto pHexEdit::setColumns(unsigned columns) -> void {
|
||||||
|
@ -47,7 +54,11 @@ auto pHexEdit::setColumns(unsigned columns) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pHexEdit::setForegroundColor(Color color) -> void {
|
auto pHexEdit::setForegroundColor(Color color) -> void {
|
||||||
_setState();
|
static auto defaultColor = qtHexEdit->palette().color(QPalette::Text);
|
||||||
|
|
||||||
|
auto palette = qtHexEdit->palette();
|
||||||
|
palette.setColor(QPalette::Text, color ? CreateColor(color) : defaultColor);
|
||||||
|
qtHexEdit->setPalette(palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pHexEdit::setLength(unsigned length) -> void {
|
auto pHexEdit::setLength(unsigned length) -> void {
|
||||||
|
@ -242,29 +253,13 @@ auto pHexEdit::_scrollTo(signed position) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pHexEdit::_setState() -> void {
|
auto pHexEdit::_setState() -> void {
|
||||||
lock();
|
auto lock = acquire();
|
||||||
if(auto color = state().backgroundColor) {
|
|
||||||
QPalette palette = qtHexEdit->palette();
|
|
||||||
palette.setColor(QPalette::Base, QColor(color.red(), color.green(), color.blue()));
|
|
||||||
qtHexEdit->setPalette(palette);
|
|
||||||
qtHexEdit->setAutoFillBackground(true);
|
|
||||||
} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
if(auto color = state().foregroundColor) {
|
|
||||||
QPalette palette = qtHexEdit->palette();
|
|
||||||
palette.setColor(QPalette::Text, QColor(color.red(), color.green(), color.blue()));
|
|
||||||
qtHexEdit->setPalette(palette);
|
|
||||||
} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
//add one if last row is not equal to column length (eg only part of the row is present)
|
//add one if last row is not equal to column length (eg only part of the row is present)
|
||||||
bool indivisible = state().columns == 0 || (state().length % state().columns) != 0;
|
bool indivisible = state().columns == 0 || (state().length % state().columns) != 0;
|
||||||
qtScrollBar->setRange(0, state().length / state().columns + indivisible - state().rows);
|
qtScrollBar->setRange(0, state().length / state().columns + indivisible - state().rows);
|
||||||
qtScrollBar->setSliderPosition(state().address / state().columns);
|
qtScrollBar->setSliderPosition(state().address / state().columns);
|
||||||
qtScrollBar->setPageStep(state().rows);
|
qtScrollBar->setPageStep(state().rows);
|
||||||
update();
|
update();
|
||||||
unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto QtHexEdit::keyPressEvent(QKeyEvent* event) -> void {
|
auto QtHexEdit::keyPressEvent(QKeyEvent* event) -> void {
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
#if defined(Hiro_IconView)
|
|
||||||
|
|
||||||
namespace hiro {
|
|
||||||
|
|
||||||
void pIconView::append() {
|
|
||||||
lock();
|
|
||||||
auto item = new QListWidgetItem(qtIconView);
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::remove(unsigned selection) {
|
|
||||||
lock();
|
|
||||||
if(auto item = qtIconView->item(selection)) {
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::reset() {
|
|
||||||
lock();
|
|
||||||
qtIconView->clear();
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setBackgroundColor(Color color) {
|
|
||||||
QPalette palette = qtIconView->palette();
|
|
||||||
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
|
|
||||||
qtIconView->setPalette(palette);
|
|
||||||
qtIconView->setAutoFillBackground(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setFlow(Orientation flow) {
|
|
||||||
qtIconView->setFlow(flow == Orientation::Horizontal ? QListView::LeftToRight : QListView::TopToBottom);
|
|
||||||
qtIconView->resize(qtIconView->size()); //adjust visibility of scroll bars
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setForegroundColor(Color color) {
|
|
||||||
QPalette palette = qtIconView->palette();
|
|
||||||
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
|
|
||||||
qtIconView->setPalette(palette);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setImage(unsigned selection, const image& image) {
|
|
||||||
if(auto item = qtIconView->item(selection)) {
|
|
||||||
item->setIcon(CreateIcon(image));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setOrientation(Orientation orientation) {
|
|
||||||
qtIconView->setViewMode(orientation == Orientation::Horizontal ? QListView::ListMode : QListView::IconMode);
|
|
||||||
qtIconView->setWrapping(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setSelected(unsigned selection, bool selected) {
|
|
||||||
lock();
|
|
||||||
if(auto item = qtIconView->item(selection)) {
|
|
||||||
item->setSelected(selected);
|
|
||||||
}
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setSelected(const vector<unsigned>& selections) {
|
|
||||||
lock();
|
|
||||||
qtIconView->clearSelection();
|
|
||||||
for(auto& selection : selections) {
|
|
||||||
if(auto item = qtIconView->item(selection)) {
|
|
||||||
item->setSelected(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setSelectedAll() {
|
|
||||||
lock();
|
|
||||||
qtIconView->selectAll();
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setSelectedNone() {
|
|
||||||
lock();
|
|
||||||
qtIconView->clearSelection();
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setSingleSelection(bool singleSelection) {
|
|
||||||
qtIconView->setSelectionMode(singleSelection ? QAbstractItemView::SingleSelection : QAbstractItemView::ExtendedSelection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::setText(unsigned selection, const string& text) {
|
|
||||||
if(auto item = qtIconView->item(selection)) {
|
|
||||||
item->setText(QString::fromUtf8(text));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::constructor() {
|
|
||||||
qtWidget = qtIconView = new QtListWidget;
|
|
||||||
qtIconView->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
qtIconView->setMovement(QListView::Static);
|
|
||||||
qtIconView->setResizeMode(QListView::Adjust);
|
|
||||||
qtIconView->setSelectionRectVisible(true);
|
|
||||||
qtIconView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
||||||
qtIconView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
||||||
|
|
||||||
connect(qtIconView, SIGNAL(itemActivated(QListWidgetItem*)), SLOT(onActivate()));
|
|
||||||
connect(qtIconView, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
|
|
||||||
connect(qtIconView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onContext()));
|
|
||||||
|
|
||||||
setFlow(iconView.state.flow);
|
|
||||||
setOrientation(iconView.state.orientation);
|
|
||||||
setSingleSelection(iconView.state.singleSelection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::destructor() {
|
|
||||||
delete qtIconView;
|
|
||||||
qtWidget = qtIconView = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::orphan() {
|
|
||||||
destructor();
|
|
||||||
constructor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::onActivate() {
|
|
||||||
if(!locked() && iconView.onActivate) iconView.onActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::onChange() {
|
|
||||||
for(auto& selected : iconView.state.selected) selected = false;
|
|
||||||
for(unsigned n = 0; n < qtIconView->count(); n++) {
|
|
||||||
if(auto item = qtIconView->item(n)) {
|
|
||||||
if(item->isSelected()) iconView.state.selected[n] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!locked() && iconView.onChange) iconView.onChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::onContext() {
|
|
||||||
if(!locked() && iconView.onContext) iconView.onContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pIconView::QtListWidget::resizeEvent(QResizeEvent* event) {
|
|
||||||
//Qt::ScrollBarAsNeeded results in the scroll bar area being reserved from the icon viewport even when scroll bar is hidden
|
|
||||||
//this creates the appearance of an invisible gap that wastes precious screen space
|
|
||||||
//below code simulates a Qt::ScrollBarAsNeeded which uses the extra space when the scroll bar is hidden
|
|
||||||
setHorizontalScrollBarPolicy(horizontalScrollBar()->maximum() > horizontalScrollBar()->minimum() ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAlwaysOff);
|
|
||||||
setVerticalScrollBarPolicy(verticalScrollBar()->maximum() > verticalScrollBar()->minimum() ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAlwaysOff);
|
|
||||||
return QListWidget::resizeEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -28,27 +28,20 @@ auto pLabel::setAlignment(Alignment alignment) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLabel::setBackgroundColor(Color color) -> void {
|
auto pLabel::setBackgroundColor(Color color) -> void {
|
||||||
if(!color) color = self().parentWindow(true)->backgroundColor();
|
static auto defaultColor = qtLabel->palette().color(QPalette::Base);
|
||||||
if(color) {
|
|
||||||
QPalette palette = qtLabel->palette();
|
auto palette = qtLabel->palette();
|
||||||
palette.setColor(QPalette::Base, QColor(color.red(), color.green(), color.blue()));
|
palette.setColor(QPalette::Base, CreateColor(color, defaultColor));
|
||||||
qtLabel->setBackgroundRole(QPalette::Base);
|
qtLabel->setPalette(palette);
|
||||||
qtLabel->setPalette(palette);
|
qtLabel->setAutoFillBackground((bool)color);
|
||||||
qtLabel->setAutoFillBackground(true);
|
|
||||||
} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLabel::setForegroundColor(Color color) -> void {
|
auto pLabel::setForegroundColor(Color color) -> void {
|
||||||
if(color) {
|
static auto defaultColor = qtLabel->palette().color(QPalette::Text);
|
||||||
QPalette palette = qtLabel->palette();
|
|
||||||
palette.setColor(QPalette::Text, QColor(color.red(), color.green(), color.blue()));
|
auto palette = qtLabel->palette();
|
||||||
qtLabel->setForegroundRole(QPalette::Text);
|
palette.setColor(QPalette::Text, CreateColor(color, defaultColor));
|
||||||
qtLabel->setPalette(palette);
|
qtLabel->setPalette(palette);
|
||||||
} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLabel::setText(const string& text) -> void {
|
auto pLabel::setText(const string& text) -> void {
|
||||||
|
|
|
@ -8,7 +8,10 @@ auto pLineEdit::construct() -> void {
|
||||||
qtLineEdit->connect(qtLineEdit, SIGNAL(textEdited(const QString&)), SLOT(onChange()));
|
qtLineEdit->connect(qtLineEdit, SIGNAL(textEdited(const QString&)), SLOT(onChange()));
|
||||||
|
|
||||||
pWidget::construct();
|
pWidget::construct();
|
||||||
_setState();
|
setBackgroundColor(state().backgroundColor);
|
||||||
|
setEditable(state().editable);
|
||||||
|
setForegroundColor(state().foregroundColor);
|
||||||
|
setText(state().text);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLineEdit::destruct() -> void {
|
auto pLineEdit::destruct() -> void {
|
||||||
|
@ -22,38 +25,27 @@ auto pLineEdit::minimumSize() const -> Size {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLineEdit::setBackgroundColor(Color color) -> void {
|
auto pLineEdit::setBackgroundColor(Color color) -> void {
|
||||||
_setState();
|
static auto defaultColor = qtLineEdit->palette().color(QPalette::Base);
|
||||||
|
|
||||||
|
auto palette = qtLineEdit->palette();
|
||||||
|
palette.setColor(QPalette::Base, CreateColor(color, defaultColor));
|
||||||
|
qtLineEdit->setPalette(palette);
|
||||||
|
qtLineEdit->setAutoFillBackground((bool)color);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLineEdit::setEditable(bool editable) -> void {
|
auto pLineEdit::setEditable(bool editable) -> void {
|
||||||
_setState();
|
qtLineEdit->setReadOnly(!state().editable);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLineEdit::setForegroundColor(Color color) -> void {
|
auto pLineEdit::setForegroundColor(Color color) -> void {
|
||||||
_setState();
|
static auto defaultColor = qtLineEdit->palette().color(QPalette::Text);
|
||||||
|
|
||||||
|
auto palette = qtLineEdit->palette();
|
||||||
|
palette.setColor(QPalette::Text, CreateColor(color, defaultColor));
|
||||||
|
qtLineEdit->setPalette(palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pLineEdit::setText(const string& text) -> void {
|
auto pLineEdit::setText(const string& text) -> void {
|
||||||
_setState();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pLineEdit::_setState() -> void {
|
|
||||||
if(auto color = state().backgroundColor) {
|
|
||||||
QPalette palette = qtLineEdit->palette();
|
|
||||||
palette.setColor(QPalette::Base, QColor(color.red(), color.green(), color.blue()));
|
|
||||||
qtLineEdit->setPalette(palette);
|
|
||||||
qtLineEdit->setAutoFillBackground(true);
|
|
||||||
} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
qtLineEdit->setReadOnly(!state().editable);
|
|
||||||
if(auto color = state().foregroundColor) {
|
|
||||||
QPalette palette = qtLineEdit->palette();
|
|
||||||
palette.setColor(QPalette::Text, QColor(color.red(), color.green(), color.blue()));
|
|
||||||
qtLineEdit->setPalette(palette);
|
|
||||||
} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
qtLineEdit->setText(QString::fromUtf8(state().text));
|
qtLineEdit->setText(QString::fromUtf8(state().text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ struct pLineEdit : pWidget {
|
||||||
auto setForegroundColor(Color color) -> void;
|
auto setForegroundColor(Color color) -> void;
|
||||||
auto setText(const string& text) -> void;
|
auto setText(const string& text) -> void;
|
||||||
|
|
||||||
auto _setState() -> void;
|
|
||||||
|
|
||||||
QtLineEdit* qtLineEdit = nullptr;
|
QtLineEdit* qtLineEdit = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ auto pTabFrameItem::setClosable(bool closable) -> void {
|
||||||
auto pTabFrameItem::setGeometry(Geometry geometry) -> void {
|
auto pTabFrameItem::setGeometry(Geometry geometry) -> void {
|
||||||
if(auto& sizable = state().sizable) {
|
if(auto& sizable = state().sizable) {
|
||||||
auto offset = qtTabFrameItem->geometry();
|
auto offset = qtTabFrameItem->geometry();
|
||||||
geometry.setPosition({0, 0});
|
geometry.setPosition();
|
||||||
geometry.setWidth(geometry.width() - (geometry.width() - offset.width()));
|
geometry.setWidth(geometry.width() - (geometry.width() - offset.width()));
|
||||||
geometry.setHeight(geometry.height() - (geometry.height() - offset.height()));
|
geometry.setHeight(geometry.height() - (geometry.height() - offset.height()));
|
||||||
sizable->setGeometry(geometry);
|
sizable->setGeometry(geometry);
|
||||||
|
@ -72,7 +72,7 @@ auto pTabFrameItem::_setState() -> void {
|
||||||
geometry.setWidth(geometry.width() - (geometry.width() - offset.width()));
|
geometry.setWidth(geometry.width() - (geometry.width() - offset.width()));
|
||||||
geometry.setHeight(geometry.height() - (geometry.height() - offset.height()));
|
geometry.setHeight(geometry.height() - (geometry.height() - offset.height()));
|
||||||
sizable->setGeometry(geometry);
|
sizable->setGeometry(geometry);
|
||||||
sizable->setVisible(sizable->visible(true));
|
sizable->setVisible(sizable->visible());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ auto pTabFrame::construct() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTabFrame::destruct() -> void {
|
auto pTabFrame::destruct() -> void {
|
||||||
|
if(Application::state.quit) return; //TODO: hack
|
||||||
delete qtTabFrame;
|
delete qtTabFrame;
|
||||||
qtWidget = qtTabFrame = nullptr;
|
qtWidget = qtTabFrame = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ auto pTableViewItem::_parent() -> maybe<pTableView&> {
|
||||||
|
|
||||||
auto pTableViewItem::_setState() -> void {
|
auto pTableViewItem::_setState() -> void {
|
||||||
if(auto parent = _parent()) {
|
if(auto parent = _parent()) {
|
||||||
parent->lock();
|
auto lock = parent->acquire();
|
||||||
qtItem->setSelected(state().selected);
|
qtItem->setSelected(state().selected);
|
||||||
if(state().selected) {
|
if(state().selected) {
|
||||||
parent->qtTableView->setCurrentItem(qtItem);
|
parent->qtTableView->setCurrentItem(qtItem);
|
||||||
|
|
|
@ -32,6 +32,7 @@ auto pTableView::construct() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTableView::destruct() -> void {
|
auto pTableView::destruct() -> void {
|
||||||
|
if(Application::state.quit) return; //TODO: hack
|
||||||
delete qtTableViewDelegate;
|
delete qtTableViewDelegate;
|
||||||
delete qtTableView;
|
delete qtTableView;
|
||||||
qtWidget = qtTableView = nullptr;
|
qtWidget = qtTableView = nullptr;
|
||||||
|
@ -99,15 +100,13 @@ auto pTableView::setAlignment(Alignment alignment) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTableView::setBackgroundColor(Color color) -> void {
|
auto pTableView::setBackgroundColor(Color color) -> void {
|
||||||
if(color) {
|
//note: QPalette::AlternateBase can be used for alternating row colors
|
||||||
QPalette palette = qtTableView->palette();
|
static auto defaultColor = qtTableView->palette().color(QPalette::Base);
|
||||||
palette.setColor(QPalette::Base, QColor(color.red(), color.green(), color.blue()));
|
|
||||||
palette.setColor(QPalette::AlternateBase, QColor(max(0, (signed)color.red() - 17), max(0, (signed)color.green() - 17), max(0, (signed)color.blue() - 17)));
|
auto palette = qtTableView->palette();
|
||||||
qtTableView->setPalette(palette);
|
palette.setColor(QPalette::Base, CreateColor(color, defaultColor));
|
||||||
qtTableView->setAutoFillBackground(true);
|
qtTableView->setPalette(palette);
|
||||||
} else {
|
qtTableView->setAutoFillBackground((bool)color);
|
||||||
//todo: set default color
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTableView::setBatchable(bool batchable) -> void {
|
auto pTableView::setBatchable(bool batchable) -> void {
|
||||||
|
@ -121,13 +120,12 @@ auto pTableView::setBordered(bool bordered) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTableView::setForegroundColor(Color color) -> void {
|
auto pTableView::setForegroundColor(Color color) -> void {
|
||||||
if(color) {
|
static auto defaultColor = qtTableView->palette().color(QPalette::Text);
|
||||||
QPalette palette = qtTableView->palette();
|
|
||||||
palette.setColor(QPalette::Text, QColor(color.red(), color.green(), color.blue()));
|
auto palette = qtTableView->palette();
|
||||||
qtTableView->setPalette(palette);
|
palette.setColor(QPalette::Text, CreateColor(color, defaultColor));
|
||||||
} else {
|
qtTableView->setPalette(palette);
|
||||||
//todo: set default color
|
qtTableView->setAutoFillBackground((bool)color);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//called on resize/show events
|
//called on resize/show events
|
||||||
|
|
|
@ -7,16 +7,24 @@ auto pTextEdit::construct() -> void {
|
||||||
qtTextEdit->connect(qtTextEdit, SIGNAL(textChanged()), SLOT(onChange()));
|
qtTextEdit->connect(qtTextEdit, SIGNAL(textChanged()), SLOT(onChange()));
|
||||||
|
|
||||||
pWidget::construct();
|
pWidget::construct();
|
||||||
|
setBackgroundColor(state().backgroundColor);
|
||||||
|
setForegroundColor(state().foregroundColor);
|
||||||
_setState();
|
_setState();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTextEdit::destruct() -> void {
|
auto pTextEdit::destruct() -> void {
|
||||||
|
if(Application::state.quit) return; //TODO: hack
|
||||||
delete qtTextEdit;
|
delete qtTextEdit;
|
||||||
qtWidget = qtTextEdit = nullptr;
|
qtWidget = qtTextEdit = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTextEdit::setBackgroundColor(Color color) -> void {
|
auto pTextEdit::setBackgroundColor(Color color) -> void {
|
||||||
_setState();
|
static auto defaultColor = qtTextEdit->palette().color(QPalette::Base);
|
||||||
|
|
||||||
|
auto palette = qtTextEdit->palette();
|
||||||
|
palette.setColor(QPalette::Base, CreateColor(color, defaultColor));
|
||||||
|
qtTextEdit->setPalette(palette);
|
||||||
|
qtTextEdit->setAutoFillBackground((bool)color);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTextEdit::setCursor(Cursor cursor) -> void {
|
auto pTextEdit::setCursor(Cursor cursor) -> void {
|
||||||
|
@ -28,7 +36,11 @@ auto pTextEdit::setEditable(bool editable) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTextEdit::setForegroundColor(Color color) -> void {
|
auto pTextEdit::setForegroundColor(Color color) -> void {
|
||||||
_setState();
|
static auto defaultColor = qtTextEdit->palette().color(QPalette::Text);
|
||||||
|
|
||||||
|
auto palette = qtTextEdit->palette();
|
||||||
|
palette.setColor(QPalette::Text, CreateColor(color, defaultColor));
|
||||||
|
qtTextEdit->setPalette(palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTextEdit::setText(const string& text) -> void {
|
auto pTextEdit::setText(const string& text) -> void {
|
||||||
|
@ -44,14 +56,6 @@ auto pTextEdit::text() const -> string {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pTextEdit::_setState() -> void {
|
auto pTextEdit::_setState() -> void {
|
||||||
if(auto color = state().backgroundColor) {
|
|
||||||
QPalette palette = qtTextEdit->palette();
|
|
||||||
palette.setColor(QPalette::Base, QColor(color.red(), color.green(), color.blue()));
|
|
||||||
qtTextEdit->setPalette(palette);
|
|
||||||
qtTextEdit->setAutoFillBackground(true);
|
|
||||||
} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
QTextCursor cursor = qtTextEdit->textCursor();
|
QTextCursor cursor = qtTextEdit->textCursor();
|
||||||
signed lastCharacter = strlen(qtTextEdit->toPlainText().toUtf8().constData());
|
signed lastCharacter = strlen(qtTextEdit->toPlainText().toUtf8().constData());
|
||||||
cursor.setPosition(max(0, min(lastCharacter, state().cursor.offset())));
|
cursor.setPosition(max(0, min(lastCharacter, state().cursor.offset())));
|
||||||
|
@ -61,13 +65,6 @@ auto pTextEdit::_setState() -> void {
|
||||||
? Qt::TextEditorInteraction
|
? Qt::TextEditorInteraction
|
||||||
: Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse
|
: Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse
|
||||||
);
|
);
|
||||||
if(auto color = state().foregroundColor) {
|
|
||||||
QPalette palette = qtTextEdit->palette();
|
|
||||||
palette.setColor(QPalette::Text, QColor(color.red(), color.green(), color.blue()));
|
|
||||||
qtTextEdit->setPalette(palette);
|
|
||||||
} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
qtTextEdit->setWordWrapMode(state().wordWrap ? QTextOption::WordWrap : QTextOption::NoWrap);
|
qtTextEdit->setWordWrapMode(state().wordWrap ? QTextOption::WordWrap : QTextOption::NoWrap);
|
||||||
qtTextEdit->setHorizontalScrollBarPolicy(state().wordWrap ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAlwaysOn);
|
qtTextEdit->setHorizontalScrollBarPolicy(state().wordWrap ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAlwaysOn);
|
||||||
qtTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
qtTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||||
|
|
|
@ -44,6 +44,7 @@ auto pWindow::construct() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::destruct() -> void {
|
auto pWindow::destruct() -> void {
|
||||||
|
if(Application::state.quit) return; //TODO: hack
|
||||||
delete qtStatusBar;
|
delete qtStatusBar;
|
||||||
delete qtContainer;
|
delete qtContainer;
|
||||||
delete qtMenuBar;
|
delete qtMenuBar;
|
||||||
|
@ -90,14 +91,14 @@ auto pWindow::remove(sStatusBar statusBar) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setBackgroundColor(Color color) -> void {
|
auto pWindow::setBackgroundColor(Color color) -> void {
|
||||||
if(color) {
|
static auto defaultColor = qtContainer->palette().color(QPalette::Background);
|
||||||
QPalette palette;
|
|
||||||
palette.setColor(QPalette::Background, QColor(color.red(), color.green(), color.blue() /*, color.alpha() */));
|
auto palette = qtContainer->palette();
|
||||||
qtContainer->setPalette(palette);
|
palette.setColor(QPalette::Background, CreateColor(color, defaultColor));
|
||||||
qtContainer->setAutoFillBackground(true);
|
qtContainer->setPalette(palette);
|
||||||
//translucency results are very unpleasant without a compositor; so disable for now
|
qtContainer->setAutoFillBackground((bool)color);
|
||||||
//qtWindow->setAttribute(Qt::WA_TranslucentBackground, color.alpha() != 255);
|
//translucency results are very unpleasant without a compositor; so disable for now
|
||||||
}
|
//qtWindow->setAttribute(Qt::WA_TranslucentBackground, color && color.alpha() != 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setDismissable(bool dismissable) -> void {
|
auto pWindow::setDismissable(bool dismissable) -> void {
|
||||||
|
@ -133,7 +134,7 @@ auto pWindow::setFullScreen(bool fullScreen) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setGeometry(Geometry geometry) -> void {
|
auto pWindow::setGeometry(Geometry geometry) -> void {
|
||||||
lock();
|
auto lock = acquire();
|
||||||
Application::processEvents();
|
Application::processEvents();
|
||||||
#if HIRO_QT==4
|
#if HIRO_QT==4
|
||||||
QApplication::syncX();
|
QApplication::syncX();
|
||||||
|
@ -145,13 +146,14 @@ auto pWindow::setGeometry(Geometry geometry) -> void {
|
||||||
qtWindow->move(geometry.x() - frameMargin().x(), geometry.y() - frameMargin().y());
|
qtWindow->move(geometry.x() - frameMargin().x(), geometry.y() - frameMargin().y());
|
||||||
//qtWindow->adjustSize() fails if larger than 2/3rds screen size
|
//qtWindow->adjustSize() fails if larger than 2/3rds screen size
|
||||||
qtWindow->resize(qtWindow->sizeHint());
|
qtWindow->resize(qtWindow->sizeHint());
|
||||||
|
qtContainer->setMinimumSize(1, 1);
|
||||||
if(state().resizable) {
|
if(state().resizable) {
|
||||||
//required to allow shrinking window from default size
|
setMaximumSize(state().maximumSize);
|
||||||
qtWindow->setMinimumSize(1, 1);
|
setMinimumSize(state().minimumSize);
|
||||||
qtContainer->setMinimumSize(1, 1);
|
} else {
|
||||||
|
setMaximumSize(geometry.size());
|
||||||
|
setMinimumSize(geometry.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setMaximized(bool maximized) -> void {
|
auto pWindow::setMaximized(bool maximized) -> void {
|
||||||
|
@ -159,7 +161,14 @@ auto pWindow::setMaximized(bool maximized) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setMaximumSize(Size size) -> void {
|
auto pWindow::setMaximumSize(Size size) -> void {
|
||||||
//todo
|
static auto maximumSize = qtWindow->maximumSize();
|
||||||
|
|
||||||
|
if(size) {
|
||||||
|
//once this is called, no matter what the size is, Qt will no longer allow the window to be maximized
|
||||||
|
qtWindow->setMaximumSize(size.width(), size.height() + _menuHeight() + _statusHeight());
|
||||||
|
} else {
|
||||||
|
qtWindow->setMaximumSize(maximumSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setMinimized(bool minimized) -> void {
|
auto pWindow::setMinimized(bool minimized) -> void {
|
||||||
|
@ -167,7 +176,7 @@ auto pWindow::setMinimized(bool minimized) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setMinimumSize(Size size) -> void {
|
auto pWindow::setMinimumSize(Size size) -> void {
|
||||||
//todo
|
qtWindow->setMinimumSize(size.width(), size.height() + _menuHeight() + _statusHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setModal(bool modal) -> void {
|
auto pWindow::setModal(bool modal) -> void {
|
||||||
|
@ -200,7 +209,7 @@ auto pWindow::setResizable(bool resizable) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setTitle(const string& text) -> void {
|
auto pWindow::setTitle(const string& text) -> void {
|
||||||
qtWindow->setWindowTitle(QString::fromUtf8(text));
|
qtWindow->setWindowTitle(text ? QString::fromUtf8(text) : " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setVisible(bool visible) -> void {
|
auto pWindow::setVisible(bool visible) -> void {
|
||||||
|
@ -220,8 +229,10 @@ auto pWindow::_append(mWidget& widget) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::_menuHeight() const -> uint {
|
auto pWindow::_menuHeight() const -> uint {
|
||||||
if(!qtMenuBar->isVisible()) return 0;
|
if(auto& menuBar = state().menuBar) {
|
||||||
return settings.geometry.menuHeight + _menuTextHeight();
|
if(menuBar->visible()) return settings.geometry.menuHeight + _menuTextHeight();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::_menuTextHeight() const -> uint {
|
auto pWindow::_menuTextHeight() const -> uint {
|
||||||
|
@ -235,8 +246,10 @@ auto pWindow::_menuTextHeight() const -> uint {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::_statusHeight() const -> uint {
|
auto pWindow::_statusHeight() const -> uint {
|
||||||
if(!qtStatusBar->isVisible()) return 0;
|
if(auto& statusBar = state().statusBar) {
|
||||||
return settings.geometry.statusHeight + _statusTextHeight();
|
if(statusBar->visible()) return settings.geometry.statusHeight + _statusTextHeight();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::_statusTextHeight() const -> uint {
|
auto pWindow::_statusTextHeight() const -> uint {
|
||||||
|
@ -314,7 +327,7 @@ auto QtWindow::keyReleaseEvent(QKeyEvent* event) -> void {
|
||||||
//if(sym != Keyboard::Keycode::None && self.window.onKeyRelease) self.window.onKeyRelease(sym);
|
//if(sym != Keyboard::Keycode::None && self.window.onKeyRelease) self.window.onKeyRelease(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto QtWindow::resizeEvent(QResizeEvent*) -> void {
|
auto QtWindow::resizeEvent(QResizeEvent* event) -> void {
|
||||||
if(!p.locked() && !p.state().fullScreen && p.qtWindow->isVisible()) {
|
if(!p.locked() && !p.state().fullScreen && p.qtWindow->isVisible()) {
|
||||||
p.state().geometry.setSize({
|
p.state().geometry.setSize({
|
||||||
p.qtContainer->geometry().width(),
|
p.qtContainer->geometry().width(),
|
||||||
|
@ -334,8 +347,8 @@ auto QtWindow::resizeEvent(QResizeEvent*) -> void {
|
||||||
auto QtWindow::sizeHint() const -> QSize {
|
auto QtWindow::sizeHint() const -> QSize {
|
||||||
uint width = p.state().geometry.width();
|
uint width = p.state().geometry.width();
|
||||||
uint height = p.state().geometry.height();
|
uint height = p.state().geometry.height();
|
||||||
if(p.qtMenuBar->isVisible()) height += settings.geometry.menuHeight;
|
height += p._menuHeight();
|
||||||
if(p.qtStatusBar->isVisible()) height += settings.geometry.statusHeight;
|
height += p._statusHeight();
|
||||||
return QSize(width, height);
|
return QSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,7 @@ auto pApplication::initialize() -> void {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pKeyboard::initialize();
|
pKeyboard::initialize();
|
||||||
|
pWindow::initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> bool {
|
static auto Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> bool {
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
namespace hiro {
|
namespace hiro {
|
||||||
|
|
||||||
struct pFont;
|
|
||||||
struct pObject;
|
|
||||||
struct pWindow;
|
|
||||||
struct pMenu;
|
|
||||||
struct pLayout;
|
|
||||||
struct pWidget;
|
|
||||||
|
|
||||||
struct AppMessage {
|
struct AppMessage {
|
||||||
enum : uint {
|
enum : uint {
|
||||||
None = WM_APP,
|
None = WM_APP,
|
||||||
|
|
|
@ -6,37 +6,49 @@ auto pStatusBar::construct() -> void {
|
||||||
if(auto parent = _parent()) {
|
if(auto parent = _parent()) {
|
||||||
hwnd = CreateWindow(STATUSCLASSNAME, L"", WS_CHILD, 0, 0, 0, 0, parent->hwnd, nullptr, GetModuleHandle(0), 0);
|
hwnd = CreateWindow(STATUSCLASSNAME, L"", WS_CHILD, 0, 0, 0, 0, parent->hwnd, nullptr, GetModuleHandle(0), 0);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&reference);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&reference);
|
||||||
setEnabled(self().enabled(true));
|
setEnabled(self().enabled());
|
||||||
setFont(self().font(true));
|
setFont(self().font());
|
||||||
setText(self().text());
|
setText(self().text());
|
||||||
setVisible(self().visible(true));
|
setVisible(self().visible());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pStatusBar::destruct() -> void {
|
auto pStatusBar::destruct() -> void {
|
||||||
if(hfont) { DeleteObject(hfont); hfont = nullptr; }
|
if(hfont) { DeleteObject(hfont); hfont = nullptr; }
|
||||||
if(hwnd) { DestroyWindow(hwnd); hwnd = nullptr; }
|
if(hwnd) { DestroyWindow(hwnd); hwnd = nullptr; }
|
||||||
|
|
||||||
if(auto parent = _parent()) {
|
if(auto parent = _parent()) {
|
||||||
parent->setGeometry(parent->state().geometry);
|
parent->setGeometry(parent->state().geometry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pStatusBar::setEnabled(bool enabled) -> void {
|
auto pStatusBar::setEnabled(bool) -> void {
|
||||||
//unsupported
|
//unsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pStatusBar::setFont(const Font& font) -> void {
|
auto pStatusBar::setFont(const Font&) -> void {
|
||||||
|
auto font = self().font(true);
|
||||||
if(hfont) DeleteObject(hfont);
|
if(hfont) DeleteObject(hfont);
|
||||||
hfont = pFont::create(font);
|
hfont = pFont::create(font);
|
||||||
if(hwnd) SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, 0);
|
SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, 0);
|
||||||
|
|
||||||
|
auto& text = state().text;
|
||||||
|
auto height = font.size(text ? text : " ").height();
|
||||||
|
SendMessage(hwnd, SB_SETMINHEIGHT, (WPARAM)height, 0);
|
||||||
|
|
||||||
|
if(auto parent = _parent()) {
|
||||||
|
parent->setGeometry(parent->state().geometry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pStatusBar::setText(const string& text) -> void {
|
auto pStatusBar::setText(const string&) -> void {
|
||||||
if(hwnd) SendMessage(hwnd, SB_SETTEXT, 0, (LPARAM)(wchar_t*)utf16_t(text));
|
auto& text = state().text;
|
||||||
|
SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)(wchar_t*)utf16_t(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pStatusBar::setVisible(bool visible) -> void {
|
auto pStatusBar::setVisible(bool) -> void {
|
||||||
if(hwnd) ShowWindow(hwnd, visible ? SW_SHOWNORMAL : SW_HIDE);
|
ShowWindow(hwnd, self().visible() ? SW_SHOWNORMAL : SW_HIDE);
|
||||||
|
|
||||||
if(auto parent = _parent()) {
|
if(auto parent = _parent()) {
|
||||||
parent->setGeometry(parent->state().geometry);
|
parent->setGeometry(parent->state().geometry);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +58,7 @@ auto pStatusBar::_parent() -> maybe<pWindow&> {
|
||||||
if(auto parent = self().parentWindow(true)) {
|
if(auto parent = self().parentWindow(true)) {
|
||||||
if(auto self = parent->self()) return *self;
|
if(auto self = parent->self()) return *self;
|
||||||
}
|
}
|
||||||
return nothing;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,20 @@ static auto CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT ms
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case WM_GETMINMAXINFO: {
|
||||||
|
auto info = (LPMINMAXINFO)lparam;
|
||||||
|
auto frameMargin = pWindow->frameMargin();
|
||||||
|
if(auto minimumSize = window->state.minimumSize) {
|
||||||
|
info->ptMinTrackSize.x = minimumSize.width() + frameMargin.width();
|
||||||
|
info->ptMinTrackSize.y = minimumSize.height() + frameMargin.height();
|
||||||
|
}
|
||||||
|
if(auto maximumSize = window->state.maximumSize) {
|
||||||
|
info->ptMaxTrackSize.x = maximumSize.width() + frameMargin.width();
|
||||||
|
info->ptMaxTrackSize.y = maximumSize.height() + frameMargin.height();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case WM_MENUCOMMAND: {
|
case WM_MENUCOMMAND: {
|
||||||
return Menu_windowProc(hwnd, msg, wparam, lparam);
|
return Menu_windowProc(hwnd, msg, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,19 @@ namespace hiro {
|
||||||
static const uint FixedStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_BORDER | WS_CLIPCHILDREN;
|
static const uint FixedStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_BORDER | WS_CLIPCHILDREN;
|
||||||
static const uint ResizableStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN;
|
static const uint ResizableStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN;
|
||||||
|
|
||||||
|
uint pWindow::minimumStatusHeight = 0;
|
||||||
|
|
||||||
|
auto pWindow::initialize() -> void {
|
||||||
|
HWND hwnd = CreateWindow(L"hiroWindow", L"", ResizableStyle, 128, 128, 256, 256, 0, 0, GetModuleHandle(0), 0);
|
||||||
|
HWND hstatus = CreateWindow(STATUSCLASSNAME, L"", WS_CHILD, 0, 0, 0, 0, hwnd, nullptr, GetModuleHandle(0), 0);
|
||||||
|
SetWindowPos(hstatus, nullptr, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
|
RECT rc;
|
||||||
|
GetWindowRect(hstatus, &rc);
|
||||||
|
minimumStatusHeight = rc.bottom - rc.top;
|
||||||
|
DestroyWindow(hstatus);
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
auto pWindow::construct() -> void {
|
auto pWindow::construct() -> void {
|
||||||
hwnd = CreateWindow(L"hiroWindow", L"", ResizableStyle, 128, 128, 256, 256, 0, 0, GetModuleHandle(0), 0);
|
hwnd = CreateWindow(L"hiroWindow", L"", ResizableStyle, 128, 128, 256, 256, 0, 0, GetModuleHandle(0), 0);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&reference);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&reference);
|
||||||
|
@ -35,21 +48,11 @@ auto pWindow::focused() const -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::frameMargin() const -> Geometry {
|
auto pWindow::frameMargin() const -> Geometry {
|
||||||
unsigned style = state().resizable ? ResizableStyle : FixedStyle;
|
|
||||||
if(state().fullScreen) style = 0;
|
|
||||||
RECT rc{0, 0, 640, 480};
|
RECT rc{0, 0, 640, 480};
|
||||||
AdjustWindowRect(&rc, style, (bool)GetMenu(hwnd));
|
uint style = state().fullScreen ? 0 : state().resizable ? ResizableStyle : FixedStyle;
|
||||||
signed statusHeight = 0;
|
bool menuVisible = state().menuBar && state().menuBar->visible();
|
||||||
if(auto& statusBar = state().statusBar) {
|
AdjustWindowRect(&rc, style, menuVisible);
|
||||||
if(auto self = statusBar->self()) {
|
return {abs(rc.left), abs(rc.top), (rc.right - rc.left) - 640, (rc.bottom - rc.top) + _statusHeight() - 480};
|
||||||
if(statusBar->visible()) {
|
|
||||||
RECT src;
|
|
||||||
GetClientRect(self->hwnd, &src);
|
|
||||||
statusHeight = src.bottom - src.top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {abs(rc.left), abs(rc.top), (rc.right - rc.left) - 640, (rc.bottom - rc.top) + statusHeight - 480};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::remove(sMenuBar menuBar) -> void {
|
auto pWindow::remove(sMenuBar menuBar) -> void {
|
||||||
|
@ -183,14 +186,9 @@ auto pWindow::setTitle(string text) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::setVisible(bool visible) -> void {
|
auto pWindow::setVisible(bool visible) -> void {
|
||||||
lock();
|
auto lock = acquire();
|
||||||
ShowWindow(hwnd, visible ? SW_SHOWNORMAL : SW_HIDE);
|
ShowWindow(hwnd, visible ? SW_SHOWNORMAL : SW_HIDE);
|
||||||
if(!visible) setModal(false);
|
if(!visible) setModal(false);
|
||||||
|
|
||||||
if(auto& sizable = state().sizable) {
|
|
||||||
if(auto self = sizable->self()) self->setVisible(sizable->visible(true));
|
|
||||||
}
|
|
||||||
unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -301,6 +299,18 @@ auto pWindow::_modalityUpdate() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto pWindow::_statusHeight() const -> int {
|
||||||
|
int height = 0;
|
||||||
|
if(auto& statusBar = state().statusBar) {
|
||||||
|
if(statusBar->visible()) {
|
||||||
|
auto& text = statusBar->state.text;
|
||||||
|
height = statusBar->font(true).size(text ? text : " ").height();
|
||||||
|
height = max(height, minimumStatusHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,6 +5,10 @@ namespace hiro {
|
||||||
struct pWindow : pObject {
|
struct pWindow : pObject {
|
||||||
Declare(Window, Object)
|
Declare(Window, Object)
|
||||||
|
|
||||||
|
static auto initialize() -> void;
|
||||||
|
|
||||||
|
static uint minimumStatusHeight;
|
||||||
|
|
||||||
auto append(sMenuBar menuBar) -> void;
|
auto append(sMenuBar menuBar) -> void;
|
||||||
auto append(sSizable sizable) -> void;
|
auto append(sSizable sizable) -> void;
|
||||||
auto append(sStatusBar statusBar) -> void;
|
auto append(sStatusBar statusBar) -> void;
|
||||||
|
@ -42,6 +46,7 @@ struct pWindow : pObject {
|
||||||
auto _modalityCount() -> unsigned;
|
auto _modalityCount() -> unsigned;
|
||||||
auto _modalityDisabled() -> bool;
|
auto _modalityDisabled() -> bool;
|
||||||
auto _modalityUpdate() -> void;
|
auto _modalityUpdate() -> void;
|
||||||
|
auto _statusHeight() const -> int;
|
||||||
|
|
||||||
HWND hwnd = nullptr;
|
HWND hwnd = nullptr;
|
||||||
HFONT hstatusfont = nullptr;
|
HFONT hstatusfont = nullptr;
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
name := icarus
|
name := icarus
|
||||||
build := performance
|
build := performance
|
||||||
|
flags += -I..
|
||||||
|
|
||||||
nall.path := ../nall
|
nall.path := ../nall
|
||||||
include $(nall.path)/GNUmakefile
|
include $(nall.path)/GNUmakefile
|
||||||
|
|
||||||
object.path := obj
|
|
||||||
flags += -I..
|
|
||||||
|
|
||||||
hiro.path := ../hiro
|
hiro.path := ../hiro
|
||||||
hiro.resource := data/$(name).rc
|
hiro.resource := data/$(name).rc
|
||||||
include $(hiro.path)/GNUmakefile
|
include $(hiro.path)/GNUmakefile
|
||||||
|
|
||||||
objects += obj/hiro.o $(if $(call streq,$(platform),windows),obj/hiro-resource.o)
|
objects := obj/icarus.o
|
||||||
objects += obj/icarus.o
|
|
||||||
|
|
||||||
all: $(objects)
|
obj/icarus.o: icarus.cpp
|
||||||
|
|
||||||
|
all: $(hiro.objects) $(objects)
|
||||||
$(info Linking out/$(name) ...)
|
$(info Linking out/$(name) ...)
|
||||||
+@$(strip $(compiler) -o out/$(name) $(objects) $(options) $(hiro.options))
|
+@$(compiler) -o out/$(name) $(hiro.objects) $(objects) $(hiro.options) $(options)
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
rm -rf out/$(name).app
|
rm -rf out/$(name).app
|
||||||
mkdir -p out/$(name).app/Contents/MacOS/
|
mkdir -p out/$(name).app/Contents/MacOS/
|
||||||
|
@ -26,16 +25,14 @@ ifeq ($(platform),macos)
|
||||||
sips -s format icns data/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
|
sips -s format icns data/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj/icarus.o: icarus.cpp $(call rwildcard,core/) $(call rwildcard,heuristics/) $(call rwildcard,ui/)
|
verbose: hiro.verbose nall.verbose all;
|
||||||
$(info Compiling $< ...)
|
|
||||||
@$(compiler) $(flags.cpp) $(flags) -o obj/icarus.o -c icarus.cpp
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
rm -rf out/$(name).app
|
rm -rf out/$(name).app
|
||||||
endif
|
endif
|
||||||
$(call rm,obj/*)
|
$(call delete,obj/*)
|
||||||
$(call rm,out/*)
|
$(call delete,out/*)
|
||||||
|
|
||||||
install:
|
install:
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
|
|
|
@ -31,21 +31,19 @@ ifeq ($(platform),)
|
||||||
|
|
||||||
# common commands
|
# common commands
|
||||||
ifeq ($(uname),)
|
ifeq ($(uname),)
|
||||||
rm = $(info Deleting $1 ...) @del /q $(subst /,\,$1)
|
delete = $(info Deleting $1 ...) @del /q $(subst /,\,$1)
|
||||||
rmdir = $(info Deleting $1 ...) @del /s /q $(subst /,\,$1) && if exist $(subst /,\,$1) (rmdir /s /q $(subst /,\,$1))
|
rdelete = $(info Deleting $1 ...) @del /s /q $(subst /,\,$1) && if exist $(subst /,\,$1) (rmdir /s /q $(subst /,\,$1))
|
||||||
else
|
else
|
||||||
rm = $(info Deleting $1 ...) @rm -f $1
|
delete = $(info Deleting $1 ...) @rm -f $1
|
||||||
rmdir = $(info Deleting $1 ...) @rm -rf $1
|
rdelete = $(info Deleting $1 ...) @rm -rf $1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
flags.c := -x c -std=c11
|
flags.c = -x c -std=c11
|
||||||
flags.cpp := -x c++ -std=c++14
|
flags.cpp = -x c++ -std=c++14
|
||||||
flags.objc := -x objective-c -std=c11
|
flags.objc = -x objective-c -std=c11
|
||||||
flags.objcpp := -x objective-c++ -std=c++14
|
flags.objcpp = -x objective-c++ -std=c++14
|
||||||
|
flags.deps = -MMD -MP -MF $(@:.o=.d)
|
||||||
flags :=
|
|
||||||
options :=
|
|
||||||
|
|
||||||
# compiler detection
|
# compiler detection
|
||||||
ifeq ($(compiler),)
|
ifeq ($(compiler),)
|
||||||
|
@ -135,16 +133,31 @@ endif
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
prefix := $(HOME)/.local
|
prefix := $(HOME)/.local
|
||||||
|
object.path := obj
|
||||||
|
|
||||||
# targets
|
# rules
|
||||||
default: all;
|
default: all;
|
||||||
verbose: information all;
|
|
||||||
information:
|
nall.verbose:
|
||||||
$(info Compiler Flags:)
|
$(info Compiler Flags:)
|
||||||
$(foreach n,$(sort $(call unique,$(flags))),$(if $(filter-out -I%,$n),$(info $([space]) $n)))
|
$(foreach n,$(sort $(call unique,$(flags))),$(if $(filter-out -I%,$n),$(info $([space]) $n)))
|
||||||
$(info Linker Options:)
|
$(info Linker Options:)
|
||||||
$(foreach n,$(sort $(call unique,$(options))),$(if $(filter-out -l%,$n),$(info $([space]) $n)))
|
$(foreach n,$(sort $(call unique,$(options))),$(if $(filter-out -l%,$n),$(info $([space]) $n)))
|
||||||
|
|
||||||
|
%.o: $<
|
||||||
|
$(info Compiling $< ...)
|
||||||
|
@$(call compile)
|
||||||
|
|
||||||
|
# function compile([arguments])
|
||||||
|
compile = \
|
||||||
|
$(strip \
|
||||||
|
$(if $(filter %.c,$<), \
|
||||||
|
$(compiler) $(flags.c) $(flags.deps) $(flags) $1 -c $< -o $@ \
|
||||||
|
,$(if $(filter %.cpp,$<), \
|
||||||
|
$(compiler) $(flags.cpp) $(flags.deps) $(flags) $1 -c $< -o $@ \
|
||||||
|
)) \
|
||||||
|
)
|
||||||
|
|
||||||
# function rwildcard(directory, pattern)
|
# function rwildcard(directory, pattern)
|
||||||
rwildcard = \
|
rwildcard = \
|
||||||
$(strip \
|
$(strip \
|
||||||
|
|
|
@ -63,6 +63,11 @@ struct Locale {
|
||||||
struct Namespace {
|
struct Namespace {
|
||||||
Namespace(Locale& _locale, string _namespace) : _locale(_locale), _namespace(_namespace) {}
|
Namespace(Locale& _locale, string _namespace) : _locale(_locale), _namespace(_namespace) {}
|
||||||
|
|
||||||
|
template<typename... P>
|
||||||
|
auto operator()(string input, P&&... p) const -> string {
|
||||||
|
return _locale(_namespace, input, forward<P>(p)...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... P>
|
template<typename... P>
|
||||||
auto tr(string input, P&&... p) const -> string {
|
auto tr(string input, P&&... p) const -> string {
|
||||||
return _locale(_namespace, input, forward<P>(p)...);
|
return _locale(_namespace, input, forward<P>(p)...);
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
ifeq ($(ruby),)
|
||||||
|
ifeq ($(platform),windows)
|
||||||
|
ruby += video.wgl video.direct3d video.directdraw video.gdi
|
||||||
|
ruby += audio.asio audio.wasapi audio.xaudio2 audio.directsound
|
||||||
|
ruby += input.windows
|
||||||
|
else ifeq ($(platform),macos)
|
||||||
|
ruby += video.cgl
|
||||||
|
ruby += audio.openal
|
||||||
|
ruby += input.quartz input.carbon
|
||||||
|
else ifeq ($(platform),linux)
|
||||||
|
ruby += video.glx video.xvideo video.xshm
|
||||||
|
ruby += audio.oss audio.alsa audio.openal audio.pulseaudio audio.pulseaudiosimple audio.ao
|
||||||
|
ruby += input.sdl input.xlib input.udev
|
||||||
|
else ifeq ($(platform),bsd)
|
||||||
|
ruby += video.glx video.xvideo video.xshm
|
||||||
|
ruby += audio.oss audio.openal
|
||||||
|
ruby += input.sdl input.xlib
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(platform),macos)
|
ifeq ($(platform),macos)
|
||||||
ruby.flags := $(flags.objcpp)
|
ruby.flags := $(flags.objcpp)
|
||||||
else
|
else
|
||||||
|
@ -46,6 +66,12 @@ ifeq ($(platform),bsd)
|
||||||
ruby.options += $(if $(findstring audio.openal,$(ruby)),-lopenal)
|
ruby.options += $(if $(findstring audio.openal,$(ruby)),-lopenal)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(object.path)/ruby.o: $(ruby.path)/ruby.cpp $(call rwildcard,$(ruby.path)) $(call rwildcard,$(nall.path))
|
ruby.objects := $(object.path)/ruby.o
|
||||||
|
|
||||||
|
$(object.path)/ruby.o: $(ruby.path)/ruby.cpp
|
||||||
$(info Compiling $< ...)
|
$(info Compiling $< ...)
|
||||||
@$(compiler) $(ruby.flags) $(flags) -c $< -o $@
|
@$(compiler) $(ruby.flags) $(flags) $(flags.deps) -c $< -o $@
|
||||||
|
|
||||||
|
ruby.verbose:
|
||||||
|
$(info ruby Drivers:)
|
||||||
|
$(foreach n,$(ruby),$(info $([space]) $n))
|
||||||
|
|
Loading…
Reference in New Issue