mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-20 17:51:26 +02:00
Update to v094r09 release.
byuu says: This will easily be the biggest diff in the history of higan. And not in a good way. * target-higan and target-loki have been blown away completely * nall and ruby massively updated * phoenix replaced with hiro (pretty near a total rewrite) * target-higan restarted using hiro (just a window for now) * all emulation cores updated to compile again * installation changed to not require root privileges (installs locally) For the foreseeable future (maybe even permanently?), the new higan UI will only build under Linux/BSD with GTK+ 2.20+. Probably the most likely route for Windows/OS X will be to try and figure out how to build hiro/GTK on those platforms, as awful as that would be. The other alternative would be to produce new UIs for those platforms ... which would actually be a good opportunity to make something much more user friendly. Being that I just started on this a few hours ago, that means that for at least a few weeks, don't expect to be able to actually play any games. Right now, you can pretty much just compile the binary and that's it. It's quite possible that some nall changes didn't produce compilation errors, but will produce runtime errors. So until the UI can actually load games, we won't know if anything is broken. But we should mostly be okay. It was mostly just trim<1> -> trim changes, moving to Hash::SHA256 (much cleaner), and patching some reckless memory copy functions enough to compile. Progress isn't going to be like it was before: I'm now dividing my time much thinner between studying and other hobbies. My aim this time is not to produce a binary for everyone to play games on. Rather, it's to keep the emulator alive. I want to be able to apply critical patches again. And I would also like the base of the emulator to live on, for use in other emulator frontends that utilize higan.
This commit is contained in:
80
hiro/cocoa/widget/button.cpp
Normal file
80
hiro/cocoa/widget/button.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
@implementation CocoaButton : NSButton
|
||||
|
||||
-(id) initWith:(phoenix::Button&)buttonReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
button = &buttonReference;
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
//NSRoundedBezelStyle has a fixed height; which breaks both icons and larger/smaller text
|
||||
[self setBezelStyle:NSRegularSquareBezelStyle];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
if(button->onActivate) button->onActivate();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pButton::minimumSize() {
|
||||
Size size = Font::size(button.font(), button.state.text);
|
||||
|
||||
if(button.state.orientation == Orientation::Horizontal) {
|
||||
size.width += button.state.image.width;
|
||||
size.height = max(button.state.image.height, size.height);
|
||||
}
|
||||
|
||||
if(button.state.orientation == Orientation::Vertical) {
|
||||
size.width = max(button.state.image.width, size.width);
|
||||
size.height += button.state.image.height;
|
||||
}
|
||||
|
||||
return {size.width + (button.state.text ? 20 : 4), size.height + 4};
|
||||
}
|
||||
|
||||
void pButton::setBordered(bool bordered) {
|
||||
}
|
||||
|
||||
void pButton::setGeometry(Geometry geometry) {
|
||||
pWidget::setGeometry({
|
||||
geometry.x - 2, geometry.y - 2,
|
||||
geometry.width + 4, geometry.height + 4
|
||||
});
|
||||
}
|
||||
|
||||
void pButton::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 pButton::setText(string text) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
void pButton::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaButton = [[CocoaButton alloc] initWith:button];
|
||||
}
|
||||
}
|
||||
|
||||
void pButton::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
26
hiro/cocoa/widget/button.hpp
Normal file
26
hiro/cocoa/widget/button.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
@interface CocoaButton : NSButton {
|
||||
@public
|
||||
phoenix::Button* button;
|
||||
}
|
||||
-(id) initWith:(phoenix::Button&)button;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pButton : public pWidget {
|
||||
Button& button;
|
||||
CocoaButton* cocoaButton = nullptr;
|
||||
|
||||
Size minimumSize();
|
||||
void setBordered(bool bordered);
|
||||
void setGeometry(Geometry geometry);
|
||||
void setImage(const image& image, Orientation orientation);
|
||||
void setText(string text);
|
||||
|
||||
pButton(Button& button) : pWidget(button), button(button) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
214
hiro/cocoa/widget/canvas.cpp
Normal file
214
hiro/cocoa/widget/canvas.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
@implementation CocoaCanvas : NSImageView
|
||||
|
||||
-(id) initWith:(phoenix::Canvas&)canvasReference {
|
||||
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]
|
||||
options:NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect
|
||||
owner:self userInfo:nil
|
||||
] autorelease];
|
||||
[self addTrackingArea:area];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender {
|
||||
return DropPathsOperation(sender);
|
||||
}
|
||||
|
||||
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender {
|
||||
lstring paths = DropPaths(sender);
|
||||
if(paths.empty()) return NO;
|
||||
if(canvas->onDrop) canvas->onDrop(paths);
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown {
|
||||
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);
|
||||
case 2: return callback(phoenix::Mouse::Button::Middle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) mouseExited:(NSEvent*)event {
|
||||
if(canvas->onMouseLeave) canvas->onMouseLeave();
|
||||
}
|
||||
|
||||
-(void) mouseMove:(NSEvent*)event {
|
||||
if([event window] == nil) return;
|
||||
NSPoint location = [self convertPoint:[event locationInWindow] fromView:nil];
|
||||
if(canvas->onMouseMove) canvas->onMouseMove({location.x, [self frame].size.height - 1 - location.y});
|
||||
}
|
||||
|
||||
-(void) mouseDown:(NSEvent*)event {
|
||||
[self mouseButton:event down:YES];
|
||||
}
|
||||
|
||||
-(void) mouseUp:(NSEvent*)event {
|
||||
[self mouseButton:event down:NO];
|
||||
}
|
||||
|
||||
-(void) mouseDragged:(NSEvent*)event {
|
||||
[self mouseMove:event];
|
||||
}
|
||||
|
||||
-(void) rightMouseDown:(NSEvent*)event {
|
||||
[self mouseButton:event down:YES];
|
||||
}
|
||||
|
||||
-(void) rightMouseUp:(NSEvent*)event {
|
||||
[self mouseButton:event down:NO];
|
||||
}
|
||||
|
||||
-(void) rightMouseDragged:(NSEvent*)event {
|
||||
[self mouseMove:event];
|
||||
}
|
||||
|
||||
-(void) otherMouseDown:(NSEvent*)event {
|
||||
[self mouseButton:event down:YES];
|
||||
}
|
||||
|
||||
-(void) otherMouseUp:(NSEvent*)event {
|
||||
[self mouseButton:event down:NO];
|
||||
}
|
||||
|
||||
-(void) otherMouseDragged:(NSEvent*)event {
|
||||
[self mouseMove:event];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
void pCanvas::setDroppable(bool droppable) {
|
||||
@autoreleasepool {
|
||||
if(droppable) {
|
||||
[cocoaCanvas registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
||||
} else {
|
||||
[cocoaCanvas unregisterDraggedTypes];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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::setMode(Canvas::Mode mode) {
|
||||
rasterize(), redraw();
|
||||
}
|
||||
|
||||
void pCanvas::setSize(Size size) {
|
||||
rasterize(), redraw();
|
||||
}
|
||||
|
||||
void pCanvas::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaCanvas = [[CocoaCanvas alloc] initWith:canvas];
|
||||
}
|
||||
setSize(canvas.size());
|
||||
}
|
||||
|
||||
void pCanvas::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
42
hiro/cocoa/widget/canvas.hpp
Normal file
42
hiro/cocoa/widget/canvas.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
@interface CocoaCanvas : NSImageView {
|
||||
@public
|
||||
phoenix::Canvas* canvas;
|
||||
}
|
||||
-(id) initWith:(phoenix::Canvas&)canvas;
|
||||
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender;
|
||||
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender;
|
||||
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown;
|
||||
-(void) mouseExited:(NSEvent*)event;
|
||||
-(void) mouseMove:(NSEvent*)event;
|
||||
-(void) mouseDown:(NSEvent*)event;
|
||||
-(void) mouseUp:(NSEvent*)event;
|
||||
-(void) mouseDragged:(NSEvent*)event;
|
||||
-(void) rightMouseDown:(NSEvent*)event;
|
||||
-(void) rightMouseUp:(NSEvent*)event;
|
||||
-(void) rightMouseDragged:(NSEvent*)event;
|
||||
-(void) otherMouseDown:(NSEvent*)event;
|
||||
-(void) otherMouseUp:(NSEvent*)event;
|
||||
-(void) otherMouseDragged:(NSEvent*)event;
|
||||
@end
|
||||
|
||||
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);
|
||||
|
||||
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void rasterize();
|
||||
void redraw();
|
||||
};
|
||||
|
||||
}
|
85
hiro/cocoa/widget/check-button.cpp
Normal file
85
hiro/cocoa/widget/check-button.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
@implementation CocoaCheckButton : NSButton
|
||||
|
||||
-(id) initWith:(phoenix::CheckButton&)checkButtonReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
checkButton = &checkButtonReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setBezelStyle:NSRegularSquareBezelStyle];
|
||||
[self setButtonType:NSOnOffButton];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
checkButton->state.checked = [self state] != NSOffState;
|
||||
if(checkButton->onToggle) checkButton->onToggle();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pCheckButton::minimumSize() {
|
||||
Size size = Font::size(checkButton.font(), checkButton.state.text);
|
||||
|
||||
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) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setState:checked ? NSOnState : NSOffState];
|
||||
}
|
||||
}
|
||||
|
||||
void pCheckButton::setGeometry(Geometry geometry) {
|
||||
pWidget::setGeometry({
|
||||
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]];
|
||||
}
|
||||
}
|
||||
|
||||
void pCheckButton::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaCheckButton = [[CocoaCheckButton alloc] initWith:checkButton];
|
||||
}
|
||||
}
|
||||
|
||||
void pCheckButton::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
26
hiro/cocoa/widget/check-button.hpp
Normal file
26
hiro/cocoa/widget/check-button.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
@interface CocoaCheckButton : NSButton {
|
||||
@public
|
||||
phoenix::CheckButton* checkButton;
|
||||
}
|
||||
-(id) initWith:(phoenix::CheckButton&)checkButton;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pCheckButton : public pWidget {
|
||||
CheckButton& checkButton;
|
||||
CocoaCheckButton* cocoaCheckButton = nullptr;
|
||||
|
||||
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) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
61
hiro/cocoa/widget/check-label.cpp
Normal file
61
hiro/cocoa/widget/check-label.cpp
Normal 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];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
hiro/cocoa/widget/check-label.hpp
Normal file
25
hiro/cocoa/widget/check-label.hpp
Normal 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();
|
||||
};
|
||||
|
||||
}
|
78
hiro/cocoa/widget/combo-button.cpp
Normal file
78
hiro/cocoa/widget/combo-button.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
@implementation CocoaComboButton : NSPopUpButton
|
||||
|
||||
-(id) initWith:(phoenix::ComboButton&)comboButtonReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0) pullsDown:NO]) {
|
||||
comboButton = &comboButtonReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
comboButton->state.selection = [self indexOfSelectedItem];
|
||||
if(comboButton->onChange) comboButton->onChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
void pComboButton::append(string text) {
|
||||
@autoreleasepool {
|
||||
[cocoaView addItemWithTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
Size pComboButton::minimumSize() {
|
||||
unsigned maximumWidth = 0;
|
||||
for(auto& text : comboButton.state.text) maximumWidth = max(maximumWidth, Font::size(comboButton.font(), text).width);
|
||||
Size size = Font::size(comboButton.font(), " ");
|
||||
return {maximumWidth + 36, size.height + 6};
|
||||
}
|
||||
|
||||
void pComboButton::remove(unsigned selection) {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeItemAtIndex:selection];
|
||||
}
|
||||
}
|
||||
|
||||
void pComboButton::reset() {
|
||||
@autoreleasepool {
|
||||
[cocoaView removeAllItems];
|
||||
}
|
||||
}
|
||||
|
||||
void pComboButton::setGeometry(Geometry geometry) {
|
||||
pWidget::setGeometry({
|
||||
geometry.x - 2, geometry.y,
|
||||
geometry.width + 4, geometry.height
|
||||
});
|
||||
}
|
||||
|
||||
void pComboButton::setSelection(unsigned selection) {
|
||||
@autoreleasepool {
|
||||
[cocoaView selectItemAtIndex:selection];
|
||||
}
|
||||
}
|
||||
|
||||
void pComboButton::setText(unsigned selection, string text) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView itemAtIndex:selection] setTitle:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
void pComboButton::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaComboButton = [[CocoaComboButton alloc] initWith:comboButton];
|
||||
}
|
||||
}
|
||||
|
||||
void pComboButton::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
28
hiro/cocoa/widget/combo-button.hpp
Normal file
28
hiro/cocoa/widget/combo-button.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
@interface CocoaComboButton : NSPopUpButton {
|
||||
@public
|
||||
phoenix::ComboButton* comboButton;
|
||||
}
|
||||
-(id) initWith:(phoenix::ComboButton&)comboButton;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pComboButton : public pWidget {
|
||||
ComboButton& comboButton;
|
||||
CocoaComboButton* cocoaComboButton = nullptr;
|
||||
|
||||
void append(string text);
|
||||
Size minimumSize();
|
||||
void remove(unsigned selection);
|
||||
void reset();
|
||||
void setGeometry(Geometry geometry);
|
||||
void setSelection(unsigned selection);
|
||||
void setText(unsigned selection, string text);
|
||||
|
||||
pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
41
hiro/cocoa/widget/console.cpp
Normal file
41
hiro/cocoa/widget/console.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
@implementation CocoaConsole : NSScrollView
|
||||
|
||||
-(id) initWith:(phoenix::Console&)consoleReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
console = &consoleReference;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
void pConsole::print(string text) {
|
||||
}
|
||||
|
||||
void pConsole::reset() {
|
||||
}
|
||||
|
||||
void pConsole::setBackgroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pConsole::setForegroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pConsole::setPrompt(string prompt) {
|
||||
}
|
||||
|
||||
void pConsole::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaConsole = [[CocoaConsole alloc] initWith:console];
|
||||
}
|
||||
}
|
||||
|
||||
void pConsole::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
hiro/cocoa/widget/console.hpp
Normal file
25
hiro/cocoa/widget/console.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
@interface CocoaConsole : NSScrollView {
|
||||
@public
|
||||
phoenix::Console* console;
|
||||
}
|
||||
-(id) initWith:(phoenix::Console&)console;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pConsole : public pWidget {
|
||||
Console& console;
|
||||
CocoaConsole* cocoaConsole = nullptr;
|
||||
|
||||
void print(string text);
|
||||
void reset();
|
||||
void setBackgroundColor(Color color);
|
||||
void setForegroundColor(Color color);
|
||||
void setPrompt(string prompt);
|
||||
|
||||
pConsole(Console& console) : pWidget(console), console(console) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
68
hiro/cocoa/widget/frame.cpp
Normal file
68
hiro/cocoa/widget/frame.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
26
hiro/cocoa/widget/frame.hpp
Normal file
26
hiro/cocoa/widget/frame.hpp
Normal 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();
|
||||
};
|
||||
|
||||
}
|
47
hiro/cocoa/widget/hex-edit.cpp
Normal file
47
hiro/cocoa/widget/hex-edit.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
@implementation CocoaHexEdit : NSScrollView
|
||||
|
||||
-(id) initWith:(phoenix::HexEdit&)hexEditReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
hexEdit = &hexEditReference;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
void pHexEdit::setBackgroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pHexEdit::setColumns(unsigned columns) {
|
||||
}
|
||||
|
||||
void pHexEdit::setForegroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pHexEdit::setLength(unsigned length) {
|
||||
}
|
||||
|
||||
void pHexEdit::setOffset(unsigned offset) {
|
||||
}
|
||||
|
||||
void pHexEdit::setRows(unsigned rows) {
|
||||
}
|
||||
|
||||
void pHexEdit::update() {
|
||||
}
|
||||
|
||||
void pHexEdit::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaHexEdit = [[CocoaHexEdit alloc] initWith:hexEdit];
|
||||
}
|
||||
}
|
||||
|
||||
void pHexEdit::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
27
hiro/cocoa/widget/hex-edit.hpp
Normal file
27
hiro/cocoa/widget/hex-edit.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
@interface CocoaHexEdit : NSScrollView {
|
||||
@public
|
||||
phoenix::HexEdit* hexEdit;
|
||||
}
|
||||
-(id) initWith:(phoenix::HexEdit&)hexEdit;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pHexEdit : public pWidget {
|
||||
HexEdit& hexEdit;
|
||||
CocoaHexEdit* cocoaHexEdit = nullptr;
|
||||
|
||||
void setBackgroundColor(Color color);
|
||||
void setColumns(unsigned columns);
|
||||
void setForegroundColor(Color color);
|
||||
void setLength(unsigned length);
|
||||
void setOffset(unsigned offset);
|
||||
void setRows(unsigned rows);
|
||||
void update();
|
||||
|
||||
pHexEdit(HexEdit& hexEdit) : pWidget(hexEdit), hexEdit(hexEdit) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
85
hiro/cocoa/widget/horizontal-scroller.cpp
Normal file
85
hiro/cocoa/widget/horizontal-scroller.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
@implementation CocoaHorizontalScroller : NSScroller
|
||||
|
||||
-(id) initWith:(phoenix::HorizontalScroller&)horizontalScrollerReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 1, 0)]) {
|
||||
horizontalScroller = &horizontalScrollerReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(scroll:)];
|
||||
|
||||
[self setControlSize:NSRegularControlSize];
|
||||
[self setScrollerStyle:NSScrollerStyleLegacy];
|
||||
[self setEnabled:YES];
|
||||
|
||||
[self update];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) update {
|
||||
double d = 1.0 / horizontalScroller->state.length;
|
||||
double f = d * horizontalScroller->state.position;
|
||||
|
||||
[self setDoubleValue:f];
|
||||
[self setKnobProportion:d];
|
||||
}
|
||||
|
||||
-(IBAction) scroll:(id)sender {
|
||||
auto& state = horizontalScroller->state;
|
||||
|
||||
switch([self hitPart]) {
|
||||
case NSScrollerIncrementLine:
|
||||
case NSScrollerIncrementPage:
|
||||
if(state.position < state.length - 1) state.position++;
|
||||
[self update];
|
||||
break;
|
||||
|
||||
case NSScrollerDecrementLine:
|
||||
case NSScrollerDecrementPage:
|
||||
if(state.position) state.position--;
|
||||
[self update];
|
||||
break;
|
||||
|
||||
case NSScrollerKnob:
|
||||
state.position = [self doubleValue] * state.length;
|
||||
break;
|
||||
}
|
||||
|
||||
if(horizontalScroller->onChange) horizontalScroller->onChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pHorizontalScroller::minimumSize() {
|
||||
@autoreleasepool {
|
||||
return {32, [NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegacy]};
|
||||
}
|
||||
}
|
||||
|
||||
void pHorizontalScroller::setLength(unsigned length) {
|
||||
@autoreleasepool {
|
||||
[cocoaView update];
|
||||
}
|
||||
}
|
||||
|
||||
void pHorizontalScroller::setPosition(unsigned position) {
|
||||
@autoreleasepool {
|
||||
[cocoaView update];
|
||||
}
|
||||
}
|
||||
|
||||
void pHorizontalScroller::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaHorizontalScroller = [[CocoaHorizontalScroller alloc] initWith:horizontalScroller];
|
||||
}
|
||||
}
|
||||
|
||||
void pHorizontalScroller::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
hiro/cocoa/widget/horizontal-scroller.hpp
Normal file
25
hiro/cocoa/widget/horizontal-scroller.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
@interface CocoaHorizontalScroller : NSScroller {
|
||||
@public
|
||||
phoenix::HorizontalScroller* horizontalScroller;
|
||||
}
|
||||
-(id) initWith:(phoenix::HorizontalScroller&)horizontalScroller;
|
||||
-(void) update;
|
||||
-(IBAction) scroll:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pHorizontalScroller : public pWidget {
|
||||
HorizontalScroller& horizontalScroller;
|
||||
CocoaHorizontalScroller* cocoaHorizontalScroller = nullptr;
|
||||
|
||||
Size minimumSize();
|
||||
void setLength(unsigned length);
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pHorizontalScroller(HorizontalScroller& horizontalScroller) : pWidget(horizontalScroller), horizontalScroller(horizontalScroller) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
61
hiro/cocoa/widget/horizontal-slider.cpp
Normal file
61
hiro/cocoa/widget/horizontal-slider.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
@implementation CocoaHorizontalSlider : NSSlider
|
||||
|
||||
-(id) initWith:(phoenix::HorizontalSlider&)horizontalSliderReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 1, 0)]) {
|
||||
horizontalSlider = &horizontalSliderReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setMinValue:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
horizontalSlider->state.position = [self doubleValue];
|
||||
if(horizontalSlider->onChange) horizontalSlider->onChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pHorizontalSlider::minimumSize() {
|
||||
return {48, 20};
|
||||
}
|
||||
|
||||
void pHorizontalSlider::setGeometry(Geometry geometry) {
|
||||
pWidget::setGeometry({
|
||||
geometry.x - 2, geometry.y,
|
||||
geometry.width + 4, geometry.height
|
||||
});
|
||||
}
|
||||
|
||||
void pHorizontalSlider::setLength(unsigned length) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setMaxValue:length];
|
||||
}
|
||||
}
|
||||
|
||||
void pHorizontalSlider::setPosition(unsigned position) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setDoubleValue:position];
|
||||
}
|
||||
}
|
||||
|
||||
void pHorizontalSlider::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaHorizontalSlider = [[CocoaHorizontalSlider alloc] initWith:horizontalSlider];
|
||||
|
||||
setLength(horizontalSlider.state.length);
|
||||
setPosition(horizontalSlider.state.position);
|
||||
}
|
||||
}
|
||||
|
||||
void pHorizontalSlider::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
hiro/cocoa/widget/horizontal-slider.hpp
Normal file
25
hiro/cocoa/widget/horizontal-slider.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
@interface CocoaHorizontalSlider : NSSlider {
|
||||
@public
|
||||
phoenix::HorizontalSlider* horizontalSlider;
|
||||
}
|
||||
-(id) initWith:(phoenix::HorizontalSlider&)horizontalSlider;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pHorizontalSlider : public pWidget {
|
||||
HorizontalSlider& horizontalSlider;
|
||||
CocoaHorizontalSlider* cocoaHorizontalSlider = nullptr;
|
||||
|
||||
Size minimumSize();
|
||||
void setGeometry(Geometry geometry);
|
||||
void setLength(unsigned length);
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pHorizontalSlider(HorizontalSlider& horizontalSlider) : pWidget(horizontalSlider), horizontalSlider(horizontalSlider) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
62
hiro/cocoa/widget/label.cpp
Normal file
62
hiro/cocoa/widget/label.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
@implementation CocoaLabel : NSTextField
|
||||
|
||||
-(id) initWith:(phoenix::Label&)labelReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
label = &labelReference;
|
||||
|
||||
[self setAlignment:NSLeftTextAlignment];
|
||||
[self setBordered:NO];
|
||||
[self setDrawsBackground:NO];
|
||||
[self setEditable:NO];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pLabel::minimumSize() {
|
||||
Size size = Font::size(label.font(), label.state.text);
|
||||
return {size.width, size.height};
|
||||
}
|
||||
|
||||
void pLabel::setGeometry(Geometry geometry) {
|
||||
//NSTextField does not support vertical text centering:
|
||||
//simulate this by adjusting the geometry placement (reduce height, move view down)
|
||||
unsigned height = Font::size(label.font(), " ").height;
|
||||
unsigned widgetHeight = geometry.height + 4; //+4 compensates for margin adjust
|
||||
auto offset = geometry;
|
||||
|
||||
if(widgetHeight > height) {
|
||||
unsigned diff = widgetHeight - height;
|
||||
offset.y += diff >> 1;
|
||||
offset.height -= diff >> 1;
|
||||
}
|
||||
|
||||
pWidget::setGeometry({
|
||||
offset.x - 3, offset.y - 3,
|
||||
offset.width + 6, offset.height + 6
|
||||
});
|
||||
}
|
||||
|
||||
void pLabel::setText(string text) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setStringValue:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
void pLabel::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaLabel = [[CocoaLabel alloc] initWith:label];
|
||||
setText(label.state.text);
|
||||
}
|
||||
}
|
||||
|
||||
void pLabel::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
23
hiro/cocoa/widget/label.hpp
Normal file
23
hiro/cocoa/widget/label.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
@interface CocoaLabel : NSTextField {
|
||||
@public
|
||||
phoenix::Label* label;
|
||||
}
|
||||
-(id) initWith:(phoenix::Label&)label;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pLabel : public pWidget {
|
||||
Label& label;
|
||||
CocoaLabel* cocoaLabel = nullptr;
|
||||
|
||||
Size minimumSize();
|
||||
void setGeometry(Geometry geometry);
|
||||
void setText(string text);
|
||||
|
||||
pLabel(Label& label) : pWidget(label), label(label) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
9
hiro/cocoa/widget/layout.hpp
Normal file
9
hiro/cocoa/widget/layout.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace phoenix {
|
||||
|
||||
struct pLayout : public pSizable {
|
||||
Layout& layout;
|
||||
|
||||
pLayout(Layout& layout) : pSizable(layout), layout(layout) {}
|
||||
};
|
||||
|
||||
}
|
71
hiro/cocoa/widget/line-edit.cpp
Normal file
71
hiro/cocoa/widget/line-edit.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
@implementation CocoaLineEdit : NSTextField
|
||||
|
||||
-(id) initWith:(phoenix::LineEdit&)lineEditReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
lineEdit = &lineEditReference;
|
||||
|
||||
[self setDelegate:self];
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
|
||||
//prevent focus changes from generating activate event
|
||||
[[self cell] setSendsActionOnEndEditing:NO];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) textDidChange:(NSNotification*)n {
|
||||
if(lineEdit->onChange) lineEdit->onChange();
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
if(lineEdit->onActivate) lineEdit->onActivate();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pLineEdit::minimumSize() {
|
||||
Size size = Font::size(lineEdit.font(), lineEdit.state.text);
|
||||
return {size.width + 10, size.height + 8};
|
||||
}
|
||||
|
||||
void pLineEdit::setBackgroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pLineEdit::setEditable(bool editable) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setEditable:editable];
|
||||
}
|
||||
}
|
||||
|
||||
void pLineEdit::setForegroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pLineEdit::setText(string text) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setStringValue:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
string pLineEdit::text() {
|
||||
@autoreleasepool {
|
||||
return [[cocoaView stringValue] UTF8String];
|
||||
}
|
||||
}
|
||||
|
||||
void pLineEdit::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaLineEdit = [[CocoaLineEdit alloc] initWith:lineEdit];
|
||||
setEditable(lineEdit.state.editable);
|
||||
}
|
||||
}
|
||||
|
||||
void pLineEdit::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
28
hiro/cocoa/widget/line-edit.hpp
Normal file
28
hiro/cocoa/widget/line-edit.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
@interface CocoaLineEdit : NSTextField <NSTextFieldDelegate> {
|
||||
@public
|
||||
phoenix::LineEdit* lineEdit;
|
||||
}
|
||||
-(id) initWith:(phoenix::LineEdit&)lineEdit;
|
||||
-(void) textDidChange:(NSNotification*)n;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pLineEdit : public pWidget {
|
||||
LineEdit& lineEdit;
|
||||
CocoaLineEdit* cocoaLineEdit = nullptr;
|
||||
|
||||
Size minimumSize();
|
||||
void setBackgroundColor(Color color);
|
||||
void setEditable(bool editable);
|
||||
void setForegroundColor(Color color);
|
||||
void setText(string text);
|
||||
string text();
|
||||
|
||||
pLineEdit(LineEdit& lineEdit) : pWidget(lineEdit), lineEdit(lineEdit) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
333
hiro/cocoa/widget/list-view.cpp
Normal file
333
hiro/cocoa/widget/list-view.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
@implementation CocoaListView : NSScrollView
|
||||
|
||||
-(id) initWith:(phoenix::ListView&)listViewReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
listView = &listViewReference;
|
||||
content = [[CocoaListViewContent alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)];
|
||||
|
||||
[self setDocumentView:content];
|
||||
[self setBorderType:NSBezelBorder];
|
||||
[self setHasVerticalScroller:YES];
|
||||
|
||||
[content setDataSource:self];
|
||||
[content setDelegate:self];
|
||||
[content setTarget:self];
|
||||
[content setDoubleAction:@selector(doubleAction:)];
|
||||
|
||||
[content setAllowsColumnReordering:NO];
|
||||
[content setAllowsColumnResizing:YES];
|
||||
[content setAllowsColumnSelection:NO];
|
||||
[content setAllowsEmptySelection:YES];
|
||||
[content setAllowsMultipleSelection:NO];
|
||||
[content setColumnAutoresizingStyle:NSTableViewLastColumnOnlyAutoresizingStyle];
|
||||
|
||||
font = nil;
|
||||
[self setFont:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) dealloc {
|
||||
[content release];
|
||||
[font release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(CocoaListViewContent*) content {
|
||||
return content;
|
||||
}
|
||||
|
||||
-(NSFont*) font {
|
||||
return font;
|
||||
}
|
||||
|
||||
-(void) setFont:(NSFont*)fontPointer {
|
||||
if(!fontPointer) fontPointer = [NSFont systemFontOfSize:12];
|
||||
[fontPointer retain];
|
||||
if(font) [font release];
|
||||
font = fontPointer;
|
||||
|
||||
unsigned fontHeight = phoenix::pFont::size(font, " ").height;
|
||||
[content setFont:font];
|
||||
[content setRowHeight:fontHeight];
|
||||
[self reloadColumns];
|
||||
}
|
||||
|
||||
-(void) reloadColumns {
|
||||
while([[content tableColumns] count]) {
|
||||
[content removeTableColumn:[[content tableColumns] lastObject]];
|
||||
}
|
||||
|
||||
if(listView->state.checkable) {
|
||||
NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:@"check"];
|
||||
NSTableHeaderCell *headerCell = [[NSTableHeaderCell alloc] initTextCell:@""];
|
||||
NSButtonCell *dataCell = [[NSButtonCell alloc] initTextCell:@""];
|
||||
|
||||
[dataCell setButtonType:NSSwitchButton];
|
||||
[dataCell setControlSize:NSSmallControlSize];
|
||||
[dataCell setRefusesFirstResponder:YES];
|
||||
|
||||
[tableColumn setResizingMask:NSTableColumnNoResizing];
|
||||
[tableColumn setHeaderCell:headerCell];
|
||||
[tableColumn setDataCell:dataCell];
|
||||
[tableColumn setWidth:20.0];
|
||||
|
||||
[content addTableColumn:tableColumn];
|
||||
}
|
||||
|
||||
lstring headers = listView->state.headerText;
|
||||
if(headers.size() == 0) headers.append("");
|
||||
[content setUsesAlternatingRowBackgroundColors:headers.size() >= 2];
|
||||
|
||||
for(unsigned column = 0; column < headers.size(); column++) {
|
||||
NSTableColumn* tableColumn = [[NSTableColumn alloc] initWithIdentifier:[[NSNumber numberWithInteger:column] stringValue]];
|
||||
NSTableHeaderCell* headerCell = [[NSTableHeaderCell alloc] initTextCell:[NSString stringWithUTF8String:headers(column)]];
|
||||
CocoaListViewCell* dataCell = [[CocoaListViewCell alloc] initTextCell:@""];
|
||||
|
||||
[dataCell setEditable:NO];
|
||||
|
||||
[tableColumn setResizingMask:NSTableColumnAutoresizingMask | NSTableColumnUserResizingMask];
|
||||
[tableColumn setHeaderCell:headerCell];
|
||||
[tableColumn setDataCell:dataCell];
|
||||
|
||||
[content addTableColumn:tableColumn];
|
||||
}
|
||||
}
|
||||
|
||||
-(NSInteger) numberOfRowsInTableView:(NSTableView*)table {
|
||||
return listView->state.text.size();
|
||||
}
|
||||
|
||||
-(id) tableView:(NSTableView*)table objectValueForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
|
||||
if([[tableColumn identifier] isEqualToString:@"check"]) {
|
||||
auto checked = listView->state.checked(row) ? NSOnState : NSOffState;
|
||||
return [NSNumber numberWithInteger:checked];
|
||||
}
|
||||
|
||||
NSInteger column = [[tableColumn identifier] integerValue];
|
||||
unsigned height = [table rowHeight];
|
||||
|
||||
NSString* text = [NSString stringWithUTF8String:listView->state.text(row)(column)];
|
||||
NSImage* image = NSMakeImage(listView->state.image(row)(column), height, height);
|
||||
|
||||
if(image) return @{ @"text":text, @"image":image };
|
||||
return @{ @"text":text };
|
||||
}
|
||||
|
||||
-(BOOL) tableView:(NSTableView*)table shouldShowCellExpansionForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(NSString*) tableView:(NSTableView*)table toolTipForCell:(NSCell*)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row mouseLocation:(NSPoint)mouseLocation {
|
||||
return nil;
|
||||
}
|
||||
|
||||
-(void) tableView:(NSTableView*)table setObjectValue:(id)object forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
|
||||
if([[tableColumn identifier] isEqualToString:@"check"]) {
|
||||
listView->state.checked(row) = [object integerValue] != NSOffState;
|
||||
if(listView->onToggle) listView->onToggle(row);
|
||||
}
|
||||
}
|
||||
|
||||
-(void) tableView:(NSTableView*)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
|
||||
[cell setFont:[self font]];
|
||||
}
|
||||
|
||||
-(void) tableViewSelectionDidChange:(NSNotification*)notification {
|
||||
listView->state.selected = true;
|
||||
listView->state.selection = [content selectedRow];
|
||||
if(listView->onChange) listView->onChange();
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
if(listView->onActivate) listView->onActivate();
|
||||
}
|
||||
|
||||
-(IBAction) doubleAction:(id)sender {
|
||||
if([content clickedRow] >= 0) {
|
||||
[self activate:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CocoaListViewContent : NSTableView
|
||||
|
||||
-(void) keyDown:(NSEvent*)event {
|
||||
auto character = [[event characters] characterAtIndex:0];
|
||||
if(character == NSEnterCharacter || character == NSCarriageReturnCharacter) {
|
||||
if([self selectedRow] >= 0) {
|
||||
[[self delegate] activate:self];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[super keyDown:event];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CocoaListViewCell : NSTextFieldCell
|
||||
|
||||
//used by type-ahead
|
||||
-(NSString*) stringValue {
|
||||
return [[self objectValue] objectForKey:@"text"];
|
||||
}
|
||||
|
||||
-(void) drawWithFrame:(NSRect)frame inView:(NSView*)view {
|
||||
NSString* text = [[self objectValue] objectForKey:@"text"];
|
||||
NSImage* image = [[self objectValue] objectForKey:@"image"];
|
||||
unsigned textDisplacement = 0;
|
||||
|
||||
if(image) {
|
||||
[[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];
|
||||
|
||||
[[NSGraphicsContext currentContext] restoreGraphicsState];
|
||||
textDisplacement = frame.size.height + 2;
|
||||
}
|
||||
|
||||
NSRect textRect = NSMakeRect(
|
||||
frame.origin.x + textDisplacement, frame.origin.y,
|
||||
frame.size.width - textDisplacement, frame.size.height
|
||||
);
|
||||
|
||||
NSColor* textColor = [self isHighlighted]
|
||||
? [NSColor alternateSelectedControlTextColor]
|
||||
: [NSColor textColor];
|
||||
|
||||
[text drawInRect:textRect withAttributes:@{
|
||||
NSForegroundColorAttributeName:textColor,
|
||||
NSFontAttributeName:[self font]
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
void pListView::append(const lstring& text) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::autoSizeColumns() {
|
||||
@autoreleasepool {
|
||||
if(listView.state.checkable) {
|
||||
NSTableColumn* tableColumn = [[cocoaView content] tableColumnWithIdentifier:@"check"];
|
||||
[tableColumn setWidth:20.0];
|
||||
}
|
||||
|
||||
unsigned height = [[cocoaView content] rowHeight];
|
||||
for(unsigned column = 0; column < max(1u, listView.state.headerText.size()); column++) {
|
||||
NSTableColumn* tableColumn = [[cocoaView content] tableColumnWithIdentifier:[[NSNumber numberWithInteger:column] stringValue]];
|
||||
unsigned minimumWidth = pFont::size([[tableColumn headerCell] font], listView.state.headerText(column)).width + 4;
|
||||
for(unsigned row = 0; row < listView.state.text.size(); row++) {
|
||||
unsigned width = pFont::size([cocoaView font], listView.state.text(row)(column)).width + 2;
|
||||
if(listView.state.image(row)(height).empty() == false) width += height + 2;
|
||||
if(width > minimumWidth) minimumWidth = width;
|
||||
}
|
||||
[tableColumn setWidth:minimumWidth];
|
||||
}
|
||||
|
||||
[[cocoaView content] sizeLastColumnToFit];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::remove(unsigned selection) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::reset() {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setBackgroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pListView::setCheckable(bool checkable) {
|
||||
@autoreleasepool {
|
||||
[cocoaView reloadColumns];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setChecked(unsigned selection, bool checked) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setFont(string font) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setFont:pFont::cocoaFont(font)];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setForegroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pListView::setHeaderText(const lstring& text) {
|
||||
@autoreleasepool {
|
||||
[cocoaView reloadColumns];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setHeaderVisible(bool visible) {
|
||||
@autoreleasepool {
|
||||
if(visible) {
|
||||
[[cocoaView content] setHeaderView:[[[NSTableHeaderView alloc] init] autorelease]];
|
||||
} else {
|
||||
[[cocoaView content] setHeaderView:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setImage(unsigned selection, unsigned position, const image& image) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setSelected(bool selected) {
|
||||
@autoreleasepool {
|
||||
if(selected == false) {
|
||||
[[cocoaView content] deselectAll:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setSelection(unsigned selection) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] selectRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(selection, 1)] byExtendingSelection:NO];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setText(unsigned selection, unsigned position, const string text) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaListView = [[CocoaListView alloc] initWith:listView];
|
||||
setHeaderVisible(listView.state.headerVisible);
|
||||
setHeaderText(listView.state.headerText);
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
64
hiro/cocoa/widget/list-view.hpp
Normal file
64
hiro/cocoa/widget/list-view.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
@class CocoaListViewContent;
|
||||
|
||||
@interface CocoaListView : NSScrollView <NSTableViewDelegate, NSTableViewDataSource> {
|
||||
@public
|
||||
phoenix::ListView* listView;
|
||||
CocoaListViewContent* content;
|
||||
NSFont* font;
|
||||
}
|
||||
-(id) initWith:(phoenix::ListView&)listView;
|
||||
-(void) dealloc;
|
||||
-(CocoaListViewContent*) content;
|
||||
-(NSFont*) font;
|
||||
-(void) setFont:(NSFont*)font;
|
||||
-(void) reloadColumns;
|
||||
-(NSInteger) numberOfRowsInTableView:(NSTableView*)table;
|
||||
-(id) tableView:(NSTableView*)table objectValueForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row;
|
||||
-(BOOL) tableView:(NSTableView*)table shouldShowCellExpansionForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row;
|
||||
-(NSString*) tableView:(NSTableView*)table toolTipForCell:(NSCell*)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row mouseLocation:(NSPoint)mouseLocation;
|
||||
-(void) tableView:(NSTableView*)table setObjectValue:(id)object forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row;
|
||||
-(void) tableView:(NSTableView*)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row;
|
||||
-(void) tableViewSelectionDidChange:(NSNotification*)notification;
|
||||
-(IBAction) activate:(id)sender;
|
||||
-(IBAction) doubleAction:(id)sender;
|
||||
@end
|
||||
|
||||
@interface CocoaListViewContent : NSTableView {
|
||||
}
|
||||
-(void) keyDown:(NSEvent*)event;
|
||||
@end
|
||||
|
||||
@interface CocoaListViewCell : NSTextFieldCell {
|
||||
}
|
||||
-(NSString*) stringValue;
|
||||
-(void) drawWithFrame:(NSRect)frame inView:(NSView*)view;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pListView : public pWidget {
|
||||
ListView& listView;
|
||||
CocoaListView* cocoaListView = nullptr;
|
||||
|
||||
void append(const lstring& text);
|
||||
void autoSizeColumns();
|
||||
void remove(unsigned selection);
|
||||
void reset();
|
||||
void setBackgroundColor(Color color);
|
||||
void setCheckable(bool checkable);
|
||||
void setChecked(unsigned selection, bool checked);
|
||||
void setFont(string font);
|
||||
void setForegroundColor(Color color);
|
||||
void setHeaderText(const lstring& text);
|
||||
void setHeaderVisible(bool visible);
|
||||
void setImage(unsigned selection, unsigned position, const image& image);
|
||||
void setSelected(bool selected);
|
||||
void setSelection(unsigned selection);
|
||||
void setText(unsigned selection, unsigned position, string text);
|
||||
|
||||
pListView(ListView& listView) : pWidget(listView), listView(listView) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
37
hiro/cocoa/widget/progress-bar.cpp
Normal file
37
hiro/cocoa/widget/progress-bar.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
@implementation CocoaProgressBar : NSProgressIndicator
|
||||
|
||||
-(id) initWith:(phoenix::ProgressBar&)progressBarReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
progressBar = &progressBarReference;
|
||||
|
||||
[self setIndeterminate:NO];
|
||||
[self setMinValue:0.0];
|
||||
[self setMaxValue:100.0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
void pProgressBar::setPosition(unsigned position) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setDoubleValue:position];
|
||||
}
|
||||
}
|
||||
|
||||
void pProgressBar::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaProgressBar = [[CocoaProgressBar alloc] initWith:progressBar];
|
||||
setPosition(progressBar.state.position);
|
||||
}
|
||||
}
|
||||
|
||||
void pProgressBar::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
21
hiro/cocoa/widget/progress-bar.hpp
Normal file
21
hiro/cocoa/widget/progress-bar.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
@interface CocoaProgressBar : NSProgressIndicator {
|
||||
@public
|
||||
phoenix::ProgressBar* progressBar;
|
||||
}
|
||||
-(id) initWith:(phoenix::ProgressBar&)progressBar;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pProgressBar : public pWidget {
|
||||
ProgressBar& progressBar;
|
||||
CocoaProgressBar* cocoaProgressBar = nullptr;
|
||||
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pProgressBar(ProgressBar& progressBar) : pWidget(progressBar), progressBar(progressBar) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
94
hiro/cocoa/widget/radio-button.cpp
Normal file
94
hiro/cocoa/widget/radio-button.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
@implementation CocoaRadioButton : NSButton
|
||||
|
||||
-(id) initWith:(phoenix::RadioButton&)radioButtonReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
radioButton = &radioButtonReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setBezelStyle:NSRegularSquareBezelStyle];
|
||||
[self setButtonType:NSOnOffButton];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
bool wasChecked = radioButton->state.checked;
|
||||
radioButton->setChecked();
|
||||
if(wasChecked == false) {
|
||||
if(radioButton->onActivate) radioButton->onActivate();
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pRadioButton::minimumSize() {
|
||||
Size size = Font::size(radioButton.font(), radioButton.state.text);
|
||||
|
||||
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() {
|
||||
@autoreleasepool {
|
||||
for(auto& button : radioButton.state.group) {
|
||||
auto state = (&button == &radioButton) ? NSOnState : NSOffState;
|
||||
[button.p.cocoaView setState:state];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pRadioButton::setGeometry(Geometry geometry) {
|
||||
pWidget::setGeometry({
|
||||
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]];
|
||||
}
|
||||
}
|
||||
|
||||
void pRadioButton::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaRadioButton = [[CocoaRadioButton alloc] initWith:radioButton];
|
||||
}
|
||||
}
|
||||
|
||||
void pRadioButton::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
27
hiro/cocoa/widget/radio-button.hpp
Normal file
27
hiro/cocoa/widget/radio-button.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
@interface CocoaRadioButton : NSButton {
|
||||
@public
|
||||
phoenix::RadioButton* radioButton;
|
||||
}
|
||||
-(id) initWith:(phoenix::RadioButton&)radioButton;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pRadioButton : public pWidget {
|
||||
RadioButton& radioButton;
|
||||
CocoaRadioButton* cocoaRadioButton = nullptr;
|
||||
|
||||
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) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
65
hiro/cocoa/widget/radio-label.cpp
Normal file
65
hiro/cocoa/widget/radio-label.cpp
Normal 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];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
26
hiro/cocoa/widget/radio-label.hpp
Normal file
26
hiro/cocoa/widget/radio-label.hpp
Normal 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();
|
||||
};
|
||||
|
||||
}
|
9
hiro/cocoa/widget/sizable.hpp
Normal file
9
hiro/cocoa/widget/sizable.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace phoenix {
|
||||
|
||||
struct pSizable : public pObject {
|
||||
Sizable& sizable;
|
||||
|
||||
pSizable(Sizable& sizable) : pObject(sizable), sizable(sizable) {}
|
||||
};
|
||||
|
||||
}
|
145
hiro/cocoa/widget/tab-frame.cpp
Normal file
145
hiro/cocoa/widget/tab-frame.cpp
Normal 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++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
41
hiro/cocoa/widget/tab-frame.hpp
Normal file
41
hiro/cocoa/widget/tab-frame.hpp
Normal 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();
|
||||
};
|
||||
|
||||
}
|
107
hiro/cocoa/widget/text-edit.cpp
Normal file
107
hiro/cocoa/widget/text-edit.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
@implementation CocoaTextEdit : NSScrollView
|
||||
|
||||
-(id) initWith:(phoenix::TextEdit&)textEditReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
textEdit = &textEditReference;
|
||||
|
||||
content = [[[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)] autorelease];
|
||||
[content setDelegate:self];
|
||||
[content setRichText:NO];
|
||||
|
||||
[self setBorderType:NSBezelBorder];
|
||||
[self setDocumentView:content];
|
||||
[self configure];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSTextView*) content {
|
||||
return content;
|
||||
}
|
||||
|
||||
-(void) configure {
|
||||
[content setMinSize:NSMakeSize(0, 0)];
|
||||
[content setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
|
||||
|
||||
[[content textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
|
||||
[[content textContainer] setWidthTracksTextView:textEdit->wordWrap()];
|
||||
|
||||
[content setHorizontallyResizable:YES];
|
||||
[content setVerticallyResizable:YES];
|
||||
[content setAutoresizingMask:NSViewNotSizable];
|
||||
|
||||
[self setHasHorizontalScroller:!textEdit->wordWrap()];
|
||||
[self setHasVerticalScroller:YES];
|
||||
}
|
||||
|
||||
-(void) textDidChange:(NSNotification*)notification {
|
||||
textEdit->state.text = [[content string] UTF8String];
|
||||
if(textEdit->onChange) textEdit->onChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
void pTextEdit::setBackgroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pTextEdit::setCursorPosition(unsigned position) {
|
||||
@autoreleasepool {
|
||||
string text = [[[cocoaView content] string] UTF8String];
|
||||
position = min(position, text.length());
|
||||
[[cocoaView content] setSelectedRange:NSMakeRange(position, 0)];
|
||||
}
|
||||
}
|
||||
|
||||
void pTextEdit::setEditable(bool editable) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] setEditable:editable];
|
||||
}
|
||||
}
|
||||
|
||||
void pTextEdit::setFont(string font) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] setFont:pFont::cocoaFont(font)];
|
||||
}
|
||||
}
|
||||
|
||||
void pTextEdit::setForegroundColor(Color color) {
|
||||
}
|
||||
|
||||
void pTextEdit::setText(string text) {
|
||||
@autoreleasepool {
|
||||
[[cocoaView content] setString:[NSString stringWithUTF8String:text]];
|
||||
}
|
||||
}
|
||||
|
||||
void pTextEdit::setWordWrap(bool wordWrap) {
|
||||
@autoreleasepool {
|
||||
[cocoaView configure];
|
||||
}
|
||||
}
|
||||
|
||||
string pTextEdit::text() {
|
||||
@autoreleasepool {
|
||||
return [[[cocoaView content] string] UTF8String];
|
||||
}
|
||||
}
|
||||
|
||||
void pTextEdit::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaTextEdit = [[CocoaTextEdit alloc] initWith:textEdit];
|
||||
setEditable(textEdit.state.editable);
|
||||
setWordWrap(textEdit.state.wordWrap);
|
||||
setFont(textEdit.font());
|
||||
setText(textEdit.state.text);
|
||||
setCursorPosition(textEdit.state.cursorPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void pTextEdit::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
32
hiro/cocoa/widget/text-edit.hpp
Normal file
32
hiro/cocoa/widget/text-edit.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
@interface CocoaTextEdit : NSScrollView <NSTextViewDelegate> {
|
||||
@public
|
||||
phoenix::TextEdit* textEdit;
|
||||
NSTextView* content;
|
||||
}
|
||||
-(id) initWith:(phoenix::TextEdit&)textEdit;
|
||||
-(NSTextView*) content;
|
||||
-(void) configure;
|
||||
-(void) textDidChange:(NSNotification*)notification;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pTextEdit : public pWidget {
|
||||
TextEdit& textEdit;
|
||||
CocoaTextEdit* cocoaTextEdit = nullptr;
|
||||
|
||||
void setBackgroundColor(Color color);
|
||||
void setCursorPosition(unsigned position);
|
||||
void setEditable(bool editable);
|
||||
void setFont(string font);
|
||||
void setForegroundColor(Color color);
|
||||
void setText(string text);
|
||||
void setWordWrap(bool wordWrap);
|
||||
string text();
|
||||
|
||||
pTextEdit(TextEdit& textEdit) : pWidget(textEdit), textEdit(textEdit) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
85
hiro/cocoa/widget/vertical-scroller.cpp
Normal file
85
hiro/cocoa/widget/vertical-scroller.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
@implementation CocoaVerticalScroller : NSScroller
|
||||
|
||||
-(id) initWith:(phoenix::VerticalScroller&)verticalScrollerReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 1)]) {
|
||||
verticalScroller = &verticalScrollerReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(scroll:)];
|
||||
|
||||
[self setControlSize:NSRegularControlSize];
|
||||
[self setScrollerStyle:NSScrollerStyleLegacy];
|
||||
[self setEnabled:YES];
|
||||
|
||||
[self update];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) update {
|
||||
double d = 1.0 / verticalScroller->state.length;
|
||||
double f = d * verticalScroller->state.position;
|
||||
|
||||
[self setDoubleValue:f];
|
||||
[self setKnobProportion:d];
|
||||
}
|
||||
|
||||
-(IBAction) scroll:(id)sender {
|
||||
auto& state = verticalScroller->state;
|
||||
|
||||
switch([self hitPart]) {
|
||||
case NSScrollerIncrementLine:
|
||||
case NSScrollerIncrementPage:
|
||||
if(state.position < state.length - 1) state.position++;
|
||||
[self update];
|
||||
break;
|
||||
|
||||
case NSScrollerDecrementLine:
|
||||
case NSScrollerDecrementPage:
|
||||
if(state.position) state.position--;
|
||||
[self update];
|
||||
break;
|
||||
|
||||
case NSScrollerKnob:
|
||||
state.position = [self doubleValue] * state.length;
|
||||
break;
|
||||
}
|
||||
|
||||
if(verticalScroller->onChange) verticalScroller->onChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pVerticalScroller::minimumSize() {
|
||||
@autoreleasepool {
|
||||
return {[NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegacy], 32};
|
||||
}
|
||||
}
|
||||
|
||||
void pVerticalScroller::setLength(unsigned length) {
|
||||
@autoreleasepool {
|
||||
[cocoaView update];
|
||||
}
|
||||
}
|
||||
|
||||
void pVerticalScroller::setPosition(unsigned position) {
|
||||
@autoreleasepool {
|
||||
[cocoaView update];
|
||||
}
|
||||
}
|
||||
|
||||
void pVerticalScroller::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaVerticalScroller = [[CocoaVerticalScroller alloc] initWith:verticalScroller];
|
||||
}
|
||||
}
|
||||
|
||||
void pVerticalScroller::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
hiro/cocoa/widget/vertical-scroller.hpp
Normal file
25
hiro/cocoa/widget/vertical-scroller.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
@interface CocoaVerticalScroller : NSScroller {
|
||||
@public
|
||||
phoenix::VerticalScroller* verticalScroller;
|
||||
}
|
||||
-(id) initWith:(phoenix::VerticalScroller&)verticalScroller;
|
||||
-(void) update;
|
||||
-(IBAction) scroll:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pVerticalScroller : public pWidget {
|
||||
VerticalScroller& verticalScroller;
|
||||
CocoaVerticalScroller* cocoaVerticalScroller = nullptr;
|
||||
|
||||
Size minimumSize();
|
||||
void setLength(unsigned length);
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pVerticalScroller(VerticalScroller& verticalScroller) : pWidget(verticalScroller), verticalScroller(verticalScroller) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
61
hiro/cocoa/widget/vertical-slider.cpp
Normal file
61
hiro/cocoa/widget/vertical-slider.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
@implementation CocoaVerticalSlider : NSSlider
|
||||
|
||||
-(id) initWith:(phoenix::VerticalSlider&)verticalSliderReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 1)]) {
|
||||
verticalSlider = &verticalSliderReference;
|
||||
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(activate:)];
|
||||
[self setMinValue:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(IBAction) activate:(id)sender {
|
||||
verticalSlider->state.position = [self doubleValue];
|
||||
if(verticalSlider->onChange) verticalSlider->onChange();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
Size pVerticalSlider::minimumSize() {
|
||||
return {20, 48};
|
||||
}
|
||||
|
||||
void pVerticalSlider::setGeometry(Geometry geometry) {
|
||||
pWidget::setGeometry({
|
||||
geometry.x, geometry.y - 2,
|
||||
geometry.width, geometry.height + 4
|
||||
});
|
||||
}
|
||||
|
||||
void pVerticalSlider::setLength(unsigned length) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setMaxValue:length];
|
||||
}
|
||||
}
|
||||
|
||||
void pVerticalSlider::setPosition(unsigned position) {
|
||||
@autoreleasepool {
|
||||
[cocoaView setDoubleValue:position];
|
||||
}
|
||||
}
|
||||
|
||||
void pVerticalSlider::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaVerticalSlider = [[CocoaVerticalSlider alloc] initWith:verticalSlider];
|
||||
|
||||
setLength(verticalSlider.state.length);
|
||||
setPosition(verticalSlider.state.position);
|
||||
}
|
||||
}
|
||||
|
||||
void pVerticalSlider::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
hiro/cocoa/widget/vertical-slider.hpp
Normal file
25
hiro/cocoa/widget/vertical-slider.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
@interface CocoaVerticalSlider : NSSlider {
|
||||
@public
|
||||
phoenix::VerticalSlider* verticalSlider;
|
||||
}
|
||||
-(id) initWith:(phoenix::VerticalSlider&)verticalSlider;
|
||||
-(IBAction) activate:(id)sender;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pVerticalSlider : public pWidget {
|
||||
VerticalSlider& verticalSlider;
|
||||
CocoaVerticalSlider* cocoaVerticalSlider = nullptr;
|
||||
|
||||
Size minimumSize();
|
||||
void setGeometry(Geometry geometry);
|
||||
void setLength(unsigned length);
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pVerticalSlider(VerticalSlider& verticalSlider) : pWidget(verticalSlider), verticalSlider(verticalSlider) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
66
hiro/cocoa/widget/viewport.cpp
Normal file
66
hiro/cocoa/widget/viewport.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
@implementation CocoaViewport : NSView
|
||||
|
||||
-(id) initWith:(phoenix::Viewport&)viewportReference {
|
||||
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
||||
viewport = &viewportReference;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) drawRect:(NSRect)rect {
|
||||
[[NSColor blackColor] setFill];
|
||||
NSRectFillUsingOperation(rect, NSCompositeSourceOver);
|
||||
}
|
||||
|
||||
-(BOOL) acceptsFirstResponder {
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender {
|
||||
return DropPathsOperation(sender);
|
||||
}
|
||||
|
||||
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender {
|
||||
lstring paths = DropPaths(sender);
|
||||
if(paths.empty()) return NO;
|
||||
if(viewport->onDrop) viewport->onDrop(paths);
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void) keyDown:(NSEvent*)event {
|
||||
}
|
||||
|
||||
-(void) keyUp:(NSEvent*)event {
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
uintptr_t pViewport::handle() {
|
||||
return (uintptr_t)cocoaViewport;
|
||||
}
|
||||
|
||||
void pViewport::setDroppable(bool droppable) {
|
||||
@autoreleasepool {
|
||||
if(droppable) {
|
||||
[cocoaViewport registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
||||
} else {
|
||||
[cocoaViewport unregisterDraggedTypes];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pViewport::constructor() {
|
||||
@autoreleasepool {
|
||||
cocoaView = cocoaViewport = [[CocoaViewport alloc] initWith:viewport];
|
||||
}
|
||||
}
|
||||
|
||||
void pViewport::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
28
hiro/cocoa/widget/viewport.hpp
Normal file
28
hiro/cocoa/widget/viewport.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
@interface CocoaViewport : NSView {
|
||||
@public
|
||||
phoenix::Viewport* viewport;
|
||||
}
|
||||
-(id) initWith:(phoenix::Viewport&)viewport;
|
||||
-(void) drawRect:(NSRect)rect;
|
||||
-(BOOL) acceptsFirstResponder;
|
||||
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender;
|
||||
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender;
|
||||
-(void) keyDown:(NSEvent*)event;
|
||||
-(void) keyUp:(NSEvent*)event;
|
||||
@end
|
||||
|
||||
namespace phoenix {
|
||||
|
||||
struct pViewport : public pWidget {
|
||||
Viewport& viewport;
|
||||
CocoaViewport* cocoaViewport = nullptr;
|
||||
|
||||
uintptr_t handle();
|
||||
void setDroppable(bool droppable);
|
||||
|
||||
pViewport(Viewport& viewport) : pWidget(viewport), viewport(viewport) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
79
hiro/cocoa/widget/widget.cpp
Normal file
79
hiro/cocoa/widget/widget.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
namespace phoenix {
|
||||
|
||||
bool pWidget::enabled() {
|
||||
@autoreleasepool {
|
||||
return [cocoaView respondsToSelector:@selector(enabled)] && [cocoaView enabled];
|
||||
}
|
||||
}
|
||||
|
||||
bool pWidget::focused() {
|
||||
@autoreleasepool {
|
||||
return cocoaView == [[cocoaView window] firstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
Size pWidget::minimumSize() {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
void pWidget::setEnabled(bool enabled) {
|
||||
if(!widget.parent()) enabled = false;
|
||||
if(widget.state.abstract) enabled = false;
|
||||
if(!widget.enabledToAll()) enabled = false;
|
||||
|
||||
@autoreleasepool {
|
||||
if([cocoaView respondsToSelector:@selector(setEnabled:)]) {
|
||||
[cocoaView setEnabled:enabled];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pWidget::setFocused() {
|
||||
@autoreleasepool {
|
||||
[[cocoaView window] makeFirstResponder:cocoaView];
|
||||
}
|
||||
}
|
||||
|
||||
void pWidget::setFont(string font) {
|
||||
@autoreleasepool {
|
||||
if([cocoaView respondsToSelector:@selector(setFont:)]) {
|
||||
[cocoaView setFont:pFont::cocoaFont(font)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pWidget::setGeometry(Geometry geometry) {
|
||||
@autoreleasepool {
|
||||
CGFloat windowHeight = [[cocoaView superview] frame].size.height;
|
||||
[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(!widget.visibleToAll()) visible = false;
|
||||
|
||||
@autoreleasepool {
|
||||
[cocoaView setHidden:!visible];
|
||||
}
|
||||
}
|
||||
|
||||
void pWidget::constructor() {
|
||||
if(!widget.state.abstract) return;
|
||||
|
||||
@autoreleasepool {
|
||||
cocoaView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)];
|
||||
[cocoaView setHidden:true];
|
||||
}
|
||||
}
|
||||
|
||||
void pWidget::destructor() {
|
||||
@autoreleasepool {
|
||||
[cocoaView release];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
21
hiro/cocoa/widget/widget.hpp
Normal file
21
hiro/cocoa/widget/widget.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace phoenix {
|
||||
|
||||
struct pWidget : public pSizable {
|
||||
Widget& widget;
|
||||
NSView* cocoaView = nullptr;
|
||||
|
||||
bool enabled();
|
||||
bool focused();
|
||||
virtual Size minimumSize();
|
||||
virtual void setEnabled(bool enabled);
|
||||
void setFocused();
|
||||
virtual void setFont(string font);
|
||||
virtual void setGeometry(Geometry geometry);
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
}
|
Reference in New Issue
Block a user