Update to v093r03 release.

byuu says:

Updated to support latest phoenix changes.
Converted Settings and Tools to TabFrame views.

Errata:
- phoenix/Windows ComboButton wasn't calling parent
  pWidget::setGeometry() [fixed locally]
- TRACKBAR_CLASS draws COLOR_3DFACE for the background even when its
  parent is a WC_TABCONTROL
This commit is contained in:
Tim Allen 2013-11-28 21:29:01 +11:00
parent 8c0b0fa4ad
commit 68eaf53691
210 changed files with 5319 additions and 1977 deletions

View File

@ -3,7 +3,7 @@
namespace Emulator {
static const char Name[] = "higan";
static const char Version[] = "093.02";
static const char Version[] = "093.03";
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
static const char Website[] = "http://byuu.org/";

View File

@ -41,7 +41,7 @@ ifeq ($(compiler),)
flags :=
link :=
else ifeq ($(platform),macosx)
compiler := clang
compiler := clang++
flags := -w -stdlib=libc++
link := -lc++ -lobjc
else ifeq ($(platform),bsd)

View File

@ -8,7 +8,7 @@
#include <nall/string.hpp>
#include <nall/utility.hpp>
#if defined(PLATFORM_X) || defined(PLATFORM_OSX)
#if defined(PLATFORM_X) || defined(PLATFORM_MACOSX)
#include <dlfcn.h>
#elif defined(PLATFORM_WINDOWS)
#include <windows.h>
@ -59,7 +59,7 @@ inline void library::close() {
dlclose((void*)handle);
handle = 0;
}
#elif defined(PLATFORM_OSX)
#elif defined(PLATFORM_MACOSX)
inline bool library::open(const string& name, const string& path) {
if(handle) close();
handle = (uintptr_t)dlopen(string(path, !path.empty() && !path.endswith("/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY);

View File

@ -11,13 +11,14 @@
namespace nall {
struct image {
uint8_t* data = nullptr;
unsigned width = 0;
uint8_t* data = nullptr;
unsigned width = 0;
unsigned height = 0;
unsigned pitch = 0;
unsigned pitch = 0;
unsigned size = 0;
bool endian = 0;
unsigned depth = 32;
bool endian = 0; //0 = lsb, 1 = msb
unsigned depth = 32;
unsigned stride = 4;
struct Channel {
@ -34,10 +35,18 @@ struct image {
}
};
Channel alpha = {255u << 24, 8u, 24};
Channel red = {255u << 16, 8u, 16};
Channel green = {255u << 8, 8u, 8};
Channel blue = {255u << 0, 8u, 0};
enum class blend : unsigned {
add,
sourceAlpha, //color = sourceColor * sourceAlpha + targetColor * (1 - sourceAlpha)
sourceColor, //color = sourceColor
targetAlpha, //color = targetColor * targetAlpha + sourceColor * (1 - targetAlpha)
targetColor, //color = targetColor
};
Channel alpha = {255u << 24, 8u, 24u};
Channel red = {255u << 16, 8u, 16u};
Channel green = {255u << 8, 8u, 8u};
Channel blue = {255u << 0, 8u, 0u};
typedef double (*interpolation)(double, double, double, double, double);
static inline unsigned bitDepth(uint64_t color);
@ -63,18 +72,27 @@ struct image {
inline void free();
inline bool empty() const;
inline void allocate(unsigned width, unsigned height);
inline void clear(uint64_t color);
inline bool crop(unsigned x, unsigned y, unsigned width, unsigned height);
inline void impose(blend mode, unsigned targetX, unsigned targetY, image source, unsigned x, unsigned y, unsigned width, unsigned height);
inline void fill(uint64_t color = 0);
inline void gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d);
inline void horizontalGradient(uint64_t a, uint64_t b);
inline void verticalGradient(uint64_t a, uint64_t b);
inline bool load(const string& filename);
//inline bool loadBMP(const uint8_t* data, unsigned size);
inline bool loadPNG(const uint8_t* data, unsigned size);
inline void scale(unsigned width, unsigned height, interpolation op);
inline void scale(unsigned width, unsigned height, bool linear = true);
inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
inline void alphaBlend(uint64_t alphaColor);
protected:
inline uint64_t interpolate(double mu, const uint64_t* s, interpolation op);
inline void scaleX(unsigned width, interpolation op);
inline void scaleY(unsigned height, interpolation op);
inline uint8_t* allocate(unsigned width, unsigned height, unsigned stride);
alwaysinline uint64_t interpolate1D(int64_t a, int64_t b, uint32_t x);
alwaysinline uint64_t interpolate2D(int64_t a, int64_t b, int64_t c, int64_t d, uint32_t x, uint32_t y);
inline void scaleLinearWidth(unsigned width);
inline void scaleLinearHeight(unsigned height);
inline void scaleLinear(unsigned width, unsigned height);
inline void scaleNearest(unsigned width, unsigned height);
inline bool loadBMP(const string& filename);
inline bool loadPNG(const string& filename);
};
@ -131,6 +149,7 @@ image& image::operator=(const image& source) {
width = source.width;
height = source.height;
pitch = source.pitch;
size = source.size;
endian = source.endian;
stride = source.stride;
@ -140,8 +159,8 @@ image& image::operator=(const image& source) {
green = source.green;
blue = source.blue;
data = new uint8_t[width * height * stride];
memcpy(data, source.data, width * height * stride);
data = allocate(width, height, stride);
memcpy(data, source.data, source.size);
return *this;
}
@ -151,6 +170,7 @@ image& image::operator=(image&& source) {
width = source.width;
height = source.height;
pitch = source.pitch;
size = source.size;
endian = source.endian;
stride = source.stride;
@ -175,13 +195,13 @@ image::image(image&& source) {
image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) {
this->endian = endian;
this->depth = depth;
this->depth = depth;
this->stride = (depth / 8) + ((depth & 7) > 0);
alpha = {alphaMask, bitDepth(alphaMask), bitShift(alphaMask)};
red = {redMask, bitDepth(redMask), bitShift(redMask)};
red = {redMask, bitDepth(redMask), bitShift(redMask )};
green = {greenMask, bitDepth(greenMask), bitShift(greenMask)};
blue = {blueMask, bitDepth(blueMask), bitShift(blueMask)};
blue = {blueMask, bitDepth(blueMask), bitShift(blueMask )};
}
image::image(const string& filename) {
@ -231,39 +251,175 @@ bool image::empty() const {
void image::allocate(unsigned width, unsigned height) {
if(data != nullptr && this->width == width && this->height == height) return;
free();
data = new uint8_t[width * height * stride]();
data = allocate(width, height, stride);
pitch = width * stride;
size = height * pitch;
this->width = width;
this->height = height;
}
void image::clear(uint64_t color) {
uint8_t *dp = data;
void image::fill(uint64_t color) {
uint8_t* dp = data;
for(unsigned n = 0; n < width * height; n++) {
write(dp, color);
dp += stride;
}
}
void image::gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
//create gradient by scaling 2x2 image using linear interpolation
//replace data with gradient data to prevent extra copy
delete[] data;
nall::image gradient;
gradient.endian = endian, gradient.depth = depth, gradient.stride = stride;
gradient.alpha = alpha, gradient.red = red, gradient.green = green, gradient.blue = blue;
gradient.allocate(2, 2);
uint8_t* dp = gradient.data;
gradient.write(dp, a); dp += stride;
gradient.write(dp, b); dp += stride;
gradient.write(dp, c); dp += stride;
gradient.write(dp, d); dp += stride;
gradient.scale(width, height);
data = gradient.data;
gradient.data = nullptr;
}
void image::horizontalGradient(uint64_t a, uint64_t b) {
gradient(a, b, a, b);
}
void image::verticalGradient(uint64_t a, uint64_t b) {
gradient(a, a, b, b);
}
bool image::load(const string& filename) {
if(loadBMP(filename) == true) return true;
if(loadPNG(filename) == true) return true;
return false;
}
void image::scale(unsigned outputWidth, unsigned outputHeight, interpolation op) {
if(width != outputWidth) scaleX(outputWidth, op);
if(height != outputHeight) scaleY(outputHeight, op);
bool image::crop(unsigned outputX, unsigned outputY, unsigned outputWidth, unsigned outputHeight) {
if(outputX + outputWidth > width) return false;
if(outputY + outputHeight > height) return false;
uint8_t* outputData = allocate(outputWidth, outputHeight, stride);
unsigned outputPitch = outputWidth * stride;
#pragma omp parallel for
for(unsigned y = 0; y < outputHeight; y++) {
const uint8_t* sp = data + pitch * (outputY + y) + stride * outputX;
uint8_t* dp = outputData + outputPitch * y;
for(unsigned x = 0; x < outputWidth; x++) {
write(dp, read(sp));
sp += stride;
dp += stride;
}
}
delete[] data;
data = outputData;
width = outputWidth;
height = outputHeight;
pitch = outputPitch;
size = width * pitch;
return true;
}
void image::impose(blend mode, unsigned targetX, unsigned targetY, image source, unsigned sourceX, unsigned sourceY, unsigned sourceWidth, unsigned sourceHeight) {
source.transform(endian, depth, alpha.mask, red.mask, green.mask, blue.mask);
for(unsigned y = 0; y < sourceHeight; y++) {
const uint8_t* sp = source.data + source.pitch * (sourceY + y) + source.stride * sourceX;
uint8_t* dp = data + pitch * (targetY + y) + stride * targetX;
for(unsigned x = 0; x < sourceWidth; x++) {
uint64_t sourceColor = source.read(sp);
uint64_t targetColor = read(dp);
int64_t sa = (sourceColor & alpha.mask) >> alpha.shift;
int64_t sr = (sourceColor & red.mask ) >> red.shift;
int64_t sg = (sourceColor & green.mask) >> green.shift;
int64_t sb = (sourceColor & blue.mask ) >> blue.shift;
int64_t da = (targetColor & alpha.mask) >> alpha.shift;
int64_t dr = (targetColor & red.mask ) >> red.shift;
int64_t dg = (targetColor & green.mask) >> green.shift;
int64_t db = (targetColor & blue.mask ) >> blue.shift;
uint64_t a, r, g, b;
switch(mode) {
case blend::add:
a = max(sa, da);
r = min(red.mask >> red.shift, ((sr * sa) >> alpha.depth) + ((dr * da) >> alpha.depth));
g = min(green.mask >> green.shift, ((sg * sa) >> alpha.depth) + ((dg * da) >> alpha.depth));
b = min(blue.mask >> blue.shift, ((sb * sa) >> alpha.depth) + ((db * da) >> alpha.depth));
break;
case blend::sourceAlpha:
a = max(sa, da);
r = dr + (((sr - dr) * sa) >> alpha.depth);
g = dg + (((sg - dg) * sa) >> alpha.depth);
b = db + (((sb - db) * sa) >> alpha.depth);
break;
case blend::sourceColor:
a = sa;
r = sr;
g = sg;
b = sb;
break;
case blend::targetAlpha:
a = max(sa, da);
r = sr + (((dr - sr) * da) >> alpha.depth);
g = sg + (((dg - sg) * da) >> alpha.depth);
b = sb + (((db - sb) * da) >> alpha.depth);
break;
case blend::targetColor:
a = da;
r = dr;
g = dg;
b = db;
break;
}
write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift));
sp += source.stride;
dp += stride;
}
}
}
void image::scale(unsigned outputWidth, unsigned outputHeight, bool linear) {
if(width == outputWidth && height == outputHeight) return; //no scaling necessary
if(linear == false) return scaleNearest(outputWidth, outputHeight);
if(width == outputWidth ) return scaleLinearHeight(outputHeight);
if(height == outputHeight) return scaleLinearWidth(outputWidth);
//find fastest scaling method, based on number of interpolation operations required
//magnification usually benefits from two-pass linear interpolation
//minification usually benefits from one-pass bilinear interpolation
unsigned d1wh = ((width * outputWidth ) + (outputWidth * outputHeight)) * 1;
unsigned d1hw = ((height * outputHeight) + (outputWidth * outputHeight)) * 1;
unsigned d2wh = (outputWidth * outputHeight) * 3;
if(d1wh <= d1hw && d1wh <= d2wh) return scaleLinearWidth(outputWidth), scaleLinearHeight(outputHeight);
if(d1hw <= d2wh) return scaleLinearHeight(outputHeight), scaleLinearWidth(outputWidth);
return scaleLinear(outputWidth, outputHeight);
}
void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) {
if(endian == outputEndian && depth == outputDepth && alpha.mask == outputAlphaMask && red.mask == outputRedMask && green.mask == outputGreenMask && blue.mask == outputBlueMask) return;
image output(outputEndian, outputDepth, outputAlphaMask, outputRedMask, outputGreenMask, outputBlueMask);
output.allocate(width, height);
#pragma omp parallel for
for(unsigned y = 0; y < height; y++) {
const uint8_t* sp = data + pitch * y;
uint8_t* dp = output.data + output.pitch * y;
uint8_t* sp = data + pitch * y;
for(unsigned x = 0; x < width; x++) {
uint64_t color = read(sp);
sp += stride;
@ -287,9 +443,9 @@ void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAl
}
void image::alphaBlend(uint64_t alphaColor) {
uint64_t alphaR = (alphaColor & red.mask) >> red.shift;
uint64_t alphaR = (alphaColor & red.mask ) >> red.shift;
uint64_t alphaG = (alphaColor & green.mask) >> green.shift;
uint64_t alphaB = (alphaColor & blue.mask) >> blue.shift;
uint64_t alphaB = (alphaColor & blue.mask ) >> blue.shift;
#pragma omp parallel for
for(unsigned y = 0; y < height; y++) {
@ -298,9 +454,9 @@ void image::alphaBlend(uint64_t alphaColor) {
uint64_t color = read(dp);
uint64_t colorA = (color & alpha.mask) >> alpha.shift;
uint64_t colorR = (color & red.mask) >> red.shift;
uint64_t colorR = (color & red.mask ) >> red.shift;
uint64_t colorG = (color & green.mask) >> green.shift;
uint64_t colorB = (color & blue.mask) >> blue.shift;
uint64_t colorB = (color & blue.mask ) >> blue.shift;
double alphaScale = (double)colorA / (double)((1 << alpha.depth) - 1);
colorA = (1 << alpha.depth) - 1;
@ -316,99 +472,199 @@ void image::alphaBlend(uint64_t alphaColor) {
//protected
uint64_t image::interpolate(double mu, const uint64_t* s, double (*op)(double, double, double, double, double)) {
uint64_t aa = (s[0] & alpha.mask) >> alpha.shift, ar = (s[0] & red.mask) >> red.shift,
ag = (s[0] & green.mask) >> green.shift, ab = (s[0] & blue.mask) >> blue.shift;
uint64_t ba = (s[1] & alpha.mask) >> alpha.shift, br = (s[1] & red.mask) >> red.shift,
bg = (s[1] & green.mask) >> green.shift, bb = (s[1] & blue.mask) >> blue.shift;
uint64_t ca = (s[2] & alpha.mask) >> alpha.shift, cr = (s[2] & red.mask) >> red.shift,
cg = (s[2] & green.mask) >> green.shift, cb = (s[2] & blue.mask) >> blue.shift;
uint64_t da = (s[3] & alpha.mask) >> alpha.shift, dr = (s[3] & red.mask) >> red.shift,
dg = (s[3] & green.mask) >> green.shift, db = (s[3] & blue.mask) >> blue.shift;
int64_t A = op(mu, aa, ba, ca, da);
int64_t R = op(mu, ar, br, cr, dr);
int64_t G = op(mu, ag, bg, cg, dg);
int64_t B = op(mu, ab, bb, cb, db);
A = max(0, min(A, (1 << alpha.depth) - 1));
R = max(0, min(R, (1 << red.depth) - 1));
G = max(0, min(G, (1 << green.depth) - 1));
B = max(0, min(B, (1 << blue.depth) - 1));
return (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift);
uint8_t* image::allocate(unsigned width, unsigned height, unsigned stride) {
//allocate 1x1 larger than requested; so that linear interpolation does not require bounds-checking
unsigned size = width * height * stride;
unsigned padding = width * stride + stride;
uint8_t* data = new uint8_t[size + padding];
memset(data + size, 0x00, padding);
return data;
}
void image::scaleX(unsigned outputWidth, interpolation op) {
uint8_t* outputData = new uint8_t[outputWidth * height * stride];
//fixed-point reduction of: a * (1 - x) + b * x
uint64_t image::interpolate1D(int64_t a, int64_t b, uint32_t x) {
return a + (((b - a) * x) >> 32); //a + (b - a) * x
}
//fixed-point reduction of: a * (1 - x) * (1 - y) + b * x * (1 - y) + c * (1 - x) * y + d * x * y
uint64_t image::interpolate2D(int64_t a, int64_t b, int64_t c, int64_t d, uint32_t x, uint32_t y) {
a = a + (((b - a) * x) >> 32); //a + (b - a) * x
c = c + (((d - c) * x) >> 32); //c + (d - c) * x
return a + (((c - a) * y) >> 32); //a + (c - a) * y
}
void image::scaleLinearWidth(unsigned outputWidth) {
uint8_t* outputData = allocate(outputWidth, height, stride);
unsigned outputPitch = outputWidth * stride;
double step = (double)width / (double)outputWidth;
const uint8_t* terminal = data + pitch * height;
uint64_t xstride = ((uint64_t)(width - 1) << 32) / max(1u, outputWidth - 1);
#pragma omp parallel for
for(unsigned y = 0; y < height; y++) {
uint64_t xfraction = 0;
const uint8_t* sp = data + pitch * y;
uint8_t* dp = outputData + outputPitch * y;
uint8_t* sp = data + pitch * y;
double fraction = 0.0;
uint64_t s[4] = {sp < terminal ? read(sp) : 0}; //B,C (0,1) = center of kernel { 0, 0, 1, 2 }
s[1] = s[0];
s[2] = sp + stride < terminal ? read(sp += stride) : s[1];
s[3] = sp + stride < terminal ? read(sp += stride) : s[2];
uint64_t a = read(sp);
uint64_t b = read(sp + stride);
sp += stride;
for(unsigned x = 0; x < width; x++) {
while(fraction <= 1.0) {
if(dp >= outputData + outputPitch * height) break;
write(dp, interpolate(fraction, (const uint64_t*)&s, op));
unsigned x = 0;
while(x < outputWidth) {
while(xfraction < 0x100000000 && x++ < outputWidth) {
uint64_t A = interpolate1D((a & alpha.mask) >> alpha.shift, (b & alpha.mask) >> alpha.shift, xfraction);
uint64_t R = interpolate1D((a & red.mask ) >> red.shift , (b & red.mask ) >> red.shift, xfraction);
uint64_t G = interpolate1D((a & green.mask) >> green.shift, (b & green.mask) >> green.shift, xfraction);
uint64_t B = interpolate1D((a & blue.mask ) >> blue.shift , (b & blue.mask ) >> blue.shift, xfraction);
write(dp, (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift));
dp += stride;
fraction += step;
xfraction += xstride;
}
s[0] = s[1]; s[1] = s[2]; s[2] = s[3];
if(sp + stride < terminal) s[3] = read(sp += stride);
fraction -= 1.0;
sp += stride;
a = b;
b = read(sp);
xfraction -= 0x100000000;
}
}
free();
data = outputData;
width = outputWidth;
pitch = width * stride;
pitch = outputPitch;
size = height * pitch;
}
void image::scaleY(unsigned outputHeight, interpolation op) {
uint8_t* outputData = new uint8_t[width * outputHeight * stride];
double step = (double)height / (double)outputHeight;
const uint8_t* terminal = data + pitch * height;
void image::scaleLinearHeight(unsigned outputHeight) {
uint8_t* outputData = allocate(width, outputHeight, stride);
uint64_t ystride = ((uint64_t)(height - 1) << 32) / max(1u, outputHeight - 1);
#pragma omp parallel for
for(unsigned x = 0; x < width; x++) {
uint64_t yfraction = 0;
const uint8_t* sp = data + stride * x;
uint8_t* dp = outputData + stride * x;
uint8_t* sp = data + stride * x;
double fraction = 0.0;
uint64_t s[4] = {sp < terminal ? read(sp) : 0};
s[1] = s[0];
s[2] = sp + pitch < terminal ? read(sp += pitch) : s[1];
s[3] = sp + pitch < terminal ? read(sp += pitch) : s[2];
uint64_t a = read(sp);
uint64_t b = read(sp + pitch);
sp += pitch;
for(unsigned y = 0; y < height; y++) {
while(fraction <= 1.0) {
if(dp >= outputData + pitch * outputHeight) break;
write(dp, interpolate(fraction, (const uint64_t*)&s, op));
unsigned y = 0;
while(y < outputHeight) {
while(yfraction < 0x100000000 && y++ < outputHeight) {
uint64_t A = interpolate1D((a & alpha.mask) >> alpha.shift, (b & alpha.mask) >> alpha.shift, yfraction);
uint64_t R = interpolate1D((a & red.mask ) >> red.shift, (b & red.mask ) >> red.shift, yfraction);
uint64_t G = interpolate1D((a & green.mask) >> green.shift, (b & green.mask) >> green.shift, yfraction);
uint64_t B = interpolate1D((a & blue.mask ) >> blue.shift, (b & blue.mask ) >> blue.shift, yfraction);
write(dp, (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift));
dp += pitch;
fraction += step;
yfraction += ystride;
}
s[0] = s[1]; s[1] = s[2]; s[2] = s[3];
if(sp + pitch < terminal) s[3] = read(sp += pitch);
fraction -= 1.0;
sp += pitch;
a = b;
b = read(sp);
yfraction -= 0x100000000;
}
}
free();
data = outputData;
height = outputHeight;
size = height * pitch;
}
void image::scaleLinear(unsigned outputWidth, unsigned outputHeight) {
uint8_t* outputData = allocate(outputWidth, outputHeight, stride);
unsigned outputPitch = outputWidth * stride;
uint64_t xstride = ((uint64_t)(width - 1) << 32) / max(1u, outputWidth - 1);
uint64_t ystride = ((uint64_t)(height - 1) << 32) / max(1u, outputHeight - 1);
#pragma omp parallel for
for(unsigned y = 0; y < outputHeight; y++) {
uint64_t yfraction = ystride * y;
uint64_t xfraction = 0;
const uint8_t* sp = data + pitch * (yfraction >> 32);
uint8_t* dp = outputData + outputPitch * y;
uint64_t a = read(sp);
uint64_t b = read(sp + stride);
uint64_t c = read(sp + pitch);
uint64_t d = read(sp + pitch + stride);
sp += stride;
unsigned x = 0;
while(x < outputWidth) {
while(xfraction < 0x100000000 && x++ < outputWidth) {
uint64_t A = interpolate2D((a & alpha.mask) >> alpha.shift, (b & alpha.mask) >> alpha.shift, (c & alpha.mask) >> alpha.shift, (d & alpha.mask) >> alpha.shift, xfraction, yfraction);
uint64_t R = interpolate2D((a & red.mask ) >> red.shift, (b & red.mask ) >> red.shift, (c & red.mask ) >> red.shift, (d & red.mask ) >> red.shift, xfraction, yfraction);
uint64_t G = interpolate2D((a & green.mask) >> green.shift, (b & green.mask) >> green.shift, (c & green.mask) >> green.shift, (d & green.mask) >> green.shift, xfraction, yfraction);
uint64_t B = interpolate2D((a & blue.mask ) >> blue.shift, (b & blue.mask ) >> blue.shift, (c & blue.mask ) >> blue.shift, (d & blue.mask ) >> blue.shift, xfraction, yfraction);
write(dp, (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift));
dp += stride;
xfraction += xstride;
}
sp += stride;
a = b;
c = d;
b = read(sp);
d = read(sp + pitch);
xfraction -= 0x100000000;
}
}
free();
data = outputData;
width = outputWidth;
height = outputHeight;
pitch = outputPitch;
size = height * pitch;
}
void image::scaleNearest(unsigned outputWidth, unsigned outputHeight) {
uint8_t* outputData = allocate(outputWidth, outputHeight, stride);
unsigned outputPitch = outputWidth * stride;
uint64_t xstride = ((uint64_t)width << 32) / outputWidth;
uint64_t ystride = ((uint64_t)height << 32) / outputHeight;
#pragma omp parallel for
for(unsigned y = 0; y < outputHeight; y++) {
uint64_t yfraction = ystride * y;
uint64_t xfraction = 0;
const uint8_t* sp = data + pitch * (yfraction >> 32);
uint8_t* dp = outputData + outputPitch * y;
uint64_t a = read(sp);
unsigned x = 0;
while(x < outputWidth) {
while(xfraction < 0x100000000 && x++ < outputWidth) {
write(dp, a);
dp += stride;
xfraction += xstride;
}
sp += stride;
a = read(sp);
xfraction -= 0x100000000;
}
}
free();
data = outputData;
width = outputWidth;
height = outputHeight;
pitch = outputPitch;
size = height * pitch;
}
bool image::loadBMP(const string& filename) {

View File

@ -21,6 +21,7 @@ namespace Math {
#include <utility>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <math.h>
#include <stdarg.h>

View File

@ -5,7 +5,7 @@
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#if !defined(PLATFORM_X) && !defined(PLATFORM_OSX)
#if !defined(PLATFORM_X) && !defined(PLATFORM_MACOSX)
#error "nall/serial: unsupported platform"
#endif

View File

@ -49,7 +49,7 @@ string configpath() {
SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path);
result = (const char*)utf8_t(path);
result.transform("\\", "/");
#elif defined(PLATFORM_OSX)
#elif defined(PLATFORM_MACOSX)
result = {userpath(), "Library/Application Support/"};
#else
result = {userpath(), ".config/"};
@ -66,7 +66,7 @@ string sharedpath() {
SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path);
result = (const char*)utf8_t(path);
result.transform("\\", "/");
#elif defined(PLATFORM_OSX)
#elif defined(PLATFORM_MACOSX)
result = "/Library/Application Support/";
#else
result = "/usr/share/";

View File

@ -5,7 +5,7 @@
#include <nall/function.hpp>
#include <nall/intrinsics.hpp>
#if defined(PLATFORM_X) || defined(PLATFORM_OSX)
#if defined(PLATFORM_X) || defined(PLATFORM_MACOSX)
#include <pthread.h>
namespace nall {
@ -64,7 +64,7 @@ void* thread_entry_point(void* parameter) {
}
}
#elif defined(PLATFORM_WIN)
#elif defined(PLATFORM_WINDOWS)
namespace nall {
inline DWORD WINAPI thread_entry_point(LPVOID);

View File

@ -3,7 +3,7 @@ ifeq ($(platform),)
phoenixlink =
else ifeq ($(platform),windows)
phoenixflags = $(cppflags) $(flags) -DPHOENIX_WINDOWS
phoenixlink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
phoenixlink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -luxtheme -lmsimg32 -lshlwapi
else ifeq ($(platform),macosx)
phoenixflags = $(objcppflags) $(flags) -DPHOENIX_COCOA
phoenixlink = -framework Cocoa -framework Carbon

View File

@ -20,12 +20,6 @@
namespace phoenix {
bool pCheckItem::checked() {
@autoreleasepool {
return [cocoaAction state] != NSOffState;
}
}
void pCheckItem::setChecked(bool checked) {
@autoreleasepool {
auto state = checked ? NSOnState : NSOffState;

View File

@ -12,7 +12,6 @@ struct pCheckItem : public pAction {
CheckItem& checkItem;
CocoaCheckItem* cocoaCheckItem = nullptr;
bool checked();
void setChecked(bool checked);
void setText(string text);

View File

@ -19,12 +19,6 @@
namespace phoenix {
bool pRadioItem::checked() {
@autoreleasepool {
return [cocoaAction state] != NSOffState;
}
}
void pRadioItem::setChecked() {
@autoreleasepool {
for(auto& item : radioItem.state.group) {

View File

@ -12,7 +12,6 @@ struct pRadioItem : public pAction {
RadioItem& radioItem;
CocoaRadioItem* cocoaRadioItem = nullptr;
bool checked();
void setChecked();
void setGroup(const group<RadioItem>& group);
void setText(string text);

View File

@ -84,7 +84,7 @@ void pApplication::initialize() {
cocoaDelegate = [[CocoaDelegate alloc] init];
[NSApp setDelegate:cocoaDelegate];
//every window has the default application menu; call this so it is displayed at startup
[NSApp setMainMenu:[Window::none().p.cocoaWindow menu]];
[NSApp setMainMenu:[pWindow::none().p.cocoaWindow menu]];
}
}

View File

@ -1,19 +1,19 @@
namespace phoenix {
string pFont::serif(unsigned size, string style) {
if(size == 0) size = 12;
if(size == 0) size = 8;
if(style == "") style = "Normal";
return {"Georgia, ", size, ", ", style};
}
string pFont::sans(unsigned size, string style) {
if(size == 0) size = 12;
if(size == 0) size = 8;
if(style == "") style = "Normal";
return {"Lucida Grande, ", size, ", ", style};
}
string pFont::monospace(unsigned size, string style) {
if(size == 0) size = 12;
if(size == 0) size = 8;
if(style == "") style = "Normal";
return {"Menlo, ", size, ", ", style};
}
@ -32,10 +32,10 @@ NSFont* pFont::cocoaFont(string description) {
NSString* family = @"Lucida Grande";
NSFontTraitMask traits = 0;
CGFloat size = 12;
CGFloat size = 8.0;
if(!part(0).empty()) family = [NSString stringWithUTF8String:part(0)];
if(!part(1).empty()) size = real(part(1));
if(!part(1).empty()) size = decimal(part(1));
if(part(2).ifind("bold")) traits |= NSBoldFontMask;
if(part(2).ifind("italic")) traits |= NSItalicFontMask;
if(part(2).ifind("narrow")) traits |= NSNarrowFontMask;
@ -43,6 +43,7 @@ NSFont* pFont::cocoaFont(string description) {
if(part(2).ifind("condensed")) traits |= NSCondensedFontMask;
if(part(2).ifind("smallcaps")) traits |= NSSmallCapsFontMask;
size *= 1.5; //scale to point sizes (for consistency with other operating systems)
return [[NSFontManager sharedFontManager] fontWithFamily:family traits:traits weight:5 size:size];
}

View File

@ -22,8 +22,10 @@
#include "widget/button.cpp"
#include "widget/canvas.cpp"
#include "widget/check-button.cpp"
#include "widget/check-label.cpp"
#include "widget/combo-button.cpp"
#include "widget/console.cpp"
#include "widget/frame.cpp"
#include "widget/hex-edit.cpp"
#include "widget/horizontal-scroller.cpp"
#include "widget/horizontal-slider.cpp"
@ -32,6 +34,8 @@
#include "widget/list-view.cpp"
#include "widget/progress-bar.cpp"
#include "widget/radio-button.cpp"
#include "widget/radio-label.cpp"
#include "widget/tab-frame.cpp"
#include "widget/text-edit.cpp"
#include "widget/vertical-scroller.cpp"
#include "widget/vertical-slider.cpp"

View File

@ -29,8 +29,10 @@ namespace phoenix {
#include "widget/button.hpp"
#include "widget/canvas.hpp"
#include "widget/check-button.hpp"
#include "widget/check-label.hpp"
#include "widget/combo-button.hpp"
#include "widget/console.hpp"
#include "widget/frame.hpp"
#include "widget/hex-edit.hpp"
#include "widget/horizontal-scroller.hpp"
#include "widget/horizontal-slider.hpp"
@ -39,6 +41,8 @@ namespace phoenix {
#include "widget/list-view.hpp"
#include "widget/progress-bar.hpp"
#include "widget/radio-button.hpp"
#include "widget/radio-label.hpp"
#include "widget/tab-frame.hpp"
#include "widget/text-edit.hpp"
#include "widget/vertical-scroller.hpp"
#include "widget/vertical-slider.hpp"

View File

@ -19,7 +19,7 @@
}
if(timer->state.enabled == false) return;
instance = [NSTimer
scheduledTimerWithTimeInterval:timer->state.milliseconds / 1000.0
scheduledTimerWithTimeInterval:timer->state.interval / 1000.0
target:self selector:@selector(run:) userInfo:nil repeats:YES
];
}
@ -38,7 +38,7 @@ void pTimer::setEnabled(bool enabled) {
}
}
void pTimer::setInterval(unsigned milliseconds) {
void pTimer::setInterval(unsigned interval) {
@autoreleasepool {
[cocoaTimer update];
}

View File

@ -16,7 +16,7 @@ struct pTimer : public pObject {
CocoaTimer* cocoaTimer = nullptr;
void setEnabled(bool enabled);
void setInterval(unsigned milliseconds);
void setInterval(unsigned interval);
pTimer(Timer& timer) : pObject(timer), timer(timer) {}
void constructor();

View File

@ -4,7 +4,7 @@
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
canvas = &canvasReference;
[self setEditable:NO]; //disable image drag-and-drop functionality
NSTrackingArea *area = [[[NSTrackingArea alloc] initWithRect:[self frame]
NSTrackingArea* area = [[[NSTrackingArea alloc] initWithRect:[self frame]
options:NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect
owner:self userInfo:nil
] autorelease];
@ -25,7 +25,7 @@
}
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown {
if(auto &callback = isDown ? canvas->onMousePress : canvas->onMouseRelease) {
if(auto& callback = isDown ? canvas->onMousePress : canvas->onMouseRelease) {
switch([event buttonNumber]) {
case 0: return callback(phoenix::Mouse::Button::Left);
case 1: return callback(phoenix::Mouse::Button::Right);
@ -94,47 +94,40 @@ void pCanvas::setDroppable(bool droppable) {
}
}
void pCanvas::setSize(Size size) {
@autoreleasepool {
NSImage* image = [[[NSImage alloc] initWithSize:NSMakeSize(size.width, size.height)] autorelease];
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:nil
pixelsWide:size.width pixelsHigh:size.height
bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES
isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace
bitmapFormat:NSAlphaNonpremultipliedBitmapFormat
bytesPerRow:size.width * 4 bitsPerPixel:32
] autorelease];
void pCanvas::setGeometry(Geometry geometry) {
if(canvas.state.width == 0 || canvas.state.height == 0) rasterize();
[image addRepresentation:bitmap];
[cocoaView setImage:image];
unsigned width = canvas.state.width;
unsigned height = canvas.state.height;
if(width == 0) width = widget.state.geometry.width;
if(height == 0) height = widget.state.geometry.height;
if(width < geometry.width) {
geometry.x += (geometry.width - width) / 2;
geometry.width = width;
}
if(height < geometry.height) {
geometry.y += (geometry.height - height) / 2;
geometry.height = height;
}
pWidget::setGeometry(geometry);
}
void pCanvas::update() {
@autoreleasepool {
if(NSBitmapImageRep* bitmap = [[[cocoaView image] representations] objectAtIndex:0]) {
uint8_t* target = [bitmap bitmapData];
uint32_t* source = canvas.state.data;
void pCanvas::setMode(Canvas::Mode mode) {
rasterize(), redraw();
}
for(unsigned n = 0; n < canvas.state.width * canvas.state.height; n++) {
*target++ = *source >> 16;
*target++ = *source >> 8;
*target++ = *source >> 0;
*target++ = *source >> 24;
source++;
}
[cocoaView setNeedsDisplay:YES];
}
}
void pCanvas::setSize(Size size) {
rasterize(), redraw();
}
void pCanvas::constructor() {
@autoreleasepool {
cocoaView = cocoaCanvas = [[CocoaCanvas alloc] initWith:canvas];
setSize(canvas.size());
}
setSize(canvas.size());
}
void pCanvas::destructor() {
@ -143,4 +136,79 @@ void pCanvas::destructor() {
}
}
void pCanvas::rasterize() {
@autoreleasepool {
unsigned width = canvas.state.width;
unsigned height = canvas.state.height;
if(width == 0) width = widget.state.geometry.width;
if(height == 0) height = widget.state.geometry.height;
if(width != surfaceWidth || height != surfaceHeight) {
NSImage* image = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] autorelease];
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:nil
pixelsWide:width pixelsHigh:height
bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES
isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace
bitmapFormat:NSAlphaNonpremultipliedBitmapFormat
bytesPerRow:width * 4 bitsPerPixel:32
] autorelease];
[image addRepresentation:bitmap];
[cocoaView setImage:image];
surfaceWidth = width;
surfaceHeight = height;
}
if(NSBitmapImageRep* bitmap = [[[cocoaView image] representations] objectAtIndex:0]) {
uint32_t* target = (uint32_t*)[bitmap bitmapData];
if(canvas.state.mode == Canvas::Mode::Color) {
nall::image image;
image.allocate(width, height);
image.fill(canvas.state.color.argb());
memcpy(target, image.data, image.size);
}
if(canvas.state.mode == Canvas::Mode::Gradient) {
nall::image image;
image.allocate(width, height);
image.gradient(
canvas.state.gradient[0].argb(), canvas.state.gradient[1].argb(), canvas.state.gradient[2].argb(), canvas.state.gradient[3].argb()
);
memcpy(target, image.data, image.size);
}
if(canvas.state.mode == Canvas::Mode::Image) {
nall::image image = canvas.state.image;
image.scale(width, height);
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
memcpy(target, image.data, image.size);
}
if(canvas.state.mode == Canvas::Mode::Data) {
if(width == canvas.state.width && height == canvas.state.height) {
memcpy(target, canvas.state.data, width * height * sizeof(uint32_t));
} else {
memset(target, 0x00, width * height * sizeof(uint32_t));
}
}
//ARGB -> ABGR transformation
for(unsigned n = 0; n < width * height; n++) {
uint32_t color = *target;
color = (color & 0xff00ff00) | ((color & 0xff0000) >> 16) | ((color & 0x0000ff) << 16);
*target++ = color;
}
}
}
}
void pCanvas::redraw() {
@autoreleasepool {
[cocoaView setNeedsDisplay:YES];
}
}
}

View File

@ -24,14 +24,19 @@ namespace phoenix {
struct pCanvas : public pWidget {
Canvas& canvas;
CocoaCanvas* cocoaCanvas = nullptr;
unsigned surfaceWidth = 0;
unsigned surfaceHeight = 0;
void setDroppable(bool droppable);
void setGeometry(Geometry geometry);
void setMode(Canvas::Mode mode);
void setSize(Size size);
void update();
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
void constructor();
void destructor();
void rasterize();
void redraw();
};
}

View File

@ -6,7 +6,8 @@
[self setTarget:self];
[self setAction:@selector(activate:)];
[self setButtonType:NSSwitchButton];
[self setBezelStyle:NSRegularSquareBezelStyle];
[self setButtonType:NSOnOffButton];
}
return self;
}
@ -20,15 +21,20 @@
namespace phoenix {
bool pCheckButton::checked() {
@autoreleasepool {
return [cocoaView state] != NSOffState;
}
}
Size pCheckButton::minimumSize() {
Size size = Font::size(checkButton.font(), checkButton.state.text);
return {size.width + 20, size.height};
if(checkButton.state.orientation == Orientation::Horizontal) {
size.width += checkButton.state.image.width;
size.height = max(checkButton.state.image.height, size.height);
}
if(checkButton.state.orientation == Orientation::Vertical) {
size.width = max(checkButton.state.image.width, size.width);
size.height += checkButton.state.image.height;
}
return {size.width + 20, size.height + 4};
}
void pCheckButton::setChecked(bool checked) {
@ -39,11 +45,25 @@ void pCheckButton::setChecked(bool checked) {
void pCheckButton::setGeometry(Geometry geometry) {
pWidget::setGeometry({
geometry.x - 2, geometry.y,
geometry.width + 4, geometry.height
geometry.x - 2, geometry.y - 2,
geometry.width + 4, geometry.height + 4
});
}
void pCheckButton::setImage(const image& image, Orientation orientation) {
@autoreleasepool {
if(image.empty()) {
[cocoaView setImage:nil];
return;
}
[cocoaView setImage:NSMakeImage(image)];
if(orientation == Orientation::Horizontal) [cocoaView setImagePosition:NSImageLeft];
if(orientation == Orientation::Vertical ) [cocoaView setImagePosition:NSImageAbove];
}
}
void pCheckButton::setText(string text) {
@autoreleasepool {
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
@ -53,8 +73,6 @@ void pCheckButton::setText(string text) {
void pCheckButton::constructor() {
@autoreleasepool {
cocoaView = cocoaCheckButton = [[CocoaCheckButton alloc] initWith:checkButton];
setChecked(checkButton.state.checked);
setText(checkButton.state.text);
}
}

View File

@ -12,10 +12,10 @@ struct pCheckButton : public pWidget {
CheckButton& checkButton;
CocoaCheckButton* cocoaCheckButton = nullptr;
bool checked();
Size minimumSize();
void setChecked(bool checked);
void setGeometry(Geometry geometry);
void setImage(const image& image, Orientation orientation);
void setText(string text);
pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {}

View File

@ -0,0 +1,61 @@
@implementation CocoaCheckLabel : NSButton
-(id) initWith:(phoenix::CheckLabel&)checkLabelReference {
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
checkLabel = &checkLabelReference;
[self setTarget:self];
[self setAction:@selector(activate:)];
[self setButtonType:NSSwitchButton];
}
return self;
}
-(IBAction) activate:(id)sender {
checkLabel->state.checked = [self state] != NSOffState;
if(checkLabel->onToggle) checkLabel->onToggle();
}
@end
namespace phoenix {
Size pCheckLabel::minimumSize() {
Size size = Font::size(checkLabel.font(), checkLabel.state.text);
return {size.width + 20, size.height};
}
void pCheckLabel::setChecked(bool checked) {
@autoreleasepool {
[cocoaView setState:checked ? NSOnState : NSOffState];
}
}
void pCheckLabel::setGeometry(Geometry geometry) {
pWidget::setGeometry({
geometry.x - 2, geometry.y,
geometry.width + 4, geometry.height
});
}
void pCheckLabel::setText(string text) {
@autoreleasepool {
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
}
}
void pCheckLabel::constructor() {
@autoreleasepool {
cocoaView = cocoaCheckLabel = [[CocoaCheckLabel alloc] initWith:checkLabel];
setChecked(checkLabel.state.checked);
setText(checkLabel.state.text);
}
}
void pCheckLabel::destructor() {
@autoreleasepool {
[cocoaView release];
}
}
}

View File

@ -0,0 +1,25 @@
@interface CocoaCheckLabel : NSButton {
@public
phoenix::CheckLabel* checkLabel;
}
-(id) initWith:(phoenix::CheckLabel&)checkLabel;
-(IBAction) activate:(id)sender;
@end
namespace phoenix {
struct pCheckLabel : public pWidget {
CheckLabel& checkLabel;
CocoaCheckLabel* cocoaCheckLabel = nullptr;
Size minimumSize();
void setChecked(bool checked);
void setGeometry(Geometry geometry);
void setText(string text);
pCheckLabel(CheckLabel& checkLabel) : pWidget(checkLabel), checkLabel(checkLabel) {}
void constructor();
void destructor();
};
}

View File

@ -11,6 +11,7 @@
}
-(IBAction) activate:(id)sender {
comboButton->state.selection = [self indexOfSelectedItem];
if(comboButton->onChange) comboButton->onChange();
}
@ -31,15 +32,9 @@ Size pComboButton::minimumSize() {
return {maximumWidth + 36, size.height + 6};
}
void pComboButton::modify(unsigned row, string text) {
void pComboButton::remove(unsigned selection) {
@autoreleasepool {
[[cocoaView itemAtIndex:row] setTitle:[NSString stringWithUTF8String:text]];
}
}
void pComboButton::remove(unsigned row) {
@autoreleasepool {
[cocoaView removeItemAtIndex:row];
[cocoaView removeItemAtIndex:selection];
}
}
@ -49,12 +44,6 @@ void pComboButton::reset() {
}
}
unsigned pComboButton::selection() {
@autoreleasepool {
return [cocoaView indexOfSelectedItem];
}
}
void pComboButton::setGeometry(Geometry geometry) {
pWidget::setGeometry({
geometry.x - 2, geometry.y,
@ -62,9 +51,15 @@ void pComboButton::setGeometry(Geometry geometry) {
});
}
void pComboButton::setSelection(unsigned row) {
void pComboButton::setSelection(unsigned selection) {
@autoreleasepool {
[cocoaView selectItemAtIndex:row];
[cocoaView selectItemAtIndex:selection];
}
}
void pComboButton::setText(unsigned selection, string text) {
@autoreleasepool {
[[cocoaView itemAtIndex:selection] setTitle:[NSString stringWithUTF8String:text]];
}
}

View File

@ -14,12 +14,11 @@ struct pComboButton : public pWidget {
void append(string text);
Size minimumSize();
void modify(unsigned row, string text);
void remove(unsigned row);
void remove(unsigned selection);
void reset();
unsigned selection();
void setGeometry(Geometry geometry);
void setSelection(unsigned row);
void setSelection(unsigned selection);
void setText(unsigned selection, string text);
pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {}
void constructor();

View File

@ -0,0 +1,68 @@
@implementation CocoaFrame : NSBox
-(id) initWith:(phoenix::Frame&)frameReference {
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
frame = &frameReference;
[self setTitle:@""];
}
return self;
}
@end
namespace phoenix {
void pFrame::setEnabled(bool enabled) {
if(frame.state.layout) frame.state.layout->setEnabled(frame.state.layout->enabled());
pWidget::setEnabled(enabled);
}
void pFrame::setFont(string font) {
@autoreleasepool {
[cocoaView setTitleFont:pFont::cocoaFont(font)];
}
}
void pFrame::setGeometry(Geometry geometry) {
bool empty = frame.state.text.empty();
Size size = Font::size(frame.font(), frame.state.text);
pWidget::setGeometry({
geometry.x - 3, geometry.y - (empty ? size.height - 2 : 1),
geometry.width + 6, geometry.height + (empty ? size.height + 2 : 5)
});
if(frame.state.layout == nullptr) return;
geometry.x += 1, geometry.y += (empty ? 1 : size.height - 2);
geometry.width -= 2, geometry.height -= (empty ? 1 : size.height - 1);
frame.state.layout->setGeometry(geometry);
}
void pFrame::setText(string text) {
@autoreleasepool {
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
}
}
void pFrame::setVisible(bool visible) {
if(frame.state.layout) frame.state.layout->setVisible(frame.state.layout->visible());
pWidget::setVisible(visible);
}
void pFrame::constructor() {
@autoreleasepool {
cocoaView = cocoaFrame = [[CocoaFrame alloc] initWith:frame];
}
}
void pFrame::destructor() {
@autoreleasepool {
[cocoaView release];
}
}
void pFrame::orphan() {
destructor();
constructor();
}
}

View File

@ -0,0 +1,26 @@
@interface CocoaFrame : NSBox {
@public
phoenix::Frame* frame;
}
-(id) initWith:(phoenix::Frame&)frame;
@end
namespace phoenix {
struct pFrame : public pWidget {
Frame& frame;
CocoaFrame* cocoaFrame = nullptr;
void setEnabled(bool enabled);
void setFont(string font);
void setGeometry(Geometry geometry);
void setText(string text);
void setVisible(bool visible);
pFrame(Frame& frame) : pWidget(frame), frame(frame) {}
void constructor();
void destructor();
void orphan();
};
}

View File

@ -58,12 +58,6 @@ Size pHorizontalScroller::minimumSize() {
}
}
unsigned pHorizontalScroller::position() {
@autoreleasepool {
return [cocoaView doubleValue] * horizontalScroller.state.length;
}
}
void pHorizontalScroller::setLength(unsigned length) {
@autoreleasepool {
[cocoaView update];

View File

@ -14,7 +14,6 @@ struct pHorizontalScroller : public pWidget {
CocoaHorizontalScroller* cocoaHorizontalScroller = nullptr;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);

View File

@ -24,12 +24,6 @@ Size pHorizontalSlider::minimumSize() {
return {48, 20};
}
unsigned pHorizontalSlider::position() {
@autoreleasepool {
return [cocoaView doubleValue];
}
}
void pHorizontalSlider::setGeometry(Geometry geometry) {
pWidget::setGeometry({
geometry.x - 2, geometry.y,

View File

@ -13,7 +13,6 @@ struct pHorizontalSlider : public pWidget {
CocoaHorizontalSlider* cocoaHorizontalSlider = nullptr;
Size minimumSize();
unsigned position();
void setGeometry(Geometry geometry);
void setLength(unsigned length);
void setPosition(unsigned position);

View File

@ -134,6 +134,8 @@
}
-(void) tableViewSelectionDidChange:(NSNotification*)notification {
listView->state.selected = true;
listView->state.selection = [content selectedRow];
if(listView->onChange) listView->onChange();
}
@ -178,14 +180,13 @@
unsigned textDisplacement = 0;
if(image) {
NSGraphicsContext* context = [NSGraphicsContext currentContext];
[context saveGraphicsState];
[[NSGraphicsContext currentContext] saveGraphicsState];
NSRect targetRect = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.height, frame.size.height);
NSRect sourceRect = NSMakeRect(0, 0, [image size].width, [image size].height);
[image drawInRect:targetRect fromRect:sourceRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil];
[context restoreGraphicsState];
[[NSGraphicsContext currentContext] restoreGraphicsState];
textDisplacement = frame.size.height + 2;
}
@ -237,17 +238,7 @@ void pListView::autoSizeColumns() {
}
}
bool pListView::checked(unsigned row) {
return listView.state.checked(row);
}
void pListView::modify(unsigned row, const lstring& text) {
@autoreleasepool {
[[cocoaView content] reloadData];
}
}
void pListView::remove(unsigned row) {
void pListView::remove(unsigned selection) {
@autoreleasepool {
[[cocoaView content] reloadData];
}
@ -259,27 +250,13 @@ void pListView::reset() {
}
}
bool pListView::selected() {
@autoreleasepool {
return [[cocoaView content] selectedRow] >= 0;
}
}
unsigned pListView::selection() {
if(selected() == false) return 0;
@autoreleasepool {
return [[cocoaView content] selectedRow];
}
}
void pListView::setCheckable(bool checkable) {
@autoreleasepool {
[cocoaView reloadColumns];
}
}
void pListView::setChecked(unsigned row, bool checked) {
void pListView::setChecked(unsigned selection, bool checked) {
@autoreleasepool {
[[cocoaView content] reloadData];
}
@ -307,7 +284,7 @@ void pListView::setHeaderVisible(bool visible) {
}
}
void pListView::setImage(unsigned row, unsigned column, const image& image) {
void pListView::setImage(unsigned selection, unsigned position, const image& image) {
@autoreleasepool {
[[cocoaView content] reloadData];
}
@ -321,9 +298,15 @@ void pListView::setSelected(bool selected) {
}
}
void pListView::setSelection(unsigned row) {
void pListView::setSelection(unsigned selection) {
@autoreleasepool {
[[cocoaView content] selectRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row, 1)] byExtendingSelection:NO];
[[cocoaView content] selectRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(selection, 1)] byExtendingSelection:NO];
}
}
void pListView::setText(unsigned selection, unsigned position, const string text) {
@autoreleasepool {
[[cocoaView content] reloadData];
}
}

View File

@ -42,20 +42,17 @@ struct pListView : public pWidget {
void append(const lstring& text);
void autoSizeColumns();
bool checked(unsigned row);
void modify(unsigned row, const lstring& text);
void remove(unsigned row);
void remove(unsigned selection);
void reset();
bool selected();
unsigned selection();
void setCheckable(bool checkable);
void setChecked(unsigned row, bool checked);
void setChecked(unsigned selection, bool checked);
void setFont(string font);
void setHeaderText(const lstring& text);
void setHeaderVisible(bool visible);
void setImage(unsigned row, unsigned column, const image& image);
void setImage(unsigned selection, unsigned position, const image& image);
void setSelected(bool selected);
void setSelection(unsigned row);
void setSelection(unsigned selection);
void setText(unsigned selection, unsigned position, string text);
pListView(ListView& listView) : pWidget(listView), listView(listView) {}
void constructor();

View File

@ -6,29 +6,38 @@
[self setTarget:self];
[self setAction:@selector(activate:)];
[self setButtonType:NSRadioButton];
[self setBezelStyle:NSRegularSquareBezelStyle];
[self setButtonType:NSOnOffButton];
}
return self;
}
-(IBAction) activate:(id)sender {
bool wasChecked = radioButton->state.checked;
radioButton->setChecked();
if(radioButton->onActivate) radioButton->onActivate();
if(wasChecked == false) {
if(radioButton->onActivate) radioButton->onActivate();
}
}
@end
namespace phoenix {
bool pRadioButton::checked() {
@autoreleasepool {
return [cocoaView state] != NSOffState;
}
}
Size pRadioButton::minimumSize() {
Size size = Font::size(radioButton.font(), radioButton.state.text);
return {size.width + 22, size.height};
if(radioButton.state.orientation == Orientation::Horizontal) {
size.width += radioButton.state.image.width;
size.height = max(radioButton.state.image.height, size.height);
}
if(radioButton.state.orientation == Orientation::Vertical) {
size.width = max(radioButton.state.image.width, size.width);
size.height += radioButton.state.image.height;
}
return {size.width + 20, size.height + 4};
}
void pRadioButton::setChecked() {
@ -42,14 +51,28 @@ void pRadioButton::setChecked() {
void pRadioButton::setGeometry(Geometry geometry) {
pWidget::setGeometry({
geometry.x - 1, geometry.y,
geometry.width + 2, geometry.height
geometry.x - 2, geometry.y - 2,
geometry.width + 4, geometry.height + 4
});
}
void pRadioButton::setGroup(const group<RadioButton>& group) {
}
void pRadioButton::setImage(const image& image, Orientation orientation) {
@autoreleasepool {
if(image.empty()) {
[cocoaView setImage:nil];
return;
}
[cocoaView setImage:NSMakeImage(image)];
if(orientation == Orientation::Horizontal) [cocoaView setImagePosition:NSImageLeft];
if(orientation == Orientation::Vertical ) [cocoaView setImagePosition:NSImageAbove];
}
}
void pRadioButton::setText(string text) {
@autoreleasepool {
[cocoaView setTitle:[NSString stringWithUTF8String:text]];

View File

@ -12,11 +12,11 @@ struct pRadioButton : public pWidget {
RadioButton& radioButton;
CocoaRadioButton* cocoaRadioButton = nullptr;
bool checked();
Size minimumSize();
void setChecked();
void setGeometry(Geometry geometry);
void setGroup(const group<RadioButton>& group);
void setImage(const image& image, Orientation orientation);
void setText(string text);
pRadioButton(RadioButton& radioButton) : pWidget(radioButton), radioButton(radioButton) {}

View File

@ -0,0 +1,65 @@
@implementation CocoaRadioLabel : NSButton
-(id) initWith:(phoenix::RadioLabel&)radioLabelReference {
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
radioLabel = &radioLabelReference;
[self setTarget:self];
[self setAction:@selector(activate:)];
[self setButtonType:NSRadioButton];
}
return self;
}
-(IBAction) activate:(id)sender {
radioLabel->setChecked();
if(radioLabel->onActivate) radioLabel->onActivate();
}
@end
namespace phoenix {
Size pRadioLabel::minimumSize() {
Size size = Font::size(radioLabel.font(), radioLabel.state.text);
return {size.width + 22, size.height};
}
void pRadioLabel::setChecked() {
@autoreleasepool {
for(auto& item : radioLabel.state.group) {
auto state = (&item == &radioLabel) ? NSOnState : NSOffState;
[item.p.cocoaView setState:state];
}
}
}
void pRadioLabel::setGeometry(Geometry geometry) {
pWidget::setGeometry({
geometry.x - 1, geometry.y,
geometry.width + 2, geometry.height
});
}
void pRadioLabel::setGroup(const group<RadioLabel>& group) {
}
void pRadioLabel::setText(string text) {
@autoreleasepool {
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
}
}
void pRadioLabel::constructor() {
@autoreleasepool {
cocoaView = cocoaRadioLabel = [[CocoaRadioLabel alloc] initWith:radioLabel];
}
}
void pRadioLabel::destructor() {
@autoreleasepool {
[cocoaView release];
}
}
}

View File

@ -0,0 +1,26 @@
@interface CocoaRadioLabel : NSButton {
@public
phoenix::RadioLabel* radioLabel;
}
-(id) initWith:(phoenix::RadioLabel&)radioLabel;
-(IBAction) activate:(id)sender;
@end
namespace phoenix {
struct pRadioLabel : public pWidget {
RadioLabel& radioLabel;
CocoaRadioLabel* cocoaRadioLabel = nullptr;
Size minimumSize();
void setChecked();
void setGeometry(Geometry geometry);
void setGroup(const group<RadioLabel>& group);
void setText(string text);
pRadioLabel(RadioLabel& radioLabel) : pWidget(radioLabel), radioLabel(radioLabel) {}
void constructor();
void destructor();
};
}

View File

@ -0,0 +1,145 @@
@implementation CocoaTabFrame : NSTabView
-(id) initWith:(phoenix::TabFrame&)tabFrameReference {
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
tabFrame = &tabFrameReference;
[self setDelegate:self];
}
return self;
}
-(void) tabView:(NSTabView*)tabView didSelectTabViewItem:(NSTabViewItem*)tabViewItem {
tabFrame->state.selection = [tabView indexOfTabViewItem:tabViewItem];
tabFrame->p.synchronizeLayout();
if(tabFrame->onChange) tabFrame->onChange();
}
@end
@implementation CocoaTabFrameItem : NSTabViewItem
-(id) initWith:(phoenix::TabFrame&)tabFrameReference {
if(self = [super initWithIdentifier:nil]) {
tabFrame = &tabFrameReference;
cocoaTabFrame = tabFrame->p.cocoaTabFrame;
}
return self;
}
-(NSSize) sizeOfLabel:(BOOL)shouldTruncateLabel {
NSSize sizeOfLabel = [super sizeOfLabel:shouldTruncateLabel];
signed selection = [cocoaTabFrame indexOfTabViewItem:self];
if(selection < 0) return sizeOfLabel; //should never happen
if(tabFrame->state.image[selection].empty() == false) {
unsigned iconSize = phoenix::Font::size(tabFrame->font(), " ").height;
sizeOfLabel.width += iconSize + 2;
}
return sizeOfLabel;
}
-(void) drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)tabRect {
signed selection = [cocoaTabFrame indexOfTabViewItem:self];
if(selection >= 0 && tabFrame->state.image[selection].empty() == false) {
unsigned iconSize = phoenix::Font::size(tabFrame->font(), " ").height;
NSImage* image = NSMakeImage(tabFrame->state.image[selection]);
[[NSGraphicsContext currentContext] saveGraphicsState];
NSRect targetRect = NSMakeRect(tabRect.origin.x, tabRect.origin.y + 2, iconSize, iconSize);
[image drawInRect:targetRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil];
[[NSGraphicsContext currentContext] restoreGraphicsState];
tabRect.origin.x += iconSize + 2;
tabRect.size.width -= iconSize + 2;
}
[super drawLabel:shouldTruncateLabel inRect:tabRect];
}
@end
namespace phoenix {
void pTabFrame::append(string text, const image& image) {
@autoreleasepool {
CocoaTabFrameItem* item = [[CocoaTabFrameItem alloc] initWith:tabFrame];
[item setLabel:[NSString stringWithUTF8String:text]];
[cocoaView addTabViewItem:item];
tabs.append(item);
}
}
void pTabFrame::remove(unsigned selection) {
@autoreleasepool {
CocoaTabFrameItem* item = tabs[selection];
[cocoaView removeTabViewItem:item];
tabs.remove(selection);
}
}
void pTabFrame::setEnabled(bool enabled) {
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setEnabled(layout->enabled());
}
pWidget::setEnabled(enabled);
}
void pTabFrame::setGeometry(Geometry geometry) {
pWidget::setGeometry({
geometry.x - 7, geometry.y - 5,
geometry.width + 14, geometry.height + 6
});
geometry.x += 1, geometry.width -= 2;
geometry.y += 22, geometry.height -= 32;
for(auto& layout : tabFrame.state.layout) {
if(layout == nullptr) continue;
layout->setGeometry(geometry);
}
synchronizeLayout();
}
void pTabFrame::setImage(unsigned selection, const image& image) {
}
void pTabFrame::setSelection(unsigned selection) {
@autoreleasepool {
CocoaTabFrameItem* item = tabs[selection];
[cocoaView selectTabViewItem:item];
}
synchronizeLayout();
}
void pTabFrame::setText(unsigned selection, string text) {
@autoreleasepool {
CocoaTabFrameItem* item = tabs[selection];
[item setLabel:[NSString stringWithUTF8String:text]];
}
}
void pTabFrame::setVisible(bool visible) {
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setVisible(layout->visible());
}
pWidget::setVisible(visible);
}
void pTabFrame::constructor() {
@autoreleasepool {
cocoaView = cocoaTabFrame = [[CocoaTabFrame alloc] initWith:tabFrame];
}
}
void pTabFrame::destructor() {
@autoreleasepool {
[cocoaView release];
}
}
void pTabFrame::synchronizeLayout() {
unsigned selection = 0;
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setVisible(selection == tabFrame.state.selection);
selection++;
}
}
}

View File

@ -0,0 +1,41 @@
@interface CocoaTabFrame : NSTabView <NSTabViewDelegate> {
@public
phoenix::TabFrame* tabFrame;
}
-(id) initWith:(phoenix::TabFrame&)tabFrame;
-(void) tabView:(NSTabView*)tabView didSelectTabViewItem:(NSTabViewItem*)tabViewItem;
@end
@interface CocoaTabFrameItem : NSTabViewItem {
@public
phoenix::TabFrame* tabFrame;
CocoaTabFrame* cocoaTabFrame;
}
-(id) initWith:(phoenix::TabFrame&)tabFrame;
-(NSSize) sizeOfLabel:(BOOL)shouldTruncateLabel;
-(void) drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)tabRect;
@end
namespace phoenix {
struct pTabFrame : public pWidget {
TabFrame& tabFrame;
CocoaTabFrame* cocoaTabFrame = nullptr;
vector<CocoaTabFrameItem*> tabs;
void append(string text, const image& image);
void remove(unsigned selection);
void setEnabled(bool enabled);
void setGeometry(Geometry geometry);
void setImage(unsigned selection, const image& image);
void setSelection(unsigned selection);
void setText(unsigned selection, string text);
void setVisible(bool visible);
pTabFrame(TabFrame& tabFrame) : pWidget(tabFrame), tabFrame(tabFrame) {}
void constructor();
void destructor();
void synchronizeLayout();
};
}

View File

@ -58,12 +58,6 @@ Size pVerticalScroller::minimumSize() {
}
}
unsigned pVerticalScroller::position() {
@autoreleasepool {
return [cocoaView doubleValue] * verticalScroller.state.length;
}
}
void pVerticalScroller::setLength(unsigned length) {
@autoreleasepool {
[cocoaView update];

View File

@ -14,7 +14,6 @@ struct pVerticalScroller : public pWidget {
CocoaVerticalScroller* cocoaVerticalScroller = nullptr;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);

View File

@ -24,12 +24,6 @@ Size pVerticalSlider::minimumSize() {
return {20, 48};
}
unsigned pVerticalSlider::position() {
@autoreleasepool {
return [cocoaView doubleValue];
}
}
void pVerticalSlider::setGeometry(Geometry geometry) {
pWidget::setGeometry({
geometry.x, geometry.y - 2,

View File

@ -13,7 +13,6 @@ struct pVerticalSlider : public pWidget {
CocoaVerticalSlider* cocoaVerticalSlider = nullptr;
Size minimumSize();
unsigned position();
void setGeometry(Geometry geometry);
void setLength(unsigned length);
void setPosition(unsigned position);

View File

@ -17,8 +17,9 @@ Size pWidget::minimumSize() {
}
void pWidget::setEnabled(bool enabled) {
if(!widget.parent()) enabled = false;
if(widget.state.abstract) enabled = false;
if(sizable.state.layout && sizable.state.layout->enabled() == false) enabled = false;
if(!widget.enabledToAll()) enabled = false;
@autoreleasepool {
if([cocoaView respondsToSelector:@selector(setEnabled:)]) {
@ -47,11 +48,13 @@ void pWidget::setGeometry(Geometry geometry) {
[cocoaView setFrame:NSMakeRect(geometry.x, windowHeight - geometry.y - geometry.height, geometry.width, geometry.height)];
[[cocoaView superview] setNeedsDisplay:YES];
}
if(widget.onSize) widget.onSize();
}
void pWidget::setVisible(bool visible) {
if(!widget.parent()) visible = false;
if(widget.state.abstract) visible = false;
if(sizable.state.layout && sizable.state.layout->visible() == false) visible = false;
if(!widget.visibleToAll()) visible = false;
@autoreleasepool {
[cocoaView setHidden:!visible];

View File

@ -7,11 +7,11 @@ struct pWidget : public pSizable {
bool enabled();
bool focused();
virtual Size minimumSize();
void setEnabled(bool enabled);
virtual void setEnabled(bool enabled);
void setFocused();
virtual void setFont(string font);
virtual void setGeometry(Geometry geometry);
void setVisible(bool visible);
virtual void setVisible(bool visible);
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
void constructor();

View File

@ -170,24 +170,12 @@ void pWindow::append(Widget& widget) {
@autoreleasepool {
[widget.p.cocoaView removeFromSuperview];
[[cocoaWindow contentView] addSubview:widget.p.cocoaView positioned:NSWindowBelow relativeTo:nil];
[[cocoaWindow contentView] addSubview:widget.p.cocoaView positioned:NSWindowAbove relativeTo:nil];
widget.p.setGeometry(widget.geometry());
[[cocoaWindow contentView] setNeedsDisplay:YES];
}
}
Color pWindow::backgroundColor() {
@autoreleasepool {
NSColor* color = [[cocoaWindow backgroundColor] colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
return {
uint8_t(255 * [color redComponent]),
uint8_t(255 * [color greenComponent]),
uint8_t(255 * [color blueComponent]),
uint8_t(255 * [color alphaComponent])
};
}
}
bool pWindow::focused() {
@autoreleasepool {
return [cocoaWindow isMainWindow] == YES;
@ -362,6 +350,14 @@ void pWindow::setWidgetFont(string font) {
void pWindow::constructor() {
@autoreleasepool {
cocoaWindow = [[CocoaWindow alloc] initWith:window];
NSColor* color = [[cocoaWindow backgroundColor] colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
window.state.backgroundColor = Color(
(uint8_t)(255 * [color redComponent]),
(uint8_t)(255 * [color greenComponent]),
(uint8_t)(255 * [color blueComponent]),
(uint8_t)(255 * [color alphaComponent])
);
}
}

View File

@ -32,7 +32,6 @@ struct pWindow : public pObject {
void append(Layout& layout);
void append(Menu& menu);
void append(Widget& widget);
Color backgroundColor();
bool focused();
Geometry frameMargin();
Geometry geometry();

File diff suppressed because it is too large Load Diff

View File

@ -37,8 +37,10 @@ struct pWidget;
struct pButton;
struct pCanvas;
struct pCheckButton;
struct pCheckLabel;
struct pComboButton;
struct pConsole;
struct pFrame;
struct pHexEdit;
struct pHorizontalScroller;
struct pHorizontalSlider;
@ -47,6 +49,8 @@ struct pLineEdit;
struct pListView;
struct pProgressBar;
struct pRadioButton;
struct pRadioLabel;
struct pTabFrame;
struct pTextEdit;
struct pVerticalScroller;
struct pVerticalSlider;
@ -59,7 +63,7 @@ struct Application {
static bool pendingEvents();
static void processEvents();
static void quit();
static void setName(nall::string name);
static void setName(const nall::string& name);
Application() = delete;
struct State;
@ -78,17 +82,13 @@ struct Application {
};
};
enum : unsigned {
MaximumSize = ~0u,
MinimumSize = 0u,
};
struct Color {
uint8_t red, green, blue, alpha;
uint32_t rgb() const;
uint32_t rgba() const;
inline Color() : red(0), green(0), blue(0), alpha(255) {}
inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255) : red(red), green(green), blue(blue), alpha(alpha) {}
uint32_t argb() const;
inline Color() : alpha(255), red(0), green(0), blue(0) {}
inline Color(uint8_t red, uint8_t green, uint8_t blue) : alpha(255), red(red), green(green), blue(blue) {}
inline Color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue) : alpha(alpha), red(red), green(green), blue(blue) {}
};
struct Position {
@ -98,6 +98,9 @@ struct Position {
};
struct Size {
static const unsigned Maximum = ~0u;
static const unsigned Minimum = 0u;
unsigned width, height;
inline Size() : width(0), height(0) {}
template<typename W, typename H> inline Size(W width, H height) : width(width), height(height) {}
@ -112,16 +115,16 @@ struct Geometry {
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(Position position, Size size) : x(position.x), y(position.y), width(size.width), height(size.height) {}
template<typename X, typename Y, typename W, typename H> inline Geometry(X x, Y y, W width, H height) : x(x), y(y), width(width), height(height) {}
Geometry(nall::string text);
Geometry(const nall::string& text);
};
enum class Orientation : unsigned { Horizontal, Vertical };
struct Font {
static nall::string serif(unsigned size = 0, nall::string style = "");
static nall::string sans(unsigned size = 0, nall::string style = "");
static nall::string monospace(unsigned size = 0, nall::string style = "");
static Size size(nall::string font, nall::string text);
static nall::string serif(unsigned size = 0, const nall::string& style = "");
static nall::string sans(unsigned size = 0, const nall::string& style = "");
static nall::string monospace(unsigned size = 0, const nall::string& style = "");
static Size size(const nall::string& font, const nall::string& text);
Font() = delete;
};
@ -148,15 +151,13 @@ struct Mouse {
};
struct BrowserWindow {
template<typename... Args> BrowserWindow& setFilters(Args&&... args) { return setFilters_({args...}); }
nall::string directory();
nall::string open();
nall::string save();
BrowserWindow& setFilters_(const nall::lstring& filters);
BrowserWindow& setFilters(const nall::lstring& filters);
BrowserWindow& setParent(Window& parent);
BrowserWindow& setPath(nall::string path);
BrowserWindow& setTitle(nall::string title);
BrowserWindow& setPath(const nall::string& path);
BrowserWindow& setTitle(const nall::string& title);
BrowserWindow();
~BrowserWindow();
@ -183,11 +184,11 @@ struct MessageWindow {
Response information(Buttons = Buttons::Ok);
Response question(Buttons = Buttons::YesNo);
MessageWindow& setParent(Window& parent);
MessageWindow& setText(nall::string text);
MessageWindow& setTitle(nall::string title);
MessageWindow& setText(const nall::string& text);
MessageWindow& setTitle(const nall::string& title);
Response warning(Buttons = Buttons::Ok);
MessageWindow(nall::string text = "");
MessageWindow(const nall::string& text = "");
~MessageWindow();
struct State;
State& state;
@ -204,8 +205,10 @@ struct Object {
struct Timer : private nall::base_from_member<pTimer&>, Object {
nall::function<void ()> onActivate;
bool enabled() const;
unsigned interval() const;
void setEnabled(bool enabled = true);
void setInterval(unsigned milliseconds);
void setInterval(unsigned interval); //in milliseconds
Timer();
~Timer();
@ -222,45 +225,47 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
nall::function<void ()> onMove;
nall::function<void ()> onSize;
static Window& none();
inline void append() {}
inline void remove() {}
template<typename T, typename... Args> void append(T& arg, Args&&... args) { append_(arg); append(args...); }
template<typename T, typename... Args> void remove(T& arg, Args&&... args) { remove_(arg); remove(args...); }
void append_(Layout& layout);
void append_(Menu& menu);
void append_(Widget& widget);
Color backgroundColor();
void append(Layout& layout);
void append(Menu& menu);
void append(Widget& widget);
Color backgroundColor() const;
bool droppable() const;
Geometry frameGeometry();
Geometry frameMargin();
bool focused();
bool fullScreen();
bool fullScreen() const;
Geometry geometry();
void remove_(Layout& layout);
void remove_(Menu& menu);
void remove_(Widget& widget);
nall::string menuFont() const;
bool menuVisible() const;
bool modal() const;
void remove(Layout& layout);
void remove(Menu& menu);
void remove(Widget& widget);
bool resizable() const;
void setBackgroundColor(Color color);
void setDroppable(bool droppable = true);
void setFrameGeometry(Geometry geometry);
void setFocused();
void setFullScreen(bool fullScreen = true);
void setGeometry(Geometry geometry);
void setMenuFont(nall::string font);
void setMenuFont(const nall::string& font);
void setMenuVisible(bool visible = true);
void setModal(bool modal = true);
void setResizable(bool resizable = true);
void setSmartGeometry(Geometry geometry);
void setStatusFont(nall::string font);
void setStatusText(nall::string text);
void setStatusFont(const nall::string& font);
void setStatusText(const nall::string& text);
void setStatusVisible(bool visible = true);
void setTitle(nall::string text);
void setTitle(const nall::string& text);
void setVisible(bool visible = true);
void setWidgetFont(nall::string font);
nall::string statusText();
void setWidgetFont(const nall::string& font);
void setWindowGeometry(Geometry geometry);
nall::string statusFont() const;
nall::string statusText() const;
bool statusVisible() const;
void synchronizeLayout();
bool visible();
nall::string title() const;
bool visible() const;
nall::string widgetFont() const;
Window();
~Window();
@ -270,10 +275,10 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
};
struct Action : Object {
bool enabled();
bool enabled() const;
void setEnabled(bool enabled = true);
void setVisible(bool visible = true);
bool visible();
bool visible() const;
Action(pAction& p);
~Action();
@ -283,13 +288,12 @@ struct Action : Object {
};
struct Menu : private nall::base_from_member<pMenu&>, Action {
template<typename... Args> void append(Args&&... args) { append({std::forward<Args>(args)...}); }
template<typename... Args> void remove(Args&&... args) { remove({std::forward<Args>(args)...}); }
void append(const nall::group<Action>& list);
nall::image image() const;
void remove(const nall::group<Action>& list);
void setImage(const nall::image& image = nall::image{});
void setText(nall::string text);
void setText(const nall::string& text);
nall::string text() const;
Menu();
~Menu();
@ -307,8 +311,10 @@ struct Separator : private nall::base_from_member<pSeparator&>, Action {
struct Item : private nall::base_from_member<pItem&>, Action {
nall::function<void ()> onActivate;
nall::image image() const;
void setImage(const nall::image& image = nall::image{});
void setText(nall::string text);
void setText(const nall::string& text);
nall::string text() const;
Item();
~Item();
@ -320,9 +326,10 @@ struct Item : private nall::base_from_member<pItem&>, Action {
struct CheckItem : private nall::base_from_member<pCheckItem&>, Action {
nall::function<void ()> onToggle;
bool checked();
bool checked() const;
void setChecked(bool checked = true);
void setText(nall::string text);
void setText(const nall::string& text);
nall::string text() const;
CheckItem();
~CheckItem();
@ -337,10 +344,10 @@ struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
nall::function<void ()> onActivate;
bool checked();
bool checked() const;
void setChecked();
void setText(nall::string text);
nall::string text();
void setText(const nall::string& text);
nall::string text() const;
RadioItem();
~RadioItem();
@ -350,14 +357,18 @@ struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
};
struct Sizable : Object {
virtual bool enabled() = 0;
Layout* layout();
bool enabled() const;
bool enabledToAll() const;
Layout* layout() const;
virtual Size minimumSize() = 0;
Sizable* parent() const;
virtual void setEnabled(bool enabled = true) = 0;
virtual void setGeometry(Geometry geometry) = 0;
virtual void setVisible(bool visible = true) = 0;
virtual bool visible() = 0;
Window* window();
virtual void synchronizeLayout() = 0;
bool visible() const;
bool visibleToAll() const;
Window* window() const;
Sizable(pSizable& p);
~Sizable();
@ -369,8 +380,7 @@ struct Sizable : Object {
struct Layout : private nall::base_from_member<pLayout&>, Sizable {
virtual void append(Sizable& sizable);
virtual void remove(Sizable& sizable);
virtual void reset() {}
virtual void synchronizeLayout() = 0;
virtual void reset();
Layout();
Layout(pLayout& p);
@ -381,17 +391,18 @@ struct Layout : private nall::base_from_member<pLayout&>, Sizable {
};
struct Widget : private nall::base_from_member<pWidget&>, Sizable {
bool enabled();
nall::function<void ()> onSize;
bool focused();
nall::string font();
Geometry geometry();
nall::string font() const;
Geometry geometry() const;
Size minimumSize();
void setEnabled(bool enabled = true);
void setFocused();
void setFont(nall::string font);
void setFont(const nall::string& font);
void setGeometry(Geometry geometry);
void setVisible(bool visible = true);
bool visible();
void synchronizeLayout();
Widget();
Widget(pWidget& p);
@ -404,8 +415,11 @@ struct Widget : private nall::base_from_member<pWidget&>, Sizable {
struct Button : private nall::base_from_member<pButton&>, Widget {
nall::function<void ()> onActivate;
void setImage(const nall::image& image = nall::image{}, Orientation = Orientation::Horizontal);
void setText(nall::string text);
nall::image image() const;
Orientation orientation() const;
void setImage(const nall::image& image = nall::image{}, Orientation orientation = Orientation::Horizontal);
void setText(const nall::string& text);
nall::string text() const;
Button();
~Button();
@ -415,18 +429,30 @@ struct Button : private nall::base_from_member<pButton&>, Widget {
};
struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
enum class Mode : unsigned { Color, Gradient, Image, Data };
nall::function<void (nall::lstring)> onDrop;
nall::function<void ()> onMouseLeave;
nall::function<void (Position)> onMouseMove;
nall::function<void (Mouse::Button)> onMousePress;
nall::function<void (Mouse::Button)> onMouseRelease;
uint32_t* data();
Color color() const;
uint32_t* data() const;
bool droppable() const;
nall::vector<Color> gradient() const;
nall::image image() const;
Mode mode() const;
void setColor(Color color);
void setData();
void setDroppable(bool droppable = true);
bool setImage(const nall::image& image);
void setHorizontalGradient(Color left, Color right);
void setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight);
void setImage(const nall::image& image);
void setMode(Mode mode);
void setSize(Size size);
Size size();
void update();
void setVerticalGradient(Color top, Color bottom);
Size size() const;
Canvas();
~Canvas();
@ -438,9 +464,12 @@ struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
struct CheckButton : private nall::base_from_member<pCheckButton&>, Widget {
nall::function<void ()> onToggle;
bool checked();
bool checked() const;
nall::image image() const;
void setChecked(bool checked = true);
void setText(nall::string text);
void setImage(const nall::image& image = nall::image{}, Orientation orientation = Orientation::Horizontal);
void setText(const nall::string& text);
nall::string text() const;
CheckButton();
~CheckButton();
@ -449,19 +478,33 @@ struct CheckButton : private nall::base_from_member<pCheckButton&>, Widget {
pCheckButton& p;
};
struct CheckLabel : private nall::base_from_member<pCheckLabel&>, Widget {
nall::function<void ()> onToggle;
bool checked() const;
void setChecked(bool checked = true);
void setText(const nall::string& text);
nall::string text() const;
CheckLabel();
~CheckLabel();
struct State;
State& state;
pCheckLabel& p;
};
struct ComboButton : private nall::base_from_member<pComboButton&>, Widget {
nall::function<void ()> onChange;
template<typename... Args> void append(Args&&... args) { append_({args...}); }
void append_(const nall::lstring& list);
void modify(unsigned row, nall::string text);
void remove(unsigned row);
void append(const nall::string& text = "");
void remove(unsigned selection);
void reset();
unsigned selection();
void setSelection(unsigned row);
nall::string text();
nall::string text(unsigned row);
unsigned rows() const;
unsigned selection() const;
void setSelection(unsigned selection);
void setText(unsigned selection, const nall::string& text);
nall::string text() const;
nall::string text(unsigned selection) const;
ComboButton();
~ComboButton();
@ -473,9 +516,9 @@ struct ComboButton : private nall::base_from_member<pComboButton&>, Widget {
struct Console : private nall::base_from_member<pConsole&>, Widget {
nall::function<void (nall::string)> onActivate;
template<typename... Args> void print(Args&&... args) { print_({args...}); }
template<typename... Args> void print(Args&&... args) { print({args...}); }
void print_(nall::string text);
void print(const nall::string& text);
void reset();
Console();
@ -485,10 +528,27 @@ struct Console : private nall::base_from_member<pConsole&>, Widget {
pConsole& p;
};
struct Frame : private nall::base_from_member<pFrame&>, Widget {
void setLayout(Layout& layout);
void setText(const nall::string& text);
void synchronizeLayout();
nall::string text() const;
Frame();
~Frame();
struct State;
State& state;
pFrame& p;
};
struct HexEdit : private nall::base_from_member<pHexEdit&>, Widget {
nall::function<uint8_t (unsigned)> onRead;
nall::function<void (unsigned, uint8_t)> onWrite;
unsigned columns() const;
unsigned length() const;
unsigned offset() const;
unsigned rows() const;
void setColumns(unsigned columns);
void setLength(unsigned length);
void setOffset(unsigned offset);
@ -505,8 +565,8 @@ struct HexEdit : private nall::base_from_member<pHexEdit&>, Widget {
struct HorizontalScroller : private nall::base_from_member<pHorizontalScroller&>, Widget {
nall::function<void ()> onChange;
unsigned length();
unsigned position();
unsigned length() const;
unsigned position() const;
void setLength(unsigned length);
void setPosition(unsigned position);
@ -520,8 +580,8 @@ struct HorizontalScroller : private nall::base_from_member<pHorizontalScroller&>
struct HorizontalSlider : private nall::base_from_member<pHorizontalSlider&>, Widget {
nall::function<void ()> onChange;
unsigned length();
unsigned position();
unsigned length() const;
unsigned position() const;
void setLength(unsigned length);
void setPosition(unsigned position);
@ -533,7 +593,8 @@ struct HorizontalSlider : private nall::base_from_member<pHorizontalSlider&>, Wi
};
struct Label : private nall::base_from_member<pLabel&>, Widget {
void setText(nall::string text);
void setText(const nall::string& text);
nall::string text() const;
Label();
~Label();
@ -546,8 +607,9 @@ struct LineEdit : private nall::base_from_member<pLineEdit&>, Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange;
bool editable() const;
void setEditable(bool editable = true);
void setText(nall::string text);
void setText(const nall::string& text);
nall::string text();
LineEdit();
@ -562,25 +624,28 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
nall::function<void ()> onChange;
nall::function<void (unsigned)> onToggle;
template<typename... Args> void append(Args&&... args) { append_({args...}); }
template<typename... Args> void modify(unsigned row, Args&&... args) { modify_(row, {args...}); }
template<typename... Args> void setHeaderText(Args&&... args) { setHeaderText_({args...}); }
void append_(const nall::lstring& list);
void append(const nall::lstring& text);
void autoSizeColumns();
bool checked(unsigned row);
void modify_(unsigned row, const nall::lstring& list);
void remove(unsigned row);
bool checkable() const;
bool checked(unsigned selection) const;
unsigned columns() const;
bool headerVisible() const;
nall::image image(unsigned selection, unsigned position) const;
void remove(unsigned selection);
void reset();
bool selected();
unsigned selection();
unsigned rows() const;
bool selected() const;
unsigned selection() const;
void setCheckable(bool checkable = true);
void setChecked(unsigned row, bool checked = true);
void setHeaderText_(const nall::lstring& list);
void setChecked(unsigned selection, bool checked = true);
void setHeaderText(const nall::lstring& text);
void setHeaderVisible(bool visible = true);
void setImage(unsigned row, unsigned column, const nall::image& image = nall::image{});
void setImage(unsigned selection, unsigned position, const nall::image& image = nall::image{});
void setSelected(bool selected = true);
void setSelection(unsigned row);
void setSelection(unsigned selection);
void setText(unsigned selection, const nall::lstring& text);
void setText(unsigned selection, unsigned position, const nall::string& text);
nall::string text(unsigned selection, unsigned position) const;
ListView();
~ListView();
@ -590,6 +655,7 @@ struct ListView : private nall::base_from_member<pListView&>, Widget {
};
struct ProgressBar : private nall::base_from_member<pProgressBar&>, Widget {
unsigned position() const;
void setPosition(unsigned position);
ProgressBar();
@ -605,9 +671,12 @@ struct RadioButton : private nall::base_from_member<pRadioButton&>, Widget {
nall::function<void ()> onActivate;
bool checked();
bool checked() const;
nall::image image() const;
void setChecked();
void setText(nall::string text);
void setImage(const nall::image& image = nall::image{}, Orientation orientation = Orientation::Horizontal);
void setText(const nall::string& text);
nall::string text() const;
RadioButton();
~RadioButton();
@ -616,15 +685,56 @@ struct RadioButton : private nall::base_from_member<pRadioButton&>, Widget {
pRadioButton& p;
};
struct RadioLabel : private nall::base_from_member<pRadioLabel&>, Widget {
template<typename... Args> static void group(Args&&... args) { group({std::forward<Args>(args)...}); }
static void group(const nall::group<RadioLabel>& list);
nall::function<void ()> onActivate;
bool checked() const;
void setChecked();
void setText(const nall::string& text);
nall::string text() const;
RadioLabel();
~RadioLabel();
struct State;
State& state;
pRadioLabel& p;
};
struct TabFrame : private nall::base_from_member<pTabFrame&>, Widget {
nall::function<void ()> onChange;
void append(const nall::string& text = "", const nall::image& image = nall::image{});
nall::image image(unsigned selection) const;
void remove(unsigned selection);
unsigned selection() const;
void setImage(unsigned selection, const nall::image& image = nall::image{});
void setLayout(unsigned selection, Layout& layout);
void setSelection(unsigned selection);
void setText(unsigned selection, const nall::string& text);
void synchronizeLayout();
unsigned tabs() const;
nall::string text(unsigned selection) const;
TabFrame();
~TabFrame();
struct State;
State& state;
pTabFrame& p;
};
struct TextEdit : private nall::base_from_member<pTextEdit&>, Widget {
nall::function<void ()> onChange;
bool editable() const;
void setCursorPosition(unsigned position);
void setEditable(bool editable = true);
void setText(nall::string text);
void setText(const nall::string& text);
void setWordWrap(bool wordWrap = true);
nall::string text();
bool wordWrap();
bool wordWrap() const;
TextEdit();
~TextEdit();
@ -636,8 +746,8 @@ struct TextEdit : private nall::base_from_member<pTextEdit&>, Widget {
struct VerticalScroller : private nall::base_from_member<pVerticalScroller&>, Widget {
nall::function<void ()> onChange;
unsigned length();
unsigned position();
unsigned length() const;
unsigned position() const;
void setLength(unsigned length);
void setPosition(unsigned position);
@ -651,8 +761,8 @@ struct VerticalScroller : private nall::base_from_member<pVerticalScroller&>, Wi
struct VerticalSlider : private nall::base_from_member<pVerticalSlider&>, Widget {
nall::function<void ()> onChange;
unsigned length();
unsigned position();
unsigned length() const;
unsigned position() const;
void setLength(unsigned length);
void setPosition(unsigned position);
@ -670,6 +780,7 @@ struct Viewport : private nall::base_from_member<pViewport&>, Widget {
nall::function<void (Mouse::Button)> onMousePress;
nall::function<void (Mouse::Button)> onMouseRelease;
bool droppable() const;
uintptr_t handle();
void setDroppable(bool droppable = true);

View File

@ -10,13 +10,8 @@ void FixedLayout::append(Sizable& sizable) {
if(window()) window()->synchronizeLayout();
}
bool FixedLayout::enabled() {
if(layout()) return state.enabled && layout()->enabled();
return state.enabled;
}
Size FixedLayout::minimumSize() {
unsigned width = MinimumSize, height = MinimumSize;
unsigned width = Size::Minimum, height = Size::Minimum;
for(auto& child : children) {
width = max(width, child.sizable->minimumSize().width);
height = max(height, child.sizable->minimumSize().height);
@ -42,9 +37,9 @@ void FixedLayout::reset() {
}
void FixedLayout::setEnabled(bool enabled) {
state.enabled = enabled;
Sizable::state.enabled = enabled;
for(auto& child : children) {
child.sizable->setVisible(dynamic_cast<Widget*>(child.sizable) ? child.sizable->enabled() : enabled);
child.sizable->setEnabled(child.sizable->enabled());
}
}
@ -52,29 +47,22 @@ void FixedLayout::setGeometry(Geometry geometry) {
}
void FixedLayout::setVisible(bool visible) {
state.visible = visible;
Sizable::state.visible = visible;
for(auto& child : children) {
child.sizable->setVisible(dynamic_cast<Widget*>(child.sizable) ? child.sizable->visible() : visible);
child.sizable->setVisible(child.sizable->visible());
}
}
void FixedLayout::synchronizeLayout() {
for(auto& child : children) {
Layout::append(*child.sizable);
child.sizable->setGeometry(child.geometry);
Geometry childGeometry = child.geometry;
if((signed)childGeometry.width < 1) childGeometry.width = 1;
if((signed)childGeometry.height < 1) childGeometry.height = 1;
child.sizable->setGeometry(childGeometry);
}
}
bool FixedLayout::visible() {
if(layout()) return state.visible && layout()->visible();
return state.visible;
}
FixedLayout::FixedLayout() {
state.enabled = true;
state.visible = true;
}
FixedLayout::~FixedLayout() {
while(children.size()) remove(*children[0].sizable);
}

View File

@ -1,7 +1,6 @@
struct FixedLayout : Layout {
void append(Sizable& sizable, Geometry geometry);
void append(Sizable& sizable);
bool enabled();
Size minimumSize();
void remove(Sizable& sizable);
void reset();
@ -9,16 +8,9 @@ struct FixedLayout : Layout {
void setGeometry(Geometry geometry);
void setVisible(bool visible = true);
void synchronizeLayout();
bool visible();
FixedLayout();
~FixedLayout();
//private:
struct State {
bool enabled;
bool visible;
} state;
struct Children {
Sizable* sizable;
Geometry geometry;

View File

@ -11,17 +11,12 @@ void HorizontalLayout::append(Sizable& sizable) {
if(window()) window()->synchronizeLayout();
}
bool HorizontalLayout::enabled() {
if(layout()) return state.enabled && layout()->enabled();
return state.enabled;
}
Size HorizontalLayout::minimumSize() {
unsigned width = 0, height = 0;
for(auto& child : children) {
width += child.spacing;
if(child.width == MinimumSize || child.width == MaximumSize) {
if(child.width == Size::Minimum || child.width == Size::Maximum) {
width += child.sizable->minimumSize().width;
continue;
}
@ -29,7 +24,7 @@ Size HorizontalLayout::minimumSize() {
}
for(auto& child : children) {
if(child.height == MinimumSize || child.height == MaximumSize) {
if(child.height == Size::Minimum || child.height == Size::Maximum) {
height = max(height, child.sizable->minimumSize().height);
continue;
}
@ -43,7 +38,7 @@ void HorizontalLayout::remove(Sizable& sizable) {
for(unsigned n = 0; n < children.size(); n++) {
if(children[n].sizable == &sizable) {
if(dynamic_cast<Layout*>(children[n].sizable)) {
Layout *layout = (Layout*)children[n].sizable;
Layout* layout = (Layout*)children[n].sizable;
layout->reset();
}
children.remove(n);
@ -66,17 +61,17 @@ void HorizontalLayout::setAlignment(double alignment) {
}
void HorizontalLayout::setEnabled(bool enabled) {
state.enabled = enabled;
Sizable::state.enabled = enabled;
for(auto& child : children) {
child.sizable->setEnabled(dynamic_cast<Widget*>(child.sizable) ? child.sizable->enabled() : enabled);
child.sizable->setEnabled(child.sizable->enabled());
}
}
void HorizontalLayout::setGeometry(Geometry containerGeometry) {
auto children = this->children;
for(auto& child : children) {
if(child.width == MinimumSize) child.width = child.sizable->minimumSize().width;
if(child.height == MinimumSize) child.height = child.sizable->minimumSize().height;
if(child.width == Size::Minimum) child.width = child.sizable->minimumSize().width;
if(child.height == Size::Minimum) child.height = child.sizable->minimumSize().height;
}
Geometry geometry = containerGeometry;
@ -87,14 +82,14 @@ void HorizontalLayout::setGeometry(Geometry containerGeometry) {
unsigned minimumWidth = 0, maximumWidthCounter = 0;
for(auto& child : children) {
if(child.width == MaximumSize) maximumWidthCounter++;
if(child.width != MaximumSize) minimumWidth += child.width;
if(child.width == Size::Maximum) maximumWidthCounter++;
if(child.width != Size::Maximum) minimumWidth += child.width;
minimumWidth += child.spacing;
}
for(auto& child : children) {
if(child.width == MaximumSize) child.width = (geometry.width - minimumWidth) / maximumWidthCounter;
if(child.height == MaximumSize) child.height = geometry.height;
if(child.width == Size::Maximum) child.width = (geometry.width - minimumWidth) / maximumWidthCounter;
if(child.height == Size::Maximum) child.height = geometry.height;
}
unsigned maximumHeight = 0;
@ -103,6 +98,8 @@ void HorizontalLayout::setGeometry(Geometry containerGeometry) {
for(auto& child : children) {
unsigned pivot = (maximumHeight - child.height) * state.alignment;
Geometry childGeometry = {geometry.x, geometry.y + pivot, child.width, child.height};
if((signed)childGeometry.width < 1) childGeometry.width = 1;
if((signed)childGeometry.height < 1) childGeometry.height = 1;
child.sizable->setGeometry(childGeometry);
geometry.x += child.width + child.spacing;
@ -115,9 +112,9 @@ void HorizontalLayout::setMargin(unsigned margin) {
}
void HorizontalLayout::setVisible(bool visible) {
state.visible = visible;
Sizable::state.visible = visible;
for(auto& child : children) {
child.sizable->setVisible(dynamic_cast<Widget*>(child.sizable) ? child.sizable->visible() : visible);
child.sizable->setVisible(child.sizable->visible());
}
}
@ -125,18 +122,6 @@ void HorizontalLayout::synchronizeLayout() {
for(auto& child : children) Layout::append(*child.sizable);
}
bool HorizontalLayout::visible() {
if(layout()) return state.visible && layout()->visible();
return state.visible;
}
HorizontalLayout::HorizontalLayout() {
state.alignment = 0.5;
state.enabled = true;
state.margin = 0;
state.visible = true;
}
HorizontalLayout::~HorizontalLayout() {
while(children.size()) remove(*children[0].sizable);
}

View File

@ -1,7 +1,6 @@
struct HorizontalLayout : public Layout {
void append(Sizable& sizable, Size size, unsigned spacing = 0);
void append(Sizable& sizable);
bool enabled();
Size minimumSize();
void remove(Sizable& sizable);
void reset();
@ -11,16 +10,12 @@ struct HorizontalLayout : public Layout {
void setMargin(unsigned margin);
void setVisible(bool visible = true);
void synchronizeLayout();
bool visible();
HorizontalLayout();
~HorizontalLayout();
//private:
struct State {
double alignment;
bool enabled;
unsigned margin;
bool visible;
double alignment = 0.5;
unsigned margin = 0;
} state;
struct Children {

View File

@ -11,16 +11,11 @@ void VerticalLayout::append(Sizable& sizable) {
if(window()) window()->synchronizeLayout();
}
bool VerticalLayout::enabled() {
if(layout()) return state.enabled && layout()->enabled();
return state.enabled;
}
Size VerticalLayout::minimumSize() {
unsigned width = 0, height = 0;
for(auto& child : children) {
if(child.width == MinimumSize || child.width == MaximumSize) {
if(child.width == Size::Minimum || child.width == Size::Maximum) {
width = max(width, child.sizable->minimumSize().width);
continue;
}
@ -29,7 +24,7 @@ Size VerticalLayout::minimumSize() {
for(auto& child : children) {
height += child.spacing;
if(child.height == MinimumSize || child.height == MaximumSize) {
if(child.height == Size::Minimum || child.height == Size::Maximum) {
height += child.sizable->minimumSize().height;
continue;
}
@ -43,7 +38,7 @@ void VerticalLayout::remove(Sizable& sizable) {
for(unsigned n = 0; n < children.size(); n++) {
if(children[n].sizable == &sizable) {
if(dynamic_cast<Layout*>(children[n].sizable)) {
Layout *layout = (Layout*)children[n].sizable;
Layout* layout = (Layout*)children[n].sizable;
layout->reset();
}
children.remove(n);
@ -66,17 +61,17 @@ void VerticalLayout::setAlignment(double alignment) {
}
void VerticalLayout::setEnabled(bool enabled) {
state.enabled = enabled;
Sizable::state.enabled = enabled;
for(auto& child : children) {
child.sizable->setEnabled(dynamic_cast<Widget*>(child.sizable) ? child.sizable->enabled() : enabled);
child.sizable->setEnabled(child.sizable->enabled());
}
}
void VerticalLayout::setGeometry(Geometry containerGeometry) {
auto children = this->children;
for(auto& child : children) {
if(child.width == MinimumSize) child.width = child.sizable->minimumSize().width;
if(child.height == MinimumSize) child.height = child.sizable->minimumSize().height;
if(child.width == Size::Minimum) child.width = child.sizable->minimumSize().width;
if(child.height == Size::Minimum) child.height = child.sizable->minimumSize().height;
}
Geometry geometry = containerGeometry;
@ -87,14 +82,14 @@ void VerticalLayout::setGeometry(Geometry containerGeometry) {
unsigned minimumHeight = 0, maximumHeightCounter = 0;
for(auto& child : children) {
if(child.height == MaximumSize) maximumHeightCounter++;
if(child.height != MaximumSize) minimumHeight += child.height;
if(child.height == Size::Maximum) maximumHeightCounter++;
if(child.height != Size::Maximum) minimumHeight += child.height;
minimumHeight += child.spacing;
}
for(auto& child : children) {
if(child.width == MaximumSize) child.width = geometry.width;
if(child.height == MaximumSize) child.height = (geometry.height - minimumHeight) / maximumHeightCounter;
if(child.width == Size::Maximum) child.width = geometry.width;
if(child.height == Size::Maximum) child.height = (geometry.height - minimumHeight) / maximumHeightCounter;
}
unsigned maximumWidth = 0;
@ -103,6 +98,8 @@ void VerticalLayout::setGeometry(Geometry containerGeometry) {
for(auto& child : children) {
unsigned pivot = (maximumWidth - child.width) * state.alignment;
Geometry childGeometry = {geometry.x + pivot, geometry.y, child.width, child.height};
if((signed)childGeometry.width < 1) childGeometry.width = 1;
if((signed)childGeometry.height < 1) childGeometry.height = 1;
child.sizable->setGeometry(childGeometry);
geometry.y += child.height + child.spacing;
@ -115,9 +112,9 @@ void VerticalLayout::setMargin(unsigned margin) {
}
void VerticalLayout::setVisible(bool visible) {
state.visible = visible;
Sizable::state.visible = visible;
for(auto& child : children) {
child.sizable->setVisible(dynamic_cast<Widget*>(child.sizable) ? child.sizable->visible() : visible);
child.sizable->setVisible(child.sizable->visible());
}
}
@ -125,18 +122,6 @@ void VerticalLayout::synchronizeLayout() {
for(auto& child : children) Layout::append(*child.sizable);
}
bool VerticalLayout::visible() {
if(layout()) return state.visible && layout()->visible();
return state.visible;
}
VerticalLayout::VerticalLayout() {
state.alignment = 0.0;
state.enabled = true;
state.margin = 0;
state.visible = true;
}
VerticalLayout::~VerticalLayout() {
while(children.size()) remove(*children[0].sizable);
}

View File

@ -1,7 +1,6 @@
struct VerticalLayout : public Layout {
void append(Sizable& sizable, Size size, unsigned spacing = 0);
void append(Sizable& sizable);
bool enabled();
Size minimumSize();
void remove(Sizable& sizable);
void reset();
@ -11,16 +10,12 @@ struct VerticalLayout : public Layout {
void setMargin(unsigned margin);
void setVisible(bool visible = true);
void synchronizeLayout();
bool visible();
VerticalLayout();
~VerticalLayout();
//private:
struct State {
double alignment;
bool enabled;
unsigned margin;
bool visible;
double alignment = 0.0;
unsigned margin = 0;
} state;
struct Children {

View File

@ -5,7 +5,7 @@ struct Application::State {
struct Timer::State {
bool enabled = false;
unsigned milliseconds = 0;
unsigned interval = 0;
};
struct BrowserWindow::State {
@ -52,12 +52,12 @@ struct Action::State {
struct Menu::State {
group<Action> action;
nall::image image = {0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0};
nall::image image;
string text;
};
struct Item::State {
nall::image image = {0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0};
nall::image image;
string text;
};
@ -73,35 +73,48 @@ struct RadioItem::State {
};
struct Sizable::State {
Layout* layout = nullptr;
bool enabled = true;
Sizable* parent = nullptr;
bool visible = true;
Window* window = nullptr;
};
struct Layout::State {
Widget* widget = nullptr;
unsigned widgetSelection = 0;
};
struct Widget::State {
bool abstract = false;
bool enabled = true;
string font;
Geometry geometry = {0, 0, 0, 0};
bool visible = true;
};
struct Button::State {
nall::image image = {0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0};
nall::image image;
Orientation orientation = Orientation::Horizontal;
string text;
};
struct Canvas::State {
Color color;
uint32_t* data = nullptr;
bool droppable = false;
unsigned width = 256;
unsigned height = 256;
vector<Color> gradient = {{}, {}, {}, {}};
nall::image image;
Canvas::Mode mode = Canvas::Mode::Color;
unsigned width = 0;
unsigned height = 0;
};
struct CheckButton::State {
bool checked = false;
nall::image image;
Orientation orientation = Orientation::Horizontal;
string text;
};
struct CheckLabel::State {
bool checked = false;
string text;
};
@ -114,6 +127,11 @@ struct ComboButton::State {
struct Console::State {
};
struct Frame::State {
Layout* layout = nullptr;
string text;
};
struct HexEdit::State {
unsigned columns = 16;
unsigned length = 0;
@ -158,9 +176,24 @@ struct ProgressBar::State {
struct RadioButton::State {
bool checked = true;
nall::group<RadioButton> group;
nall::image image;
Orientation orientation = Orientation::Horizontal;
string text;
};
struct RadioLabel::State {
bool checked = true;
nall::group<RadioLabel> group;
string text;
};
struct TabFrame::State {
vector<nall::image> image;
vector<Layout*> layout;
unsigned selection = 0;
lstring text;
};
struct TextEdit::State {
unsigned cursorPosition = 0;
bool editable = true;

0
phoenix/core/utility.cpp Normal file
View File

View File

@ -1,11 +1,8 @@
namespace phoenix {
static void CheckItem_toggle(CheckItem* self) {
if(self->p.locked == false && self->onToggle) self->onToggle();
}
bool pCheckItem::checked() {
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
static void CheckItem_toggle(GtkCheckMenuItem* gtkCheckMenuItem, CheckItem* self) {
self->state.checked = gtk_check_menu_item_get_active(gtkCheckMenuItem);
if(!self->p.locked && self->onToggle) self->onToggle();
}
void pCheckItem::setChecked(bool checked) {
@ -22,7 +19,7 @@ void pCheckItem::constructor() {
widget = gtk_check_menu_item_new_with_mnemonic("");
setChecked(checkItem.state.checked);
setText(checkItem.state.text);
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(CheckItem_toggle), (gpointer)&checkItem);
g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(CheckItem_toggle), (gpointer)&checkItem);
}
void pCheckItem::destructor() {

View File

@ -1,22 +1,18 @@
namespace phoenix {
static void RadioItem_activate(RadioItem* self) {
for(auto& item : self->state.group) item.state.checked = (&item == self);
if(self->p.locked == false && self->checked() && self->onActivate) self->onActivate();
}
bool pRadioItem::checked() {
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
static void RadioItem_activate(GtkCheckMenuItem* gtkCheckMenuItem, RadioItem* self) {
self->p.onActivate();
}
void pRadioItem::setChecked() {
locked = true;
parent().locked = true;
for(auto& item : radioItem.state.group) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item.p.widget), false);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), true);
locked = false;
parent().locked = false;
}
void pRadioItem::setGroup(const group<RadioItem>& group) {
parent().locked = true;
for(auto& item : group) {
if(&item == &group.first()) continue;
GSList* currentGroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(group.first().p.widget));
@ -24,6 +20,7 @@ void pRadioItem::setGroup(const group<RadioItem>& group) {
gtk_radio_menu_item_set_group(GTK_RADIO_MENU_ITEM(item.p.widget), currentGroup);
}
}
parent().locked = false;
}
void pRadioItem::setText(string text) {
@ -37,7 +34,7 @@ void pRadioItem::constructor() {
for(auto& item : radioItem.state.group) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item.p.widget), item.state.checked);
}
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(RadioItem_activate), (gpointer)&radioItem);
g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(RadioItem_activate), (gpointer)&radioItem);
}
void pRadioItem::destructor() {
@ -49,4 +46,17 @@ void pRadioItem::orphan() {
constructor();
}
void pRadioItem::onActivate() {
if(parent().locked) return;
bool wasChecked = radioItem.state.checked;
radioItem.setChecked();
if(wasChecked) return;
if(radioItem.onActivate) radioItem.onActivate();
}
pRadioItem& pRadioItem::parent() {
if(radioItem.state.group.size()) return radioItem.state.group.first().p;
return *this;
}
}

View File

@ -23,8 +23,10 @@
#include "widget/button.cpp"
#include "widget/canvas.cpp"
#include "widget/check-button.cpp"
#include "widget/check-label.cpp"
#include "widget/combo-button.cpp"
#include "widget/console.cpp"
#include "widget/frame.cpp"
#include "widget/hex-edit.cpp"
#include "widget/horizontal-scroller.cpp"
#include "widget/horizontal-slider.cpp"
@ -33,6 +35,8 @@
#include "widget/list-view.cpp"
#include "widget/progress-bar.cpp"
#include "widget/radio-button.cpp"
#include "widget/radio-label.cpp"
#include "widget/tab-frame.cpp"
#include "widget/text-edit.cpp"
#include "widget/vertical-scroller.cpp"
#include "widget/vertical-slider.cpp"

View File

@ -95,7 +95,7 @@ struct pTimer : public pObject {
Timer& timer;
void setEnabled(bool enabled);
void setInterval(unsigned milliseconds);
void setInterval(unsigned interval);
pTimer(Timer& timer) : pObject(timer), timer(timer) {}
void constructor();
@ -117,7 +117,6 @@ struct pWindow : public pObject {
void append(Layout& layout);
void append(Menu& menu);
void append(Widget& widget);
Color backgroundColor();
bool focused();
Geometry frameMargin();
Geometry geometry();
@ -200,7 +199,6 @@ struct pItem : public pAction {
struct pCheckItem : public pAction {
CheckItem& checkItem;
bool checked();
void setChecked(bool checked);
void setText(string text);
@ -213,7 +211,6 @@ struct pCheckItem : public pAction {
struct pRadioItem : public pAction {
RadioItem& radioItem;
bool checked();
void setChecked();
void setGroup(const group<RadioItem>& group);
void setText(string text);
@ -222,11 +219,15 @@ struct pRadioItem : public pAction {
void constructor();
void destructor();
void orphan();
void onActivate();
pRadioItem& parent();
};
struct pSizable : public pObject {
Sizable& sizable;
virtual Position displacement() { return {0, 0}; }
pSizable(Sizable &sizable) : pObject(sizable), sizable(sizable) {}
};
@ -238,16 +239,18 @@ struct pLayout : public pSizable {
struct pWidget : public pSizable {
Widget& widget;
GtkWidget* gtkWidget;
GtkWidget* gtkWidget = nullptr;
GtkWidget* gtkParent = nullptr;
bool enabled();
virtual GtkWidget* container(Widget& widget);
virtual Position containerOffset();
virtual bool focused();
virtual Size minimumSize();
void setEnabled(bool enabled);
virtual void setEnabled(bool enabled);
virtual void setFocused();
virtual void setFont(string font);
virtual void setGeometry(Geometry geometry);
void setVisible(bool visible);
virtual void setVisible(bool visible);
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
void constructor();
@ -270,27 +273,49 @@ struct pButton : public pWidget {
struct pCanvas : public pWidget {
Canvas& canvas;
cairo_surface_t* surface;
GdkPixbuf* surface = nullptr;
unsigned surfaceWidth = 0;
unsigned surfaceHeight = 0;
Size minimumSize();
void setDroppable(bool droppable);
void setGeometry(Geometry geometry);
void setMode(Canvas::Mode mode);
void setSize(Size size);
void update();
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
void constructor();
void destructor();
void orphan();
void onExpose(GdkEventExpose* event);
void rasterize();
void redraw();
void release();
};
struct pCheckButton : public pWidget {
CheckButton& checkButton;
bool checked();
Size minimumSize();
void setChecked(bool checked);
void setImage(const image& image, Orientation orientation);
void setText(string text);
pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {}
void constructor();
void destructor();
void orphan();
void onToggle();
};
struct pCheckLabel : public pWidget {
CheckLabel& checkLabel;
Size minimumSize();
void setChecked(bool checked);
void setText(string text);
pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {}
pCheckLabel(CheckLabel& checkLabel) : pWidget(checkLabel), checkLabel(checkLabel) {}
void constructor();
void destructor();
void orphan();
@ -301,12 +326,11 @@ struct pComboButton : public pWidget {
unsigned itemCounter;
void append(string text);
void modify(unsigned row, string text);
void remove(unsigned row);
Size minimumSize();
void remove(unsigned selection);
void reset();
unsigned selection();
void setSelection(unsigned row);
void setSelection(unsigned selection);
void setText(unsigned selection, string text);
pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {}
void constructor();
@ -331,6 +355,22 @@ struct pConsole : public pWidget {
void seekCursorToEnd();
};
struct pFrame : public pWidget {
Frame& frame;
GtkWidget* container(Widget& widget);
Position containerOffset();
void setEnabled(bool enabled);
void setGeometry(Geometry geometry);
void setText(string text);
void setVisible(bool visible);
pFrame(Frame& frame) : pWidget(frame), frame(frame) {}
void constructor();
void destructor();
void orphan();
};
struct pHexEdit : public pWidget {
HexEdit& hexEdit;
GtkWidget* container;
@ -364,7 +404,6 @@ struct pHorizontalScroller : public pWidget {
HorizontalScroller& horizontalScroller;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
@ -378,7 +417,6 @@ struct pHorizontalSlider : public pWidget {
HorizontalSlider& horizontalSlider;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
@ -429,20 +467,17 @@ struct pListView : public pWidget {
void append(const lstring& text);
void autoSizeColumns();
bool checked(unsigned row);
bool focused();
void modify(unsigned row, const lstring& text);
void remove(unsigned row);
void remove(unsigned selection);
void reset();
bool selected();
unsigned selection();
void setCheckable(bool checkable);
void setChecked(unsigned row, bool checked);
void setChecked(unsigned selection, bool checked);
void setHeaderText(const lstring& text);
void setHeaderVisible(bool visible);
void setImage(unsigned row, unsigned column, const nall::image& image);
void setImage(unsigned selection, unsigned position, const image& image);
void setSelected(bool selected);
void setSelection(unsigned row);
void setText(unsigned selection, unsigned position, string text);
pListView(ListView& listView) : pWidget(listView), listView(listView) {}
void constructor();
@ -467,18 +502,65 @@ struct pProgressBar : public pWidget {
struct pRadioButton : public pWidget {
RadioButton& radioButton;
bool checked();
Size minimumSize();
void setChecked();
void setGroup(const group<RadioButton>& group);
void setImage(const image& image, Orientation orientation);
void setText(string text);
pRadioButton(RadioButton& radioButton) : pWidget(radioButton), radioButton(radioButton) {}
void onActivate();
pRadioButton& parent();
void constructor();
void destructor();
void orphan();
void onActivate();
pRadioButton& parent();
};
struct pRadioLabel : public pWidget {
RadioLabel& radioLabel;
Size minimumSize();
void setChecked();
void setGroup(const group<RadioLabel>& group);
void setText(string text);
pRadioLabel(RadioLabel& radioLabel) : pWidget(radioLabel), radioLabel(radioLabel) {}
void onActivate();
pRadioLabel& parent();
void constructor();
void destructor();
void orphan();
};
struct pTabFrame : public pWidget {
TabFrame& tabFrame;
struct Tab {
GtkWidget* child;
GtkWidget* container;
GtkWidget* layout;
GtkWidget* image;
GtkWidget* title;
};
vector<Tab> tabs;
void append(string text, const image& image);
GtkWidget* container(Widget& widget);
Position containerOffset();
Position displacement();
void remove(unsigned selection);
void setEnabled(bool enabled);
void setGeometry(Geometry geometry);
void setImage(unsigned selection, const image& image);
void setSelection(unsigned selection);
void setText(unsigned selection, string text);
void setVisible(bool visible);
pTabFrame(TabFrame& tabFrame) : pWidget(tabFrame), tabFrame(tabFrame) {}
void constructor();
void destructor();
void orphan();
void setFont(string font);
void synchronizeLayout();
};
struct pTextEdit : public pWidget {
@ -503,7 +585,6 @@ struct pVerticalScroller : public pWidget {
VerticalScroller& verticalScroller;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
@ -517,7 +598,6 @@ struct pVerticalSlider : public pWidget {
VerticalSlider& verticalSlider;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);

View File

@ -7,7 +7,7 @@ static guint Timer_trigger(pTimer* self) {
}
//callback may have disabled timer, so check state again
if(self->timer.state.enabled) {
g_timeout_add(self->timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)self);
g_timeout_add(self->timer.state.interval, (GSourceFunc)Timer_trigger, (gpointer)self);
}
//kill this timer instance (it is spawned above if needed again)
return false;
@ -15,11 +15,11 @@ static guint Timer_trigger(pTimer* self) {
void pTimer::setEnabled(bool enabled) {
if(enabled) {
g_timeout_add(timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)this);
g_timeout_add(timer.state.interval, (GSourceFunc)Timer_trigger, (gpointer)this);
}
}
void pTimer::setInterval(unsigned milliseconds) {
void pTimer::setInterval(unsigned interval) {
}
void pTimer::constructor() {

View File

@ -12,7 +12,7 @@ static GdkColor CreateColor(uint8_t r, uint8_t g, uint8_t b) {
static GdkPixbuf* CreatePixbuf(const nall::image& image, bool scale = false) {
nall::image gdkImage = image;
gdkImage.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16);
if(scale) gdkImage.scale(15, 15, Interpolation::Linear);
if(scale) gdkImage.scale(15, 15);
GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, gdkImage.width, gdkImage.height);
memcpy(gdk_pixbuf_get_pixels(pixbuf), gdkImage.data, gdkImage.width * gdkImage.height * 4);
@ -46,6 +46,37 @@ static lstring DropPaths(GtkSelectionData* data) {
return paths;
}
static Position GetDisplacement(Sizable* sizable) {
Position position;
while(sizable->state.parent) {
Position displacement = sizable->state.parent->p.displacement();
position.x += displacement.x;
position.y += displacement.y;
sizable = sizable->state.parent;
}
return position;
}
static Layout* GetParentWidgetLayout(Sizable* sizable) {
while(sizable) {
if(sizable->state.parent && dynamic_cast<TabFrame*>(sizable->state.parent)) return (Layout*)sizable;
sizable = sizable->state.parent;
}
return nullptr;
}
static Widget* GetParentWidget(Sizable* sizable) {
while(sizable) {
if(sizable->state.parent && dynamic_cast<TabFrame*>(sizable->state.parent)) return (Widget*)sizable->state.parent;
sizable = sizable->state.parent;
}
return nullptr;
}
static bool HasParentWidget(Sizable* sizable) {
return GetParentWidget(sizable) != nullptr;
}
static Keyboard::Keycode Keysym(unsigned keysym) {
switch(keysym) {
case GDK_Escape: return Keyboard::Keycode::Escape;

View File

@ -1,83 +1,102 @@
namespace phoenix {
static gboolean Canvas_expose(GtkWidget* widget, GdkEvent* event, pCanvas* self) {
cairo_t* context = gdk_cairo_create(gtk_widget_get_window(widget));
cairo_set_source_surface(context, self->surface, 0, 0);
cairo_paint(context);
cairo_destroy(context);
return true;
}
static void Canvas_dropEvent(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
GtkSelectionData* data, guint type, guint timestamp, Canvas* canvas) {
if(canvas->state.droppable == false) return;
static void Canvas_drop(GtkWidget* widget, GdkDragContext* context, signed x, signed y,
GtkSelectionData* data, unsigned type, unsigned timestamp, Canvas* canvas) {
if(!canvas->state.droppable) return;
lstring paths = DropPaths(data);
if(paths.empty()) return;
if(canvas->onDrop) canvas->onDrop(paths);
}
static gboolean Canvas_mouseLeave(GtkWidget* widget, GdkEventButton* event, pCanvas* self) {
if(self->canvas.onMouseLeave) self->canvas.onMouseLeave();
static signed Canvas_expose(GtkWidget* widget, GdkEventExpose* event, Canvas* self) {
self->p.onExpose(event);
return true;
}
static gboolean Canvas_mouseMove(GtkWidget* widget, GdkEventButton* event, pCanvas* self) {
if(self->canvas.onMouseMove) self->canvas.onMouseMove({(signed)event->x, (signed)event->y});
static signed Canvas_mouseLeave(GtkWidget* widget, GdkEventButton* event, Canvas* self) {
if(self->onMouseLeave) self->onMouseLeave();
return true;
}
static gboolean Canvas_mousePress(GtkWidget* widget, GdkEventButton* event, pCanvas* self) {
if(self->canvas.onMousePress) switch(event->button) {
case 1: self->canvas.onMousePress(Mouse::Button::Left); break;
case 2: self->canvas.onMousePress(Mouse::Button::Middle); break;
case 3: self->canvas.onMousePress(Mouse::Button::Right); break;
static signed Canvas_mouseMove(GtkWidget* widget, GdkEventButton* event, Canvas* self) {
if(self->onMouseMove) self->onMouseMove({(signed)event->x, (signed)event->y});
return true;
}
static signed Canvas_mousePress(GtkWidget* widget, GdkEventButton* event, Canvas* self) {
if(self->onMousePress) switch(event->button) {
case 1: self->onMousePress(Mouse::Button::Left); break;
case 2: self->onMousePress(Mouse::Button::Middle); break;
case 3: self->onMousePress(Mouse::Button::Right); break;
}
return true;
}
static gboolean Canvas_mouseRelease(GtkWidget* widget, GdkEventButton* event, pCanvas* self) {
if(self->canvas.onMouseRelease) switch(event->button) {
case 1: self->canvas.onMouseRelease(Mouse::Button::Left); break;
case 2: self->canvas.onMouseRelease(Mouse::Button::Middle); break;
case 3: self->canvas.onMouseRelease(Mouse::Button::Right); break;
static signed Canvas_mouseRelease(GtkWidget* widget, GdkEventButton* event, Canvas* self) {
if(self->onMouseRelease) switch(event->button) {
case 1: self->onMouseRelease(Mouse::Button::Left); break;
case 2: self->onMouseRelease(Mouse::Button::Middle); break;
case 3: self->onMouseRelease(Mouse::Button::Right); break;
}
return true;
}
Size pCanvas::minimumSize() {
return {canvas.state.width, canvas.state.height};
}
void pCanvas::setDroppable(bool droppable) {
gtk_drag_dest_set(gtkWidget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY);
if(droppable) gtk_drag_dest_add_uri_targets(gtkWidget);
}
void pCanvas::setSize(Size size) {
cairo_surface_destroy(surface);
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height);
void pCanvas::setGeometry(Geometry geometry) {
if(canvas.state.width == 0 || canvas.state.height == 0) rasterize();
unsigned width = canvas.state.width;
unsigned height = canvas.state.height;
if(width == 0) width = widget.state.geometry.width;
if(height == 0) height = widget.state.geometry.height;
if(width < geometry.width) {
geometry.x += (geometry.width - width) / 2;
geometry.width = width;
}
if(height < geometry.height) {
geometry.y += (geometry.height - height) / 2;
geometry.height = height;
}
pWidget::setGeometry(geometry);
}
void pCanvas::update() {
memcpy(cairo_image_surface_get_data(surface), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
if(gtk_widget_get_realized(gtkWidget) == false) return;
gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), nullptr, true);
void pCanvas::setMode(Canvas::Mode mode) {
rasterize(), redraw();
}
void pCanvas::setSize(Size size) {
rasterize(), redraw();
}
void pCanvas::constructor() {
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height);
memcpy(cairo_image_surface_get_data(surface), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
gtkWidget = gtk_drawing_area_new();
gtk_widget_set_double_buffered(gtkWidget, false);
//gtk_widget_set_double_buffered(gtkWidget, false);
gtk_widget_add_events(gtkWidget,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Canvas_dropEvent), (gpointer)&canvas);
g_signal_connect(G_OBJECT(gtkWidget), "button_press_event", G_CALLBACK(Canvas_mousePress), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "button_release_event", G_CALLBACK(Canvas_mouseRelease), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "leave_notify_event", G_CALLBACK(Canvas_mouseLeave), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "motion_notify_event", G_CALLBACK(Canvas_mouseMove), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Canvas_mousePress), (gpointer)&canvas);
g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Canvas_mouseRelease), (gpointer)&canvas);
g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Canvas_drop), (gpointer)&canvas);
g_signal_connect(G_OBJECT(gtkWidget), "expose-event", G_CALLBACK(Canvas_expose), (gpointer)&canvas);
g_signal_connect(G_OBJECT(gtkWidget), "leave-notify-event", G_CALLBACK(Canvas_mouseLeave), (gpointer)&canvas);
g_signal_connect(G_OBJECT(gtkWidget), "motion-notify-event", G_CALLBACK(Canvas_mouseMove), (gpointer)&canvas);
setDroppable(canvas.state.droppable);
rasterize(), redraw();
}
void pCanvas::destructor() {
release();
gtk_widget_destroy(gtkWidget);
cairo_surface_destroy(surface);
}
void pCanvas::orphan() {
@ -85,4 +104,74 @@ void pCanvas::orphan() {
constructor();
}
void pCanvas::onExpose(GdkEventExpose* expose) {
if(surface) gdk_draw_pixbuf(gtk_widget_get_window(gtkWidget), nullptr, surface, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
}
void pCanvas::rasterize() {
unsigned width = canvas.state.width;
unsigned height = canvas.state.height;
if(width == 0) width = widget.state.geometry.width;
if(height == 0) height = widget.state.geometry.height;
if(width != surfaceWidth || height != surfaceHeight) release();
surfaceWidth = width;
surfaceHeight = height;
if(width == 0 || height == 0) return;
if(!surface) surface = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, width, height);
uint32_t* buffer = (uint32_t*)gdk_pixbuf_get_pixels(surface);
if(canvas.state.mode == Canvas::Mode::Color) {
uint32_t color = canvas.state.color.argb();
for(unsigned n = 0; n < width * height; n++) buffer[n] = color;
}
if(canvas.state.mode == Canvas::Mode::Gradient) {
nall::image image;
image.allocate(width, height);
image.gradient(
canvas.state.gradient[0].argb(), canvas.state.gradient[1].argb(), canvas.state.gradient[2].argb(), canvas.state.gradient[3].argb()
);
memcpy(buffer, image.data, image.size);
}
if(canvas.state.mode == Canvas::Mode::Image) {
nall::image image = canvas.state.image;
image.scale(width, height);
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
memcpy(buffer, image.data, image.size);
}
if(canvas.state.mode == Canvas::Mode::Data) {
if(width == canvas.state.width && height == canvas.state.height) {
memcpy(buffer, canvas.state.data, width * height * sizeof(uint32_t));
} else {
memset(buffer, 0x00, width * height * sizeof(uint32_t));
}
}
//ARGB -> ABGR conversion
for(unsigned n = 0; n < width * height; n++) {
uint32_t color = *buffer;
color = (color & 0xff00ff00) | ((color & 0xff0000) >> 16) | ((color & 0x0000ff) << 16);
*buffer++ = color;
}
}
void pCanvas::redraw() {
if(gtk_widget_get_realized(gtkWidget)) {
gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), nullptr, true);
}
}
void pCanvas::release() {
if(surface == nullptr) return;
g_object_unref(surface);
surface = nullptr;
surfaceWidth = 0;
surfaceHeight = 0;
}
}

View File

@ -1,17 +1,23 @@
namespace phoenix {
static void CheckButton_toggle(CheckButton* self) {
self->state.checked = self->checked();
if(self->p.locked == false && self->onToggle) self->onToggle();
}
bool pCheckButton::checked() {
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtkWidget));
static void CheckButton_toggle(GtkToggleButton* toggleButton, CheckButton* self) {
self->p.onToggle();
}
Size pCheckButton::minimumSize() {
Size size = pFont::size(widget.state.font, checkButton.state.text);
return {size.width + 28, size.height + 4};
if(checkButton.state.orientation == Orientation::Horizontal) {
size.width += checkButton.state.image.width;
size.height = max(checkButton.state.image.height, size.height);
}
if(checkButton.state.orientation == Orientation::Vertical) {
size.width = max(checkButton.state.image.width, size.width);
size.height += checkButton.state.image.height;
}
return {size.width + 24, size.height + 12};
}
void pCheckButton::setChecked(bool checked) {
@ -20,13 +26,27 @@ void pCheckButton::setChecked(bool checked) {
locked = false;
}
void pCheckButton::setImage(const image& image, Orientation orientation) {
if(image.empty() == false) {
GtkImage* gtkImage = CreateImage(image);
gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage);
} else {
gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr);
}
switch(orientation) {
case Orientation::Horizontal: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_LEFT); break;
case Orientation::Vertical: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_TOP); break;
}
}
void pCheckButton::setText(string text) {
gtk_button_set_label(GTK_BUTTON(gtkWidget), text);
setFont(widget.state.font);
}
void pCheckButton::constructor() {
gtkWidget = gtk_check_button_new_with_label("");
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckButton_toggle), (gpointer)&checkButton);
gtkWidget = gtk_toggle_button_new();
g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckButton_toggle), (gpointer)&checkButton);
setChecked(checkButton.state.checked);
setText(checkButton.state.text);
@ -41,4 +61,10 @@ void pCheckButton::orphan() {
constructor();
}
void pCheckButton::onToggle() {
if(locked) return;
checkButton.state.checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtkWidget));
if(checkButton.onToggle) checkButton.onToggle();
}
}

View File

@ -0,0 +1,40 @@
namespace phoenix {
static void CheckLabel_toggle(GtkToggleButton* toggleButton, CheckLabel* self) {
self->state.checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(self->p.gtkWidget));
if(!self->p.locked && self->onToggle) self->onToggle();
}
Size pCheckLabel::minimumSize() {
Size size = pFont::size(widget.state.font, checkLabel.state.text);
return {size.width + 28, size.height + 4};
}
void pCheckLabel::setChecked(bool checked) {
locked = true;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), checked);
locked = false;
}
void pCheckLabel::setText(string text) {
gtk_button_set_label(GTK_BUTTON(gtkWidget), text);
}
void pCheckLabel::constructor() {
gtkWidget = gtk_check_button_new_with_label("");
g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckLabel_toggle), (gpointer)&checkLabel);
setChecked(checkLabel.state.checked);
setText(checkLabel.state.text);
}
void pCheckLabel::destructor() {
gtk_widget_destroy(gtkWidget);
}
void pCheckLabel::orphan() {
destructor();
constructor();
}
}

View File

@ -1,15 +1,15 @@
namespace phoenix {
static void ComboButton_change(ComboButton* self) {
if(self->p.locked == false) {
self->state.selection = self->selection();
if(!self->p.locked) {
self->state.selection = gtk_combo_box_get_active(GTK_COMBO_BOX(self->p.gtkWidget));
if(self->onChange) self->onChange();
}
}
void pComboButton::append(string text) {
gtk_combo_box_append_text(GTK_COMBO_BOX(gtkWidget), text);
if(itemCounter++ == 0) setSelection(0);
if(itemCounter++ == 0) comboButton.setSelection(0);
}
Size pComboButton::minimumSize() {
@ -20,21 +20,14 @@ Size pComboButton::minimumSize() {
return {maximumWidth + 44, size.height + 12};
}
void pComboButton::modify(unsigned row, string text) {
void pComboButton::remove(unsigned selection) {
locked = true;
unsigned position = selection();
gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), row);
gtk_combo_box_insert_text(GTK_COMBO_BOX(gtkWidget), row, text);
gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), position);
gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), selection);
itemCounter--;
locked = false;
}
void pComboButton::remove(unsigned row) {
locked = true;
unsigned position = selection();
gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), row);
if(position == row) gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), 0);
locked = false;
//when removing the actively selected item, reset the selection to the first entry
if(selection == comboButton.state.selection) comboButton.setSelection(0);
}
void pComboButton::reset() {
@ -44,13 +37,17 @@ void pComboButton::reset() {
locked = false;
}
unsigned pComboButton::selection() {
return gtk_combo_box_get_active(GTK_COMBO_BOX(gtkWidget));
void pComboButton::setSelection(unsigned selection) {
locked = true;
gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), selection);
locked = false;
}
void pComboButton::setSelection(unsigned row) {
void pComboButton::setText(unsigned selection, string text) {
locked = true;
gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), row);
gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), selection);
gtk_combo_box_insert_text(GTK_COMBO_BOX(gtkWidget), selection, text);
gtk_combo_box_set_active(GTK_COMBO_BOX(gtkWidget), comboButton.state.selection);
locked = false;
}

View File

@ -0,0 +1,48 @@
namespace phoenix {
GtkWidget* pFrame::container(Widget& widget) {
return gtk_widget_get_parent(gtkWidget);
}
Position pFrame::containerOffset() {
return {0, 0};
}
void pFrame::setEnabled(bool enabled) {
if(frame.state.layout) frame.state.layout->setEnabled(frame.state.layout->enabled());
pWidget::setEnabled(enabled);
}
void pFrame::setGeometry(Geometry geometry) {
pWidget::setGeometry(geometry);
if(frame.state.layout == nullptr) return;
Size size = pFont::size(widget.state.font, frame.state.text);
if(frame.state.text.empty()) size.height = 8;
geometry.x += 2, geometry.width -= 5;
geometry.y += size.height - 1, geometry.height -= size.height + 2;
frame.state.layout->setGeometry(geometry);
}
void pFrame::setText(string text) {
gtk_frame_set_label(GTK_FRAME(gtkWidget), text);
}
void pFrame::setVisible(bool visible) {
if(frame.state.layout) frame.state.layout->setVisible(frame.state.layout->visible());
pWidget::setVisible(visible);
}
void pFrame::constructor() {
gtkWidget = gtk_frame_new("");
}
void pFrame::destructor() {
gtk_widget_destroy(gtkWidget);
}
void pFrame::orphan() {
destructor();
constructor();
}
}

View File

@ -1,19 +1,16 @@
namespace phoenix {
static void HorizontalScroller_change(HorizontalScroller* self) {
if(self->state.position == self->position()) return;
self->state.position = self->position();
if(self->p.locked == false && self->onChange) self->onChange();
static void HorizontalScroller_change(GtkRange* gtkRange, HorizontalScroller* self) {
unsigned position = (unsigned)gtk_range_get_value(gtkRange);
if(self->state.position == position) return;
self->state.position = position;
if(!self->p.locked && self->onChange) self->onChange();
}
Size pHorizontalScroller::minimumSize() {
return {0, 20};
}
unsigned pHorizontalScroller::position() {
return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget));
}
void pHorizontalScroller::setLength(unsigned length) {
locked = true;
length += length == 0;
@ -28,7 +25,7 @@ void pHorizontalScroller::setPosition(unsigned position) {
void pHorizontalScroller::constructor() {
gtkWidget = gtk_hscrollbar_new(0);
g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalScroller_change), (gpointer)&horizontalScroller);
g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalScroller_change), (gpointer)&horizontalScroller);
setLength(horizontalScroller.state.length);
setPosition(horizontalScroller.state.position);

View File

@ -1,8 +1,9 @@
namespace phoenix {
static void HorizontalSlider_change(HorizontalSlider* self) {
if(self->state.position == self->position()) return;
self->state.position = self->position();
static void HorizontalSlider_change(GtkRange* gtkRange, HorizontalSlider* self) {
unsigned position = (unsigned)gtk_range_get_value(gtkRange);
if(self->state.position == position) return;
self->state.position = position;
if(self->onChange) self->onChange();
}
@ -10,10 +11,6 @@ Size pHorizontalSlider::minimumSize() {
return {0, 20};
}
unsigned pHorizontalSlider::position() {
return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget));
}
void pHorizontalSlider::setLength(unsigned length) {
length += length == 0;
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1));
@ -27,7 +24,7 @@ void pHorizontalSlider::setPosition(unsigned position) {
void pHorizontalSlider::constructor() {
gtkWidget = gtk_hscale_new_with_range(0, 100, 1);
gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false);
g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)&horizontalSlider);
g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)&horizontalSlider);
setLength(horizontalSlider.state.length);
setPosition(horizontalSlider.state.position);

View File

@ -1,57 +1,53 @@
namespace phoenix {
static void ListView_activate(ListView* self) {
static void ListView_activate(GtkTreeView* treeView, GtkTreePath* path, GtkTreeViewColumn* column, ListView* self) {
char* pathname = gtk_tree_path_to_string(path);
unsigned selection = decimal(pathname);
g_free(pathname);
self->state.selection = selection;
if(self->onActivate) self->onActivate();
}
static void ListView_change(ListView* self) {
if(self->state.selected == false || self->state.selection != self->selection()) {
static void ListView_change(GtkTreeView* treeView, ListView* self) {
GtkTreeIter iter;
if(!gtk_tree_selection_get_selected(gtk_tree_view_get_selection(treeView), 0, &iter)) return; //should not be possible
char* path = gtk_tree_model_get_string_from_iter(gtk_tree_view_get_model(treeView), &iter);
unsigned selection = decimal(path);
g_free(path);
if(!self->state.selected || self->state.selection != selection) {
self->state.selected = true;
self->state.selection = self->selection();
self->state.selection = selection;
if(self->onChange) self->onChange();
}
}
static void ListView_toggle(GtkCellRendererToggle* cell, gchar* path, ListView* self) {
unsigned row = decimal(path);
self->setChecked(row, !self->checked(row));
if(self->onToggle) self->onToggle(row);
unsigned selection = decimal(path);
self->setChecked(selection, !self->checked(selection));
if(self->onToggle) self->onToggle(selection);
}
void pListView::append(const lstring& text) {
GtkTreeIter iter;
gtk_list_store_append(store, &iter);
for(unsigned n = 0; n < text.size(); n++) gtk_list_store_set(store, &iter, 1 + n * 2 + 1, (const char*)text[n], -1);
for(unsigned n = 0; n < text.size(); n++) {
gtk_list_store_set(store, &iter, 1 + n * 2 + 1, (const char*)text[n], -1);
}
}
void pListView::autoSizeColumns() {
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(subWidget));
}
bool pListView::checked(unsigned row) {
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
GtkTreeIter iter;
bool state;
if(gtk_tree_model_get_iter_from_string(model, &iter, string(row)) == false) return false;
gtk_tree_model_get(model, &iter, 0, &state, -1);
return state;
}
bool pListView::focused() {
return GTK_WIDGET_HAS_FOCUS(subWidget);
}
void pListView::modify(unsigned row, const lstring& text) {
void pListView::remove(unsigned selection) {
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
GtkTreeIter iter;
gtk_tree_model_get_iter_from_string(model, &iter, string(row));
for(unsigned n = 0; n < text.size(); n++) gtk_list_store_set(store, &iter, 1 + n * 2 + 1, (const char*)text[n], -1);
}
void pListView::remove(unsigned row) {
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
GtkTreeIter iter;
gtk_tree_model_get_iter_from_string(model, &iter, string(row));
gtk_tree_model_get_iter_from_string(model, &iter, string(selection));
gtk_list_store_remove(store, &iter);
}
@ -65,30 +61,14 @@ void pListView::reset() {
gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(gtkWidget), 0);
}
bool pListView::selected() {
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget));
return gtk_tree_selection_get_selected(selection, 0, 0);
}
unsigned pListView::selection() {
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget));
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
GtkTreeIter iter;
if(gtk_tree_selection_get_selected(selection, 0, &iter) == false) return listView.state.selection;
char* path = gtk_tree_model_get_string_from_iter(model, &iter);
unsigned row = decimal(path);
g_free(path);
return row;
}
void pListView::setCheckable(bool checkable) {
gtk_cell_renderer_set_visible(column(0).checkbutton, checkable);
}
void pListView::setChecked(unsigned row, bool checked) {
void pListView::setChecked(unsigned selection, bool checked) {
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
GtkTreeIter iter;
gtk_tree_model_get_iter_from_string(model, &iter, string(row));
gtk_tree_model_get_iter_from_string(model, &iter, string(selection));
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, checked, -1);
}
@ -101,15 +81,15 @@ void pListView::setHeaderVisible(bool visible) {
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(subWidget), visible);
}
void pListView::setImage(unsigned row, unsigned column, const nall::image& image) {
void pListView::setImage(unsigned selection, unsigned position, const image& image) {
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
GtkTreeIter iter;
gtk_tree_model_get_iter_from_string(model, &iter, string(row));
gtk_tree_model_get_iter_from_string(model, &iter, string(selection));
if(image.empty() == false) {
GdkPixbuf* pixbuf = CreatePixbuf(image, true);
gtk_list_store_set(store, &iter, 1 + column * 2, pixbuf, -1);
gtk_list_store_set(store, &iter, 1 + position * 2, pixbuf, -1);
} else {
gtk_list_store_set(store, &iter, 1 + column * 2, nullptr, -1);
gtk_list_store_set(store, &iter, 1 + position * 2, nullptr, -1);
}
}
@ -122,13 +102,13 @@ void pListView::setSelected(bool selected) {
}
}
void pListView::setSelection(unsigned row) {
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget));
void pListView::setSelection(unsigned selection) {
GtkTreeSelection* treeSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget));
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
gtk_tree_selection_unselect_all(selection);
gtk_tree_selection_unselect_all(treeSelection);
GtkTreeIter iter;
if(gtk_tree_model_get_iter_from_string(model, &iter, string(row)) == false) return;
gtk_tree_selection_select_iter(selection, &iter);
if(gtk_tree_model_get_iter_from_string(model, &iter, string(selection)) == false) return;
gtk_tree_selection_select_iter(treeSelection, &iter);
//scroll window to selected item
char* path = gtk_tree_model_get_string_from_iter(model, &iter);
@ -138,6 +118,13 @@ void pListView::setSelection(unsigned row) {
g_free(path);
}
void pListView::setText(unsigned selection, unsigned position, string text) {
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
GtkTreeIter iter;
gtk_tree_model_get_iter_from_string(model, &iter, string(selection));
gtk_list_store_set(store, &iter, 1 + position * 2 + 1, (const char*)text, -1);
}
void pListView::constructor() {
gtkWidget = gtk_scrolled_window_new(0, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
@ -190,8 +177,8 @@ void pListView::constructor() {
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(subWidget), headerText.size() >= 2); //two or more columns + checkbutton column
gtk_tree_view_set_search_column(GTK_TREE_VIEW(subWidget), 2);
g_signal_connect_swapped(G_OBJECT(subWidget), "cursor-changed", G_CALLBACK(ListView_change), (gpointer)&listView);
g_signal_connect_swapped(G_OBJECT(subWidget), "row-activated", G_CALLBACK(ListView_activate), (gpointer)&listView);
g_signal_connect(G_OBJECT(subWidget), "cursor-changed", G_CALLBACK(ListView_change), (gpointer)&listView);
g_signal_connect(G_OBJECT(subWidget), "row-activated", G_CALLBACK(ListView_activate), (gpointer)&listView);
gtk_widget_show(subWidget);

View File

@ -1,63 +1,63 @@
namespace phoenix {
static void RadioButton_activate(RadioButton* self) {
static void RadioButton_activate(GtkToggleButton* toggleButton, RadioButton* self) {
self->p.onActivate();
}
bool pRadioButton::checked() {
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtkWidget));
}
Size pRadioButton::minimumSize() {
Size size = pFont::size(widget.state.font, radioButton.state.text);
return {size.width + 28, size.height + 4};
if(radioButton.state.orientation == Orientation::Horizontal) {
size.width += radioButton.state.image.width;
size.height = max(radioButton.state.image.height, size.height);
}
if(radioButton.state.orientation == Orientation::Vertical) {
size.width = max(radioButton.state.image.width, size.width);
size.height += radioButton.state.image.height;
}
return {size.width + 24, size.height + 12};
}
void pRadioButton::setChecked() {
parent().locked = true;
for(auto& item : radioButton.state.group) item.state.checked = false;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), radioButton.state.checked = true);
for(auto& item : radioButton.state.group) {
bool checked = &item == &radioButton;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item.p.gtkWidget), item.state.checked = checked);
}
parent().locked = false;
}
void pRadioButton::setGroup(const group<RadioButton>& group) {
if(&parent() == this) return;
parent().locked = true;
gtk_radio_button_set_group(
GTK_RADIO_BUTTON(gtkWidget),
gtk_radio_button_get_group(GTK_RADIO_BUTTON(parent().gtkWidget))
);
for(auto& item : radioButton.state.group) {
if(item.state.checked) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item.p.gtkWidget), true);
break;
}
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item.p.gtkWidget), item.state.checked);
}
parent().locked = false;
}
void pRadioButton::setText(string text) {
gtk_button_set_label(GTK_BUTTON(gtkWidget), text);
}
void pRadioButton::onActivate() {
if(parent().locked == false) {
bool wasChecked = radioButton.state.checked;
setChecked();
if(wasChecked == false) {
if(radioButton.onActivate) radioButton.onActivate();
}
void pRadioButton::setImage(const image& image, Orientation orientation) {
if(image.empty() == false) {
GtkImage* gtkImage = CreateImage(image);
gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage);
} else {
gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr);
}
switch(orientation) {
case Orientation::Horizontal: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_LEFT); break;
case Orientation::Vertical: gtk_button_set_image_position(GTK_BUTTON(gtkWidget), GTK_POS_TOP); break;
}
}
pRadioButton& pRadioButton::parent() {
if(radioButton.state.group.size()) return radioButton.state.group.first().p;
return *this;
void pRadioButton::setText(string text) {
gtk_button_set_label(GTK_BUTTON(gtkWidget), text);
setFont(widget.state.font);
}
void pRadioButton::constructor() {
gtkWidget = gtk_radio_button_new_with_label(nullptr, "");
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioButton_activate), (gpointer)&radioButton);
gtkWidget = gtk_toggle_button_new();
g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioButton_activate), (gpointer)&radioButton);
setGroup(radioButton.state.group);
setText(radioButton.state.text);
@ -72,4 +72,18 @@ void pRadioButton::orphan() {
constructor();
}
void pRadioButton::onActivate() {
if(parent().locked) return;
bool wasChecked = radioButton.state.checked;
setChecked();
if(!wasChecked) {
if(radioButton.onActivate) radioButton.onActivate();
}
}
pRadioButton& pRadioButton::parent() {
if(radioButton.state.group.size()) return radioButton.state.group.first().p;
return *this;
}
}

View File

@ -0,0 +1,69 @@
namespace phoenix {
static void RadioLabel_activate(GtkToggleButton* toggleButton, RadioLabel* self) {
self->p.onActivate();
}
Size pRadioLabel::minimumSize() {
Size size = pFont::size(widget.state.font, radioLabel.state.text);
return {size.width + 28, size.height + 4};
}
void pRadioLabel::setChecked() {
parent().locked = true;
for(auto& item : radioLabel.state.group) item.state.checked = false;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkWidget), radioLabel.state.checked = true);
parent().locked = false;
}
void pRadioLabel::setGroup(const group<RadioLabel>& group) {
if(&parent() == this) return;
parent().locked = true;
gtk_radio_button_set_group(
GTK_RADIO_BUTTON(gtkWidget),
gtk_radio_button_get_group(GTK_RADIO_BUTTON(parent().gtkWidget))
);
for(auto& item : radioLabel.state.group) {
if(item.state.checked) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(item.p.gtkWidget), true);
break;
}
}
parent().locked = false;
}
void pRadioLabel::setText(string text) {
gtk_button_set_label(GTK_BUTTON(gtkWidget), text);
}
void pRadioLabel::constructor() {
gtkWidget = gtk_radio_button_new_with_label(nullptr, "");
g_signal_connect(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioLabel_activate), (gpointer)&radioLabel);
setGroup(radioLabel.state.group);
setText(radioLabel.state.text);
}
void pRadioLabel::destructor() {
gtk_widget_destroy(gtkWidget);
}
void pRadioLabel::orphan() {
destructor();
constructor();
}
void pRadioLabel::onActivate() {
if(parent().locked) return;
bool wasChecked = radioLabel.state.checked;
setChecked();
if(wasChecked) return;
if(radioLabel.onActivate) radioLabel.onActivate();
}
pRadioLabel& pRadioLabel::parent() {
if(radioLabel.state.group.size()) return radioLabel.state.group.first().p;
return *this;
}
}

View File

@ -0,0 +1,125 @@
namespace phoenix {
static void TabFrame_change(GtkNotebook* notebook, GtkWidget* page, unsigned selection, TabFrame* self) {
self->state.selection = selection;
self->p.synchronizeLayout();
if(self->onChange) self->onChange();
}
void pTabFrame::append(string text, const image& image) {
unsigned selection = tabFrame.state.text.size() - 1;
Tab tab;
tab.child = gtk_fixed_new();
tab.container = gtk_hbox_new(false, 0);
tab.image = gtk_image_new();
tab.title = gtk_label_new(text);
tabs.append(tab);
gtk_widget_show(tab.child);
gtk_widget_show(tab.container);
gtk_widget_show(tab.image);
gtk_widget_show(tab.title);
gtk_box_pack_start(GTK_BOX(tab.container), tab.image, false, false, 0);
gtk_box_pack_start(GTK_BOX(tab.container), tab.title, false, false, 2);
gtk_notebook_append_page(GTK_NOTEBOOK(gtkWidget), tab.child, tab.container);
setFont(widget.state.font);
if(!image.empty()) setImage(selection, image);
}
GtkWidget* pTabFrame::container(Widget& widget) {
Layout* widgetLayout = GetParentWidgetLayout(&widget);
unsigned selection = 0;
for(auto& layout : tabFrame.state.layout) {
if(layout == widgetLayout) return tabs[selection].child;
selection++;
}
return nullptr;
}
Position pTabFrame::containerOffset() {
return {widget.state.geometry.x + 3, widget.state.geometry.y + 28};
}
Position pTabFrame::displacement() {
return {6, 31};
}
void pTabFrame::remove(unsigned selection) {
tabs.remove(selection);
gtk_notebook_remove_page(GTK_NOTEBOOK(gtkWidget), selection);
}
void pTabFrame::setEnabled(bool enabled) {
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setEnabled(layout->enabled());
}
pWidget::setEnabled(enabled);
}
void pTabFrame::setGeometry(Geometry geometry) {
pWidget::setGeometry(geometry);
geometry.x += 1, geometry.width -= 5;
geometry.y += 26, geometry.height -= 31;
for(auto& layout : tabFrame.state.layout) {
if(layout == nullptr) continue;
layout->setGeometry(geometry);
}
synchronizeLayout();
}
void pTabFrame::setImage(unsigned selection, const image& image) {
nall::image copy = image;
unsigned size = pFont::size(widget.state.font, " ").height;
copy.scale(size, size);
GdkPixbuf* pixbuf = CreatePixbuf(copy);
gtk_image_set_from_pixbuf(GTK_IMAGE(tabs[selection].image), pixbuf);
}
void pTabFrame::setSelection(unsigned selection) {
gtk_notebook_set_current_page(GTK_NOTEBOOK(gtkWidget), selection);
}
void pTabFrame::setText(unsigned selection, string text) {
gtk_label_set_text(GTK_LABEL(tabs[selection].title), text);
}
void pTabFrame::setVisible(bool visible) {
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setVisible(layout->visible());
}
pWidget::setVisible(visible);
}
void pTabFrame::constructor() {
gtkWidget = gtk_notebook_new();
gtk_notebook_set_show_border(GTK_NOTEBOOK(gtkWidget), false);
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkWidget), GTK_POS_TOP);
g_signal_connect(G_OBJECT(gtkWidget), "switch-page", G_CALLBACK(TabFrame_change), (gpointer)&tabFrame);
setSelection(tabFrame.state.selection);
}
void pTabFrame::destructor() {
gtk_widget_destroy(gtkWidget);
}
void pTabFrame::orphan() {
destructor();
constructor();
}
void pTabFrame::setFont(string font) {
for(auto& tab : tabs) pFont::setFont(tab.title, font);
}
void pTabFrame::synchronizeLayout() {
unsigned selection = 0;
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setVisible(selection == tabFrame.state.selection);
selection++;
}
}
}

View File

@ -1,19 +1,16 @@
namespace phoenix {
static void VerticalScroller_change(VerticalScroller* self) {
if(self->state.position == self->position()) return;
self->state.position = self->position();
if(self->p.locked == false && self->onChange) self->onChange();
static void VerticalScroller_change(GtkRange* gtkRange, VerticalScroller* self) {
unsigned position = (unsigned)gtk_range_get_value(gtkRange);
if(self->state.position == position) return;
self->state.position = position;
if(!self->p.locked && self->onChange) self->onChange();
}
Size pVerticalScroller::minimumSize() {
return {20, 0};
}
unsigned pVerticalScroller::position() {
return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget));
}
void pVerticalScroller::setLength(unsigned length) {
locked = true;
length += length == 0;
@ -28,7 +25,7 @@ void pVerticalScroller::setPosition(unsigned position) {
void pVerticalScroller::constructor() {
gtkWidget = gtk_vscrollbar_new(0);
g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalScroller_change), (gpointer)&verticalScroller);
g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalScroller_change), (gpointer)&verticalScroller);
setLength(verticalScroller.state.length);
setPosition(verticalScroller.state.position);

View File

@ -1,8 +1,9 @@
namespace phoenix {
static void VerticalSlider_change(VerticalSlider* self) {
if(self->state.position == self->position()) return;
self->state.position = self->position();
static void VerticalSlider_change(GtkRange* gtkRange, VerticalSlider* self) {
unsigned position = (unsigned)gtk_range_get_value(gtkRange);
if(self->state.position == position) return;
self->state.position = position;
if(self->onChange) self->onChange();
}
@ -10,10 +11,6 @@ Size pVerticalSlider::minimumSize() {
return {20, 0};
}
unsigned pVerticalSlider::position() {
return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget));
}
void pVerticalSlider::setLength(unsigned length) {
length += length == 0;
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1));
@ -27,7 +24,7 @@ void pVerticalSlider::setPosition(unsigned position) {
void pVerticalSlider::constructor() {
gtkWidget = gtk_vscale_new_with_range(0, 100, 1);
gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false);
g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)&verticalSlider);
g_signal_connect(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)&verticalSlider);
setLength(verticalSlider.state.length);
setPosition(verticalSlider.state.position);

View File

@ -51,10 +51,10 @@ void pViewport::constructor() {
gtk_widget_add_events(gtkWidget,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Viewport_dropEvent), (gpointer)&viewport);
g_signal_connect(G_OBJECT(gtkWidget), "button_press_event", G_CALLBACK(Viewport_mousePress), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "button_release_event", G_CALLBACK(Viewport_mouseRelease), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "leave_notify_event", G_CALLBACK(Viewport_mouseLeave), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "motion_notify_event", G_CALLBACK(Viewport_mouseMove), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "button-press-event", G_CALLBACK(Viewport_mousePress), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "button-release-event", G_CALLBACK(Viewport_mouseRelease), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "leave-notify-event", G_CALLBACK(Viewport_mouseLeave), (gpointer)this);
g_signal_connect(G_OBJECT(gtkWidget), "motion-notify-event", G_CALLBACK(Viewport_mouseMove), (gpointer)this);
GdkColor color;
color.pixel = 0;

View File

@ -1,7 +1,11 @@
namespace phoenix {
bool pWidget::enabled() {
return gtk_widget_get_sensitive(gtkWidget);
GtkWidget* pWidget::container(Widget& widget) {
return nullptr;
}
Position pWidget::containerOffset() {
return {0, 0};
}
bool pWidget::focused() {
@ -13,8 +17,9 @@ Size pWidget::minimumSize() {
}
void pWidget::setEnabled(bool enabled) {
if(!widget.parent()) enabled = false;
if(widget.state.abstract) enabled = false;
if(sizable.state.layout && sizable.state.layout->enabled() == false) enabled = false;
if(!widget.enabledToAll()) enabled = false;
gtk_widget_set_sensitive(gtkWidget, enabled);
}
@ -27,20 +32,26 @@ void pWidget::setFont(string font) {
}
void pWidget::setGeometry(Geometry geometry) {
if(sizable.window() && sizable.window()->visible()) gtk_fixed_move(GTK_FIXED(sizable.window()->p.formContainer), gtkWidget, geometry.x, geometry.y);
unsigned width = (signed)geometry.width <= 0 ? 1U : geometry.width;
unsigned height = (signed)geometry.height <= 0 ? 1U : geometry.height;
Position displacement = GetDisplacement(&widget);
geometry.x -= displacement.x;
geometry.y -= displacement.y;
if(gtkParent) gtk_fixed_move(GTK_FIXED(gtkParent), gtkWidget, geometry.x, geometry.y);
unsigned width = (signed)geometry.width <= 0 ? 1u : geometry.width;
unsigned height = (signed)geometry.height <= 0 ? 1u : geometry.height;
gtk_widget_set_size_request(gtkWidget, width, height);
if(widget.onSize) widget.onSize();
}
void pWidget::setVisible(bool visible) {
if(!widget.parent()) visible = false;
if(widget.state.abstract) visible = false;
if(sizable.state.layout && sizable.state.layout->visible() == false) visible = false;
if(!widget.visibleToAll()) visible = false;
gtk_widget_set_visible(gtkWidget, visible);
}
void pWidget::constructor() {
if(widget.state.abstract) gtkWidget = gtk_label_new("");
if(widget.state.abstract) gtkWidget = gtk_fixed_new();
}
void pWidget::destructor() {

View File

@ -17,7 +17,9 @@ static gboolean Window_expose(GtkWidget* widget, GdkEvent* event, Window* window
double blue = (double)color.blue / 255.0;
double alpha = (double)color.alpha / 255.0;
if(gdk_screen_is_composited(gdk_screen_get_default())) {
if(gdk_screen_is_composited(gdk_screen_get_default())
&& gdk_screen_get_rgba_colormap(gdk_screen_get_default())
) {
cairo_set_source_rgba(context, red, green, blue, alpha);
} else {
cairo_set_source_rgb(context, red, green, blue);
@ -80,7 +82,7 @@ static gboolean Window_configure(GtkWidget* widget, GdkEvent* event, Window* win
return false;
}
static void Window_dropEvent(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
static void Window_drop(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
GtkSelectionData* data, guint type, guint timestamp, Window* window) {
if(window->state.droppable == false) return;
lstring paths = DropPaths(data);
@ -88,13 +90,13 @@ GtkSelectionData* data, guint type, guint timestamp, Window* window) {
if(window->onDrop) window->onDrop(paths);
}
static gboolean Window_keyPressEvent(GtkWidget* widget, GdkEventKey* event, Window* window) {
static gboolean Window_keyPress(GtkWidget* widget, GdkEventKey* event, Window* window) {
Keyboard::Keycode key = Keysym(event->keyval);
if(key != Keyboard::Keycode::None && window->onKeyPress) window->onKeyPress(key);
return false;
}
static gboolean Window_keyReleaseEvent(GtkWidget* widget, GdkEventKey* event, Window* window) {
static gboolean Window_keyRelease(GtkWidget* widget, GdkEventKey* event, Window* window) {
Keyboard::Keycode key = Keysym(event->keyval);
if(key != Keyboard::Keycode::None && window->onKeyRelease) window->onKeyRelease(key);
return false;
@ -140,8 +142,8 @@ void pWindow::append(Layout& layout) {
}
void pWindow::append(Menu& menu) {
if(window.state.menuFont != "") menu.p.setFont(window.state.menuFont);
else menu.p.setFont("Sans, 8");
if(window.state.menuFont) menu.p.setFont(window.state.menuFont);
else menu.p.setFont(Font::sans(8));
gtk_menu_shell_append(GTK_MENU_SHELL(this->menu), menu.p.widget);
gtk_widget_show(menu.p.widget);
}
@ -151,22 +153,17 @@ void pWindow::append(Widget& widget) {
widget.setFont(window.state.widgetFont);
}
((Sizable&)widget).state.window = &window;
gtk_fixed_put(GTK_FIXED(formContainer), widget.p.gtkWidget, 0, 0);
if(widget.state.font != "") widget.p.setFont(widget.state.font);
else if(window.state.widgetFont != "") widget.p.setFont(window.state.widgetFont);
else widget.p.setFont("Sans, 8");
widget.setVisible(widget.visible());
}
if(HasParentWidget(&widget)) {
widget.p.gtkParent = GetParentWidget(&widget)->p.container(widget);
} else {
widget.p.gtkParent = formContainer;
}
Color pWindow::backgroundColor() {
if(window.state.backgroundColorOverride) return window.state.backgroundColor;
return {
(uint8_t)(settings->window.backgroundColor >> 16),
(uint8_t)(settings->window.backgroundColor >> 8),
(uint8_t)(settings->window.backgroundColor >> 0),
255
};
gtk_fixed_put(GTK_FIXED(widget.p.gtkParent), widget.p.gtkWidget, 0, 0);
if(widget.state.font) widget.p.setFont(widget.state.font);
else if(window.state.widgetFont) widget.p.setFont(window.state.widgetFont);
else widget.p.setFont(Font::sans(8));
widget.setVisible(widget.visible());
}
Geometry pWindow::frameMargin() {
@ -335,11 +332,9 @@ void pWindow::constructor() {
}
}
if(gdk_screen_is_composited(gdk_screen_get_default())) {
gtk_widget_set_colormap(widget, gdk_screen_get_rgba_colormap(gdk_screen_get_default()));
} else {
gtk_widget_set_colormap(widget, gdk_screen_get_rgb_colormap(gdk_screen_get_default()));
}
GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
if(!colormap) colormap = gdk_screen_get_rgb_colormap(gdk_screen_get_default());
if(colormap) gtk_widget_set_colormap(widget, colormap);
gtk_window_set_resizable(GTK_WINDOW(widget), true);
#if GTK_MAJOR_VERSION >= 3
@ -370,18 +365,24 @@ void pWindow::constructor() {
setTitle("");
setResizable(window.state.resizable);
setGeometry(window.state.geometry);
setMenuFont("Sans, 8");
setStatusFont("Sans, 8");
setMenuFont(Font::sans(8));
setStatusFont(Font::sans(8));
g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "drag-data-received", G_CALLBACK(Window_dropEvent), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "drag-data-received", G_CALLBACK(Window_drop), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPress), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPress), (gpointer)&window);
g_signal_connect(G_OBJECT(formContainer), "size-allocate", G_CALLBACK(Window_sizeAllocate), (gpointer)&window);
g_signal_connect(G_OBJECT(formContainer), "size-request", G_CALLBACK(Window_sizeRequest), (gpointer)&window);
window.state.backgroundColor = Color(
(uint8_t)(settings->window.backgroundColor >> 16),
(uint8_t)(settings->window.backgroundColor >> 8),
(uint8_t)(settings->window.backgroundColor >> 0)
);
}
unsigned pWindow::menuHeight() {

View File

@ -1,9 +1,5 @@
namespace phoenix {
bool pCheckItem::checked() {
return qtAction->isChecked();
}
void pCheckItem::setChecked(bool checked) {
qtAction->setChecked(checked);
}
@ -25,7 +21,7 @@ void pCheckItem::destructor() {
}
void pCheckItem::onToggle() {
checkItem.state.checked = checked();
checkItem.state.checked = qtAction->isChecked();
if(checkItem.onToggle) checkItem.onToggle();
}

View File

@ -1,9 +1,5 @@
namespace phoenix {
bool pRadioItem::checked() {
return qtAction->isChecked();
}
void pRadioItem::setChecked() {
locked = true;
for(auto& item : radioItem.state.group) {
@ -37,9 +33,9 @@ void pRadioItem::destructor() {
}
void pRadioItem::onActivate() {
if(radioItem.state.checked == false) {
if(!radioItem.state.checked) {
setChecked();
if(locked == false && radioItem.onActivate) radioItem.onActivate();
if(!locked && radioItem.onActivate) radioItem.onActivate();
}
}

View File

@ -24,8 +24,10 @@
#include "widget/button.cpp"
#include "widget/canvas.cpp"
#include "widget/check-button.cpp"
#include "widget/check-label.cpp"
#include "widget/combo-button.cpp"
#include "widget/console.cpp"
#include "widget/frame.cpp"
#include "widget/hex-edit.cpp"
#include "widget/horizontal-scroller.cpp"
#include "widget/horizontal-slider.cpp"
@ -34,6 +36,8 @@
#include "widget/list-view.cpp"
#include "widget/progress-bar.cpp"
#include "widget/radio-button.cpp"
#include "widget/radio-label.cpp"
#include "widget/tab-frame.cpp"
#include "widget/text-edit.cpp"
#include "widget/vertical-scroller.cpp"
#include "widget/vertical-slider.cpp"

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'platform.moc.hpp'
**
** Created: Tue Nov 5 18:38:24 2013
** Created: Fri Nov 22 09:50:07 2013
** by: The Qt Meta Object Compiler version 63 (Qt 4.8.2)
**
** WARNING! All changes made in this file will be lost!
@ -536,13 +536,14 @@ static const uint qt_meta_data_phoenix__pCheckButton[] = {
0, // signalCount
// slots: signature, parameters, type, tag, flags
23, 22, 22, 22, 0x0a,
31, 23, 22, 22, 0x0a,
0 // eod
};
static const char qt_meta_stringdata_phoenix__pCheckButton[] = {
"phoenix::pCheckButton\0\0onToggle()\0"
"phoenix::pCheckButton\0\0checked\0"
"onToggle(bool)\0"
};
void phoenix::pCheckButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
@ -551,11 +552,10 @@ void phoenix::pCheckButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c
Q_ASSERT(staticMetaObject.cast(_o));
pCheckButton *_t = static_cast<pCheckButton *>(_o);
switch (_id) {
case 0: _t->onToggle(); break;
case 0: _t->onToggle((*reinterpret_cast< bool(*)>(_a[1]))); break;
default: ;
}
}
Q_UNUSED(_a);
}
const QMetaObjectExtraData phoenix::pCheckButton::staticMetaObjectExtraData = {
@ -598,6 +598,82 @@ int phoenix::pCheckButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
}
return _id;
}
static const uint qt_meta_data_phoenix__pCheckLabel[] = {
// content:
6, // revision
0, // classname
0, 0, // classinfo
1, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: signature, parameters, type, tag, flags
22, 21, 21, 21, 0x0a,
0 // eod
};
static const char qt_meta_stringdata_phoenix__pCheckLabel[] = {
"phoenix::pCheckLabel\0\0onToggle()\0"
};
void phoenix::pCheckLabel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
Q_ASSERT(staticMetaObject.cast(_o));
pCheckLabel *_t = static_cast<pCheckLabel *>(_o);
switch (_id) {
case 0: _t->onToggle(); break;
default: ;
}
}
Q_UNUSED(_a);
}
const QMetaObjectExtraData phoenix::pCheckLabel::staticMetaObjectExtraData = {
0, qt_static_metacall
};
const QMetaObject phoenix::pCheckLabel::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_phoenix__pCheckLabel,
qt_meta_data_phoenix__pCheckLabel, &staticMetaObjectExtraData }
};
#ifdef Q_NO_DATA_RELOCATION
const QMetaObject &phoenix::pCheckLabel::getStaticMetaObject() { return staticMetaObject; }
#endif //Q_NO_DATA_RELOCATION
const QMetaObject *phoenix::pCheckLabel::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
}
void *phoenix::pCheckLabel::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_phoenix__pCheckLabel))
return static_cast<void*>(const_cast< pCheckLabel*>(this));
if (!strcmp(_clname, "pWidget"))
return static_cast< pWidget*>(const_cast< pCheckLabel*>(this));
return QObject::qt_metacast(_clname);
}
int phoenix::pCheckLabel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 1)
qt_static_metacall(this, _c, _id, _a);
_id -= 1;
}
return _id;
}
static const uint qt_meta_data_phoenix__pComboButton[] = {
// content:
@ -737,6 +813,69 @@ int phoenix::pConsole::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id;
return _id;
}
static const uint qt_meta_data_phoenix__pFrame[] = {
// content:
6, // revision
0, // classname
0, 0, // classinfo
0, 0, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
0 // eod
};
static const char qt_meta_stringdata_phoenix__pFrame[] = {
"phoenix::pFrame\0"
};
void phoenix::pFrame::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
Q_UNUSED(_o);
Q_UNUSED(_id);
Q_UNUSED(_c);
Q_UNUSED(_a);
}
const QMetaObjectExtraData phoenix::pFrame::staticMetaObjectExtraData = {
0, qt_static_metacall
};
const QMetaObject phoenix::pFrame::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_phoenix__pFrame,
qt_meta_data_phoenix__pFrame, &staticMetaObjectExtraData }
};
#ifdef Q_NO_DATA_RELOCATION
const QMetaObject &phoenix::pFrame::getStaticMetaObject() { return staticMetaObject; }
#endif //Q_NO_DATA_RELOCATION
const QMetaObject *phoenix::pFrame::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
}
void *phoenix::pFrame::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_phoenix__pFrame))
return static_cast<void*>(const_cast< pFrame*>(this));
if (!strcmp(_clname, "pWidget"))
return static_cast< pWidget*>(const_cast< pFrame*>(this));
return QObject::qt_metacast(_clname);
}
int phoenix::pFrame::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
return _id;
}
static const uint qt_meta_data_phoenix__pHexEdit[] = {
// content:
@ -1125,6 +1264,82 @@ int phoenix::pListView::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
}
return _id;
}
static const uint qt_meta_data_phoenix__pRadioLabel[] = {
// content:
6, // revision
0, // classname
0, 0, // classinfo
1, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: signature, parameters, type, tag, flags
22, 21, 21, 21, 0x0a,
0 // eod
};
static const char qt_meta_stringdata_phoenix__pRadioLabel[] = {
"phoenix::pRadioLabel\0\0onActivate()\0"
};
void phoenix::pRadioLabel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
Q_ASSERT(staticMetaObject.cast(_o));
pRadioLabel *_t = static_cast<pRadioLabel *>(_o);
switch (_id) {
case 0: _t->onActivate(); break;
default: ;
}
}
Q_UNUSED(_a);
}
const QMetaObjectExtraData phoenix::pRadioLabel::staticMetaObjectExtraData = {
0, qt_static_metacall
};
const QMetaObject phoenix::pRadioLabel::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_phoenix__pRadioLabel,
qt_meta_data_phoenix__pRadioLabel, &staticMetaObjectExtraData }
};
#ifdef Q_NO_DATA_RELOCATION
const QMetaObject &phoenix::pRadioLabel::getStaticMetaObject() { return staticMetaObject; }
#endif //Q_NO_DATA_RELOCATION
const QMetaObject *phoenix::pRadioLabel::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
}
void *phoenix::pRadioLabel::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_phoenix__pRadioLabel))
return static_cast<void*>(const_cast< pRadioLabel*>(this));
if (!strcmp(_clname, "pWidget"))
return static_cast< pWidget*>(const_cast< pRadioLabel*>(this));
return QObject::qt_metacast(_clname);
}
int phoenix::pRadioLabel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 1)
qt_static_metacall(this, _c, _id, _a);
_id -= 1;
}
return _id;
}
static const uint qt_meta_data_phoenix__pRadioButton[] = {
// content:
@ -1201,6 +1416,82 @@ int phoenix::pRadioButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
}
return _id;
}
static const uint qt_meta_data_phoenix__pTabFrame[] = {
// content:
6, // revision
0, // classname
0, 0, // classinfo
1, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: signature, parameters, type, tag, flags
30, 20, 19, 19, 0x0a,
0 // eod
};
static const char qt_meta_stringdata_phoenix__pTabFrame[] = {
"phoenix::pTabFrame\0\0selection\0"
"onChange(int)\0"
};
void phoenix::pTabFrame::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
Q_ASSERT(staticMetaObject.cast(_o));
pTabFrame *_t = static_cast<pTabFrame *>(_o);
switch (_id) {
case 0: _t->onChange((*reinterpret_cast< int(*)>(_a[1]))); break;
default: ;
}
}
}
const QMetaObjectExtraData phoenix::pTabFrame::staticMetaObjectExtraData = {
0, qt_static_metacall
};
const QMetaObject phoenix::pTabFrame::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_phoenix__pTabFrame,
qt_meta_data_phoenix__pTabFrame, &staticMetaObjectExtraData }
};
#ifdef Q_NO_DATA_RELOCATION
const QMetaObject &phoenix::pTabFrame::getStaticMetaObject() { return staticMetaObject; }
#endif //Q_NO_DATA_RELOCATION
const QMetaObject *phoenix::pTabFrame::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
}
void *phoenix::pTabFrame::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_phoenix__pTabFrame))
return static_cast<void*>(const_cast< pTabFrame*>(this));
if (!strcmp(_clname, "pWidget"))
return static_cast< pWidget*>(const_cast< pTabFrame*>(this));
return QObject::qt_metacast(_clname);
}
int phoenix::pTabFrame::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 1)
qt_static_metacall(this, _c, _id, _a);
_id -= 1;
}
return _id;
}
static const uint qt_meta_data_phoenix__pTextEdit[] = {
// content:

View File

@ -94,7 +94,7 @@ public:
QTimer* qtTimer;
void setEnabled(bool enabled);
void setInterval(unsigned milliseconds);
void setInterval(unsigned interval);
pTimer(Timer& timer) : pObject(timer), timer(timer) {}
void constructor();
@ -132,7 +132,6 @@ public:
void append(Layout& layout);
void append(Menu& menu);
void append(Widget& widget);
Color backgroundColor();
Geometry frameMargin();
bool focused();
Geometry geometry();
@ -222,7 +221,6 @@ public:
CheckItem& checkItem;
QAction* qtAction;
bool checked();
void setChecked(bool checked);
void setText(string text);
@ -242,7 +240,6 @@ public:
QAction* qtAction;
QActionGroup* qtGroup;
bool checked();
void setChecked();
void setGroup(const group<RadioItem>& group);
void setText(string text);
@ -279,11 +276,11 @@ struct pWidget : public pSizable {
bool focused();
virtual Size minimumSize();
void setEnabled(bool enabled);
virtual void setEnabled(bool enabled);
void setFocused();
void setFont(string font);
void setGeometry(Geometry geometry);
void setVisible(bool visible);
virtual void setGeometry(Geometry geometry);
virtual void setVisible(bool visible);
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
void constructor();
@ -317,7 +314,9 @@ struct pCanvas : public QObject, public pWidget {
public:
Canvas& canvas;
QImage* qtImage;
QImage* surface = nullptr;
unsigned surfaceWidth = 0;
unsigned surfaceHeight = 0;
struct QtCanvas : public QWidget {
pCanvas& self;
void dragEnterEvent(QDragEnterEvent*);
@ -332,13 +331,16 @@ public:
QtCanvas* qtCanvas;
void setDroppable(bool droppable);
void setGeometry(Geometry geometry);
void setMode(Canvas::Mode mode);
void setSize(Size size);
void update();
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
void constructor();
void destructor();
void orphan();
void rasterize();
void release();
public slots:
};
@ -348,14 +350,34 @@ struct pCheckButton : public QObject, public pWidget {
public:
CheckButton& checkButton;
QCheckBox* qtCheckButton;
QToolButton* qtCheckButton;
Size minimumSize();
void setChecked(bool checked);
void setImage(const image& image, Orientation orientation);
void setText(string text);
pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {}
void constructor();
void destructor();
void orphan();
public slots:
void onToggle(bool checked);
};
struct pCheckLabel : public QObject, public pWidget {
Q_OBJECT
public:
CheckLabel& checkLabel;
QCheckBox* qtCheckLabel;
bool checked();
Size minimumSize();
void setChecked(bool checked);
void setText(string text);
pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {}
pCheckLabel(CheckLabel& checkLabel) : pWidget(checkLabel), checkLabel(checkLabel) {}
void constructor();
void destructor();
void orphan();
@ -372,12 +394,12 @@ public:
QComboBox* qtComboButton;
void append(string text);
void modify(unsigned row, string text);
void remove(unsigned row);
Size minimumSize();
void remove(unsigned selection);
void reset();
unsigned selection();
void setSelection(unsigned row);
void setSelection(unsigned selection);
void setText(unsigned selection, string text);
pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {}
void constructor();
@ -411,6 +433,24 @@ public:
void keyPressEvent(QKeyEvent*);
};
struct pFrame : public QObject, public pWidget {
Q_OBJECT
public:
Frame& frame;
QGroupBox* qtFrame;
void setEnabled(bool enabled);
void setGeometry(Geometry geometry);
void setText(string text);
void setVisible(bool visible);
pFrame(Frame& frame) : pWidget(frame), frame(frame) {}
void constructor();
void destructor();
void orphan();
};
struct pHexEdit : public QObject, public pWidget {
Q_OBJECT
@ -459,7 +499,6 @@ public:
QScrollBar* qtScroller;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
@ -480,7 +519,6 @@ public:
QSlider* qtSlider;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
@ -537,19 +575,16 @@ public:
void append(const lstring& text);
void autoSizeColumns();
bool checked(unsigned row);
void modify(unsigned row, const lstring& text);
void remove(unsigned row);
void remove(unsigned selection);
void reset();
bool selected();
unsigned selection();
void setCheckable(bool checkable);
void setChecked(unsigned row, bool checked);
void setChecked(unsigned selection, bool checked);
void setHeaderText(const lstring& text);
void setHeaderVisible(bool visible);
void setImage(unsigned row, unsigned column, const nall::image& image);
void setImage(unsigned selection, unsigned position, const image& image);
void setSelected(bool selected);
void setSelection(unsigned row);
void setSelection(unsigned selection);
void setText(unsigned selection, unsigned position, string text);
pListView(ListView& listView) : pWidget(listView), listView(listView) {}
void constructor();
@ -575,17 +610,40 @@ struct pProgressBar : public pWidget {
void orphan();
};
struct pRadioLabel : public QObject, public pWidget {
Q_OBJECT
public:
RadioLabel& radioLabel;
QRadioButton* qtRadioLabel;
bool checked();
Size minimumSize();
void setChecked();
void setGroup(const group<RadioLabel>& group);
void setText(string text);
pRadioLabel(RadioLabel& radioLabel) : pWidget(radioLabel), radioLabel(radioLabel) {}
pRadioLabel& parent();
void constructor();
void destructor();
void orphan();
public slots:
void onActivate();
};
struct pRadioButton : public QObject, public pWidget {
Q_OBJECT
public:
RadioButton& radioButton;
QRadioButton* qtRadioButton;
QToolButton* qtRadioButton;
bool checked();
Size minimumSize();
void setChecked();
void setGroup(const group<RadioButton>& group);
void setImage(const image& image, Orientation orientation);
void setText(string text);
pRadioButton(RadioButton& radioButton) : pWidget(radioButton), radioButton(radioButton) {}
@ -598,6 +656,32 @@ public slots:
void onActivate();
};
struct pTabFrame : public QObject, public pWidget {
Q_OBJECT
public:
TabFrame& tabFrame;
QTabWidget* qtTabFrame;
void append(string text, const image& image);
void remove(unsigned selection);
void setEnabled(bool enabled);
void setGeometry(Geometry geometry);
void setImage(unsigned selection, const image& image);
void setSelection(unsigned selection);
void setText(unsigned selection, string text);
void setVisible(bool visible);
pTabFrame(TabFrame& tabFrame) : pWidget(tabFrame), tabFrame(tabFrame) {}
void constructor();
void destructor();
void orphan();
void synchronizeLayout();
public slots:
void onChange(int selection);
};
struct pTextEdit : public QObject, public pWidget {
Q_OBJECT
@ -628,7 +712,6 @@ public:
QScrollBar* qtScroller;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
@ -649,7 +732,6 @@ public:
QSlider* qtSlider;
Size minimumSize();
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);

View File

@ -8,8 +8,8 @@ void pTimer::setEnabled(bool enabled) {
}
}
void pTimer::setInterval(unsigned milliseconds) {
qtTimer->setInterval(milliseconds);
void pTimer::setInterval(unsigned interval) {
qtTimer->setInterval(interval);
}
void pTimer::constructor() {

View File

@ -4,32 +4,48 @@ void pCanvas::setDroppable(bool droppable) {
qtCanvas->setAcceptDrops(droppable);
}
void pCanvas::setSize(Size size) {
delete qtImage;
qtImage = new QImage(size.width, size.height, QImage::Format_ARGB32);
void pCanvas::setGeometry(Geometry geometry) {
if(canvas.state.width == 0 || canvas.state.height == 0) rasterize();
unsigned width = canvas.state.width;
unsigned height = canvas.state.height;
if(width == 0) width = widget.state.geometry.width;
if(height == 0) height = widget.state.geometry.height;
if(width < geometry.width) {
geometry.x += (geometry.width - width) / 2;
geometry.width = width;
}
if(height < geometry.height) {
geometry.y += (geometry.height - height) / 2;
geometry.height = height;
}
pWidget::setGeometry(geometry);
}
void pCanvas::update() {
uint32_t* dp = (uint32_t*)qtImage->bits(), *sp = (uint32_t*)canvas.state.data;
for(unsigned n = 0; n < canvas.state.width * canvas.state.height; n++) *dp++ = 0xff000000 | *sp++;
void pCanvas::setMode(Canvas::Mode mode) {
rasterize();
qtCanvas->update();
}
void pCanvas::setSize(Size size) {
rasterize();
qtCanvas->update();
}
void pCanvas::constructor() {
qtWidget = qtCanvas = new QtCanvas(*this);
qtCanvas->setMouseTracking(true);
qtImage = new QImage(canvas.state.width, canvas.state.height, QImage::Format_ARGB32);
memcpy(qtImage->bits(), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
pWidget::synchronizeState();
update();
rasterize(), qtCanvas->update();
}
void pCanvas::destructor() {
release();
delete qtCanvas;
delete qtImage;
qtWidget = qtCanvas = nullptr;
qtImage = nullptr;
}
void pCanvas::orphan() {
@ -37,6 +53,53 @@ void pCanvas::orphan() {
constructor();
}
void pCanvas::rasterize() {
unsigned width = canvas.state.width;
unsigned height = canvas.state.height;
if(width == 0) width = widget.state.geometry.width;
if(height == 0) height = widget.state.geometry.height;
if(canvas.state.mode != Canvas::Mode::Color) {
if(width != surfaceWidth || height != surfaceHeight) release();
if(!surface) surface = new QImage(width, height, QImage::Format_ARGB32);
}
if(canvas.state.mode == Canvas::Mode::Gradient) {
nall::image image;
image.allocate(width, height);
image.gradient(
canvas.state.gradient[0].argb(), canvas.state.gradient[1].argb(), canvas.state.gradient[2].argb(), canvas.state.gradient[3].argb()
);
memcpy(surface->bits(), image.data, image.size);
}
if(canvas.state.mode == Canvas::Mode::Image) {
nall::image image = canvas.state.image;
image.scale(width, height);
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
memcpy(surface->bits(), image.data, image.size);
}
if(canvas.state.mode == Canvas::Mode::Data) {
if(width == canvas.state.width && height == canvas.state.height) {
memcpy(surface->bits(), canvas.state.data, width * height * sizeof(uint32_t));
} else {
memset(surface->bits(), 0x00, width * height * sizeof(uint32_t));
}
}
surfaceWidth = width;
surfaceHeight = height;
}
void pCanvas::release() {
if(surface == nullptr) return;
delete surface;
surface = nullptr;
surfaceWidth = 0;
surfaceHeight = 0;
}
void pCanvas::QtCanvas::dragEnterEvent(QDragEnterEvent* event) {
if(event->mimeData()->hasUrls()) {
event->acceptProposedAction();
@ -76,15 +139,14 @@ void pCanvas::QtCanvas::mouseReleaseEvent(QMouseEvent* event) {
}
void pCanvas::QtCanvas::paintEvent(QPaintEvent* event) {
Canvas& canvas = self.canvas;
QPainter painter(self.qtCanvas);
painter.drawImage(0, 0, *self.qtImage);
//this will scale the source image to fit the target widget size (nearest-neighbor):
//painter.drawImage(
// QRect(0, 0, geometry().width(), geometry().height()),
// *self.qtImage,
// QRect(0, 0, self.canvas.state.width, self.canvas.state.height)
//);
if(canvas.state.mode == Canvas::Mode::Color) {
painter.fillRect(event->rect(), QBrush(QColor(canvas.state.color.red, canvas.state.color.green, canvas.state.color.blue, canvas.state.color.alpha)));
} else {
painter.drawImage(0, 0, *self.surface);
}
}
pCanvas::QtCanvas::QtCanvas(pCanvas& self) : self(self) {

View File

@ -1,12 +1,19 @@
namespace phoenix {
bool pCheckButton::checked() {
return qtCheckButton->isChecked();
}
Size pCheckButton::minimumSize() {
Size size = pFont::size(qtWidget->font(), checkButton.state.text);
return {size.width + 26, size.height + 6};
if(checkButton.state.orientation == Orientation::Horizontal) {
size.width += checkButton.state.image.width;
size.height = max(checkButton.state.image.height, size.height);
}
if(checkButton.state.orientation == Orientation::Vertical) {
size.width = max(checkButton.state.image.width, size.width);
size.height += checkButton.state.image.height;
}
return {size.width + 20, size.height + 12};
}
void pCheckButton::setChecked(bool checked) {
@ -15,13 +22,25 @@ void pCheckButton::setChecked(bool checked) {
locked = false;
}
void pCheckButton::setImage(const image& image, Orientation orientation) {
qtCheckButton->setIconSize(QSize(image.width, image.height));
qtCheckButton->setIcon(CreateIcon(image));
qtCheckButton->setStyleSheet("text-align: top;");
switch(orientation) {
case Orientation::Horizontal: qtCheckButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
case Orientation::Vertical: qtCheckButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;
}
}
void pCheckButton::setText(string text) {
qtCheckButton->setText(QString::fromUtf8(text));
}
void pCheckButton::constructor() {
qtWidget = qtCheckButton = new QCheckBox;
connect(qtCheckButton, SIGNAL(stateChanged(int)), SLOT(onToggle()));
qtWidget = qtCheckButton = new QToolButton;
qtCheckButton->setCheckable(true);
qtCheckButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
connect(qtCheckButton, SIGNAL(toggled(bool)), SLOT(onToggle(bool)));
pWidget::synchronizeState();
setChecked(checkButton.state.checked);
@ -29,8 +48,6 @@ void pCheckButton::constructor() {
}
void pCheckButton::destructor() {
delete qtCheckButton;
qtWidget = qtCheckButton = nullptr;
}
void pCheckButton::orphan() {
@ -38,9 +55,9 @@ void pCheckButton::orphan() {
constructor();
}
void pCheckButton::onToggle() {
checkButton.state.checked = checked();
if(locked == false && checkButton.onToggle) checkButton.onToggle();
void pCheckButton::onToggle(bool checked) {
checkButton.state.checked = checked;
if(!locked && checkButton.onToggle) checkButton.onToggle();
}
}

View File

@ -0,0 +1,42 @@
namespace phoenix {
Size pCheckLabel::minimumSize() {
Size size = pFont::size(qtWidget->font(), checkLabel.state.text);
return {size.width + 26, size.height + 6};
}
void pCheckLabel::setChecked(bool checked) {
locked = true;
qtCheckLabel->setChecked(checked);
locked = false;
}
void pCheckLabel::setText(string text) {
qtCheckLabel->setText(QString::fromUtf8(text));
}
void pCheckLabel::constructor() {
qtWidget = qtCheckLabel = new QCheckBox;
connect(qtCheckLabel, SIGNAL(stateChanged(int)), SLOT(onToggle()));
pWidget::synchronizeState();
setChecked(checkLabel.state.checked);
setText(checkLabel.state.text);
}
void pCheckLabel::destructor() {
delete qtCheckLabel;
qtWidget = qtCheckLabel = nullptr;
}
void pCheckLabel::orphan() {
destructor();
constructor();
}
void pCheckLabel::onToggle() {
checkLabel.state.checked = qtCheckLabel->isChecked();
if(!locked && checkLabel.onToggle) checkLabel.onToggle();
}
}

View File

@ -13,16 +13,12 @@ Size pComboButton::minimumSize() {
return {maximumWidth + 32, size.height + 12};
}
void pComboButton::modify(unsigned row, string text) {
qtComboButton->setItemText(row, text);
}
void pComboButton::remove(unsigned row) {
void pComboButton::remove(unsigned selection) {
locked = true;
unsigned position = selection();
qtComboButton->removeItem(row);
if(position == row) qtComboButton->setCurrentIndex(0);
qtComboButton->removeItem(selection);
locked = false;
if(selection == comboButton.state.selection) comboButton.setSelection(0);
}
void pComboButton::reset() {
@ -31,15 +27,14 @@ void pComboButton::reset() {
locked = false;
}
unsigned pComboButton::selection() {
signed index = qtComboButton->currentIndex();
return index >= 0 ? index : 0;
void pComboButton::setSelection(unsigned selection) {
locked = true;
qtComboButton->setCurrentIndex(selection);
locked = false;
}
void pComboButton::setSelection(unsigned row) {
locked = true;
qtComboButton->setCurrentIndex(row);
locked = false;
void pComboButton::setText(unsigned selection, string text) {
qtComboButton->setItemText(selection, text);
}
void pComboButton::constructor() {
@ -51,7 +46,7 @@ void pComboButton::constructor() {
locked = true;
for(auto& text : comboButton.state.text) append(text);
locked = false;
setSelection(selection);
comboButton.setSelection(selection);
}
void pComboButton::destructor() {
@ -65,8 +60,8 @@ void pComboButton::orphan() {
}
void pComboButton::onChange() {
comboButton.state.selection = selection();
if(locked == false && comboButton.onChange) comboButton.onChange();
comboButton.state.selection = qtComboButton->currentIndex();
if(!locked && comboButton.onChange) comboButton.onChange();
}
}

View File

@ -0,0 +1,44 @@
namespace phoenix {
void pFrame::setEnabled(bool enabled) {
if(frame.state.layout) frame.state.layout->setEnabled(frame.state.layout->enabled());
pWidget::setEnabled(enabled);
}
void pFrame::setGeometry(Geometry geometry) {
pWidget::setGeometry(geometry);
if(frame.state.layout == nullptr) return;
Size size = pFont::size(widget.state.font, frame.state.text);
if(frame.state.text.empty()) size.height = 8;
geometry.x += 1, geometry.width -= 3;
geometry.y += size.height, geometry.height -= size.height + 1;
frame.state.layout->setGeometry(geometry);
}
void pFrame::setText(string text) {
qtFrame->setTitle(QString::fromUtf8(text));
}
void pFrame::setVisible(bool visible) {
if(frame.state.layout) frame.state.layout->setVisible(frame.state.layout->visible());
pWidget::setVisible(visible);
}
void pFrame::constructor() {
qtWidget = qtFrame = new QGroupBox;
pWidget::synchronizeState();
setText(frame.state.text);
}
void pFrame::destructor() {
delete qtFrame;
qtWidget = qtFrame = nullptr;
}
void pFrame::orphan() {
destructor();
constructor();
}
}

View File

@ -4,10 +4,6 @@ Size pHorizontalScroller::minimumSize() {
return {0, 15};
}
unsigned pHorizontalScroller::position() {
return qtScroller->value();
}
void pHorizontalScroller::setLength(unsigned length) {
length += length == 0;
qtScroller->setRange(0, length - 1);
@ -40,7 +36,7 @@ void pHorizontalScroller::orphan() {
}
void pHorizontalScroller::onChange() {
horizontalScroller.state.position = position();
horizontalScroller.state.position = qtScroller->value();
if(horizontalScroller.onChange) horizontalScroller.onChange();
}

View File

@ -4,10 +4,6 @@ Size pHorizontalSlider::minimumSize() {
return {0, 20};
}
unsigned pHorizontalSlider::position() {
return qtSlider->value();
}
void pHorizontalSlider::setLength(unsigned length) {
length += length == 0;
qtSlider->setRange(0, length - 1);
@ -40,7 +36,7 @@ void pHorizontalSlider::orphan() {
}
void pHorizontalSlider::onChange() {
horizontalSlider.state.position = position();
horizontalSlider.state.position = qtSlider->value();
if(horizontalSlider.onChange) horizontalSlider.onChange();
}

View File

@ -7,8 +7,8 @@ void pListView::append(const lstring& text) {
item->setData(0, Qt::UserRole, (unsigned)items.size());
if(listView.state.checkable) item->setCheckState(0, Qt::Unchecked);
for(unsigned n = 0; n < text.size(); n++) {
item->setText(n, QString::fromUtf8(text[n]));
for(unsigned position = 0; position < text.size(); position++) {
item->setText(position, QString::fromUtf8(text[position]));
}
locked = false;
}
@ -17,24 +17,9 @@ void pListView::autoSizeColumns() {
for(unsigned n = 0; n < listView.state.headerText.size(); n++) qtListView->resizeColumnToContents(n);
}
bool pListView::checked(unsigned row) {
QTreeWidgetItem* item = qtListView->topLevelItem(row);
return item ? item->checkState(0) == Qt::Checked : false;
}
void pListView::modify(unsigned row, const lstring& text) {
void pListView::remove(unsigned selection) {
locked = true;
QTreeWidgetItem* item = qtListView->topLevelItem(row);
if(item == nullptr) return;
for(unsigned n = 0; n < text.size(); n++) {
item->setText(n, QString::fromUtf8(text[n]));
}
locked = false;
}
void pListView::remove(unsigned row) {
locked = true;
QTreeWidgetItem* item = qtListView->topLevelItem(row);
QTreeWidgetItem* item = qtListView->topLevelItem(selection);
if(item == nullptr) return;
delete item;
locked = false;
@ -44,17 +29,6 @@ void pListView::reset() {
qtListView->clear();
}
bool pListView::selected() {
QTreeWidgetItem* item = qtListView->currentItem();
return (item && item->isSelected() == true);
}
unsigned pListView::selection() {
QTreeWidgetItem* item = qtListView->currentItem();
if(item == 0) return 0;
return item->data(0, Qt::UserRole).toUInt();
}
void pListView::setCheckable(bool checkable) {
if(checkable) {
auto items = qtListView->findItems("", Qt::MatchContains);
@ -62,9 +36,9 @@ void pListView::setCheckable(bool checkable) {
}
}
void pListView::setChecked(unsigned row, bool checked) {
void pListView::setChecked(unsigned selection, bool checked) {
locked = true;
QTreeWidgetItem* item = qtListView->topLevelItem(row);
QTreeWidgetItem* item = qtListView->topLevelItem(selection);
if(item) item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
locked = false;
}
@ -84,11 +58,11 @@ void pListView::setHeaderVisible(bool visible) {
autoSizeColumns();
}
void pListView::setImage(unsigned row, unsigned column, const nall::image& image) {
QTreeWidgetItem* item = qtListView->topLevelItem(row);
void pListView::setImage(unsigned selection, unsigned position, const nall::image& image) {
QTreeWidgetItem* item = qtListView->topLevelItem(selection);
if(item) {
if(image.empty() == 0) item->setIcon(column, CreateIcon(image));
if(image.empty() == 1) item->setIcon(column, QIcon());
if(image.empty() == 0) item->setIcon(position, CreateIcon(image));
if(image.empty() == 1) item->setIcon(position, QIcon());
}
}
@ -97,18 +71,19 @@ void pListView::setSelected(bool selected) {
if(item) item->setSelected(selected);
}
void pListView::setSelection(unsigned row) {
void pListView::setSelection(unsigned selection) {
locked = true;
QTreeWidgetItem* item = qtListView->currentItem();
if(item) item->setSelected(false);
qtListView->setCurrentItem(0);
auto items = qtListView->findItems("", Qt::MatchContains);
for(unsigned n = 0; n < items.size(); n++) {
if(items[n]->data(0, Qt::UserRole).toUInt() == row) {
qtListView->setCurrentItem(items[n]);
break;
}
}
item = qtListView->topLevelItem(selection);
if(item) qtListView->setCurrentItem(item);
locked = false;
}
void pListView::setText(unsigned selection, unsigned position, string text) {
locked = true;
QTreeWidgetItem* item = qtListView->topLevelItem(selection);
if(item) item->setText(position, QString::fromUtf8(text));
locked = false;
}
@ -151,18 +126,25 @@ void pListView::onActivate() {
}
void pListView::onChange(QTreeWidgetItem* item) {
//Qt bug workaround: clicking items with mouse does not mark items as selected
if(item) item->setSelected(true);
listView.state.selected = selected();
if(listView.state.selected) listView.state.selection = selection();
if(locked == false && listView.onChange) listView.onChange();
bool selected = listView.state.selected;
unsigned selection = listView.state.selection;
if(item) {
item->setSelected(true); //Qt bug workaround: clicking items with mouse does not mark items as selected
listView.state.selected = true;
listView.state.selection = item->data(0, Qt::UserRole).toUInt();
} else {
listView.state.selected = false;
listView.state.selection = 0;
}
if(selected != listView.state.selected || selection != listView.state.selection) {
if(!locked && listView.onChange) listView.onChange();
}
}
void pListView::onToggle(QTreeWidgetItem* item) {
unsigned row = item->data(0, Qt::UserRole).toUInt();
bool checkState = checked(row);
listView.state.checked[row] = checkState;
if(locked == false && listView.onToggle) listView.onToggle(row);
unsigned selection = item->data(0, Qt::UserRole).toUInt();
listView.state.checked[selection] = (item->checkState(0) == Qt::Checked);
if(!locked && listView.onToggle) listView.onToggle(selection);
}
}

View File

@ -1,20 +1,27 @@
namespace phoenix {
bool pRadioButton::checked() {
return qtRadioButton->isChecked();
}
Size pRadioButton::minimumSize() {
Size size = pFont::size(qtWidget->font(), radioButton.state.text);
return {size.width + 26, size.height + 6};
if(radioButton.state.orientation == Orientation::Horizontal) {
size.width += radioButton.state.image.width;
size.height = max(radioButton.state.image.height, size.height);
}
if(radioButton.state.orientation == Orientation::Vertical) {
size.width = max(radioButton.state.image.width, size.width);
size.height += radioButton.state.image.height;
}
return {size.width + 20, size.height + 12};
}
void pRadioButton::setChecked() {
parent().locked = true;
for(auto &item : radioButton.state.group) {
item.p.qtRadioButton->setChecked(item.state.checked = false);
for(auto& item : radioButton.state.group) {
bool checked = &item.p == this;
item.p.qtRadioButton->setChecked(item.state.checked = checked);
}
qtRadioButton->setChecked(radioButton.state.checked = true);
parent().locked = false;
}
@ -26,6 +33,16 @@ void pRadioButton::setGroup(const group<RadioButton>& group) {
parent().locked = false;
}
void pRadioButton::setImage(const image& image, Orientation orientation) {
qtRadioButton->setIconSize(QSize(image.width, image.height));
qtRadioButton->setIcon(CreateIcon(image));
qtRadioButton->setStyleSheet("text-align: top;");
switch(orientation) {
case Orientation::Horizontal: qtRadioButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
case Orientation::Vertical: qtRadioButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;
}
}
void pRadioButton::setText(string text) {
qtRadioButton->setText(QString::fromUtf8(text));
}
@ -36,8 +53,9 @@ pRadioButton& pRadioButton::parent() {
}
void pRadioButton::constructor() {
qtWidget = qtRadioButton = new QRadioButton;
qtRadioButton->setAutoExclusive(false);
qtWidget = qtRadioButton = new QToolButton;
qtRadioButton->setCheckable(true);
qtRadioButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
connect(qtRadioButton, SIGNAL(toggled(bool)), SLOT(onActivate()));
pWidget::synchronizeState();
@ -56,12 +74,11 @@ void pRadioButton::orphan() {
}
void pRadioButton::onActivate() {
if(parent().locked == false) {
bool wasChecked = radioButton.state.checked;
setChecked();
if(wasChecked == false) {
if(radioButton.onActivate) radioButton.onActivate();
}
if(parent().locked) return;
bool wasChecked = radioButton.state.checked;
setChecked();
if(!wasChecked) {
if(radioButton.onActivate) radioButton.onActivate();
}
}

View File

@ -0,0 +1,63 @@
namespace phoenix {
Size pRadioLabel::minimumSize() {
Size size = pFont::size(qtWidget->font(), radioLabel.state.text);
return {size.width + 26, size.height + 6};
}
void pRadioLabel::setChecked() {
parent().locked = true;
for(auto& item : radioLabel.state.group) {
bool checked = &item == &radioLabel;
item.p.qtRadioLabel->setChecked(item.state.checked = checked);
}
parent().locked = false;
}
void pRadioLabel::setGroup(const group<RadioLabel>& group) {
parent().locked = true;
for(auto& item : radioLabel.state.group) {
item.p.qtRadioLabel->setChecked(item.state.checked);
}
parent().locked = false;
}
void pRadioLabel::setText(string text) {
qtRadioLabel->setText(QString::fromUtf8(text));
}
pRadioLabel& pRadioLabel::parent() {
if(radioLabel.state.group.size()) return radioLabel.state.group.first().p;
return *this;
}
void pRadioLabel::constructor() {
qtWidget = qtRadioLabel = new QRadioButton;
qtRadioLabel->setAutoExclusive(false);
connect(qtRadioLabel, SIGNAL(toggled(bool)), SLOT(onActivate()));
pWidget::synchronizeState();
setGroup(radioLabel.state.group);
setText(radioLabel.state.text);
}
void pRadioLabel::destructor() {
if(qtRadioLabel) delete qtRadioLabel;
qtWidget = qtRadioLabel = nullptr;
}
void pRadioLabel::orphan() {
destructor();
constructor();
}
void pRadioLabel::onActivate() {
if(parent().locked) return;
bool wasChecked = radioLabel.state.checked;
setChecked();
if(!wasChecked) {
if(radioLabel.onActivate) radioLabel.onActivate();
}
}
}

View File

@ -0,0 +1,83 @@
namespace phoenix {
void pTabFrame::append(string text, const image& image) {
unsigned selection = tabFrame.state.text.size() - 1;
QWidget* widget = new QWidget; //addTab() requires a child widget, so give it an empty one
qtTabFrame->addTab(widget, QString::fromUtf8(text));
if(!image.empty()) setImage(selection, image);
}
void pTabFrame::remove(unsigned selection) {
qtTabFrame->removeTab(selection);
}
void pTabFrame::setEnabled(bool enabled) {
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setEnabled(layout->enabled());
}
pWidget::setEnabled(enabled);
}
void pTabFrame::setGeometry(Geometry geometry) {
pWidget::setGeometry(geometry);
geometry.x += 1, geometry.width -= 2;
geometry.y += 29, geometry.height -= 30;
for(auto& layout : tabFrame.state.layout) {
if(layout == nullptr) continue;
layout->setGeometry(geometry);
}
synchronizeLayout();
}
void pTabFrame::setImage(unsigned selection, const image& image) {
qtTabFrame->setTabIcon(selection, CreateIcon(image));
}
void pTabFrame::setSelection(unsigned selection) {
qtTabFrame->setCurrentIndex(selection);
synchronizeLayout();
}
void pTabFrame::setText(unsigned selection, string text) {
qtTabFrame->setTabText(selection, QString::fromUtf8(text));
}
void pTabFrame::setVisible(bool visible) {
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setVisible(layout->visible());
}
pWidget::setVisible(visible);
}
void pTabFrame::constructor() {
qtWidget = qtTabFrame = new QTabWidget;
connect(qtTabFrame, SIGNAL(currentChanged(int)), SLOT(onChange(int)));
setSelection(tabFrame.state.selection);
}
void pTabFrame::destructor() {
delete qtTabFrame;
qtWidget = qtTabFrame = nullptr;
}
void pTabFrame::orphan() {
destructor();
constructor();
}
void pTabFrame::synchronizeLayout() {
unsigned selection = 0;
for(auto& layout : tabFrame.state.layout) {
if(layout) layout->setVisible(selection == tabFrame.state.selection);
selection++;
}
}
void pTabFrame::onChange(int selection) {
tabFrame.state.selection = selection;
synchronizeLayout();
if(tabFrame.onChange) tabFrame.onChange();
}
}

View File

@ -4,10 +4,6 @@ Size pVerticalScroller::minimumSize() {
return {15, 0};
}
unsigned pVerticalScroller::position() {
return qtScroller->value();
}
void pVerticalScroller::setLength(unsigned length) {
length += length == 0;
qtScroller->setRange(0, length - 1);
@ -40,7 +36,7 @@ void pVerticalScroller::orphan() {
}
void pVerticalScroller::onChange() {
verticalScroller.state.position = position();
verticalScroller.state.position = qtScroller->value();
if(verticalScroller.onChange) verticalScroller.onChange();
}

View File

@ -4,10 +4,6 @@ Size pVerticalSlider::minimumSize() {
return {20, 0};
}
unsigned pVerticalSlider::position() {
return qtSlider->value();
}
void pVerticalSlider::setLength(unsigned length) {
length += length == 0;
qtSlider->setRange(0, length - 1);
@ -40,7 +36,7 @@ void pVerticalSlider::orphan() {
}
void pVerticalSlider::onChange() {
verticalSlider.state.position = position();
verticalSlider.state.position = qtSlider->value();
if(verticalSlider.onChange) verticalSlider.onChange();
}

Some files were not shown because too many files have changed in this diff Show More