ui/cocoa/container.m

Sun, 15 Dec 2024 22:13:05 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 15 Dec 2024 22:13:05 +0100
branch
newapi
changeset 417
f0fee61a70be
parent 404
384f6d1f5784
permissions
-rw-r--r--

implement menu item callbacks (Motif)

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2024 Olaf Wintermann. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#import "Container.h"
#import "GridLayout.h"

/* ------------------------- container classes ------------------------- */

@implementation BoxContainer

@synthesize label=_label;
@synthesize uilayout=_uilayout;
@synthesize newline=_newline;

- (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing {
    self = [super init];
    _label = NULL;
    _uilayout = (UiLayout){ 0 };
    _newline = false;
    
    self.distribution = NSStackViewDistributionFillProportionally;
    self.spacing = spacing;
    
    self.orientation = orientation;
    if(orientation == NSUserInterfaceLayoutOrientationHorizontal) {
        self.alignment = NSLayoutAttributeHeight;
    } else {
        self.alignment = NSLayoutAttributeWidth;
    }
    
    
    return self;
}

- (void) addView:(NSView*)view fill:(BOOL)fill {
    if(_uilayout.fill != UI_LAYOUT_UNDEFINED) {
        fill = ui_lb2bool(_uilayout.fill);
    }
    
    [self addArrangedSubview:view];
    
    if(self.orientation == NSUserInterfaceLayoutOrientationHorizontal) {
        [view.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES;
        if(!fill) {
            [view.widthAnchor constraintEqualToConstant:view.intrinsicContentSize.width].active = YES;
        }
    } else {
        [view.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES;
        if(!fill) {
            [view.heightAnchor constraintEqualToConstant:view.intrinsicContentSize.height].active = YES;
        }
    }
    
    // at the moment, only the fill layout option needs to be reset
    _uilayout.fill = UI_DEFAULT;
}

@end



/* -------------------- public container functions --------------------- */

static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, NSUserInterfaceLayoutOrientation orientation) {
    BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args.spacing];
    box.translatesAutoresizingMaskIntoConstraints = false;
    
    // add box to the parent
    UiLayout layout = UI_INIT_LAYOUT(args);
    ui_container_add(obj, box, &layout, TRUE);
    
    // add new box to the obj container chain
    uic_object_push_container(obj, ui_create_container(obj, box));
    
    return (__bridge void*)box;
}

UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) {
    return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationVertical);
}

UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) {
    return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationHorizontal);
}

UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) {
    GridLayout *grid = [[GridLayout alloc] init];
    grid.translatesAutoresizingMaskIntoConstraints = false;
    
    // add box to the parent
    UiLayout layout = UI_INIT_LAYOUT(args);
    ui_container_add(obj, grid, &layout, TRUE);
    
    // add new box to the obj container chain
    uic_object_push_container(obj, ui_create_container(obj, grid));
    
    return (__bridge void*)grid;
}


void ui_container_begin_close(UiObject *obj) {
    UiContainerX *ct = obj->container_end;
    ct->close = 1;
}

int ui_container_finish(UiObject *obj) {
    UiContainerX *ct = obj->container_end;
    if(ct->close) {
        ui_end_new(obj);
        return 0;
    }
    return 1;
}

/* ------------------------- private functions ------------------------- */

UiContainerX* ui_create_container(UiObject *obj, id<Container> container) {
    UiContainerX *ctn = ui_malloc(obj->ctx, sizeof(UiContainerX));
    ctn->container = (__bridge void*)container;
    ctn->close = 0;
    ctn->prev = NULL;
    ctn->next = NULL;
    return ctn;
}

void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout, UiBool fill) {
    UiContainerX *ctn = obj->container_end;
    id<Container> container = (__bridge id<Container>)ctn->container;
    container.uilayout = *layout;
    [container addView:view fill:fill];
}

/* ---------------------- public layout functions ----------------------- */

void ui_newline(UiObject *obj) {
    UiContainerX *ctn = obj->container_end;
    if(ctn) {
        id<Container> container = (__bridge id<Container>)ctn->container;
        container.newline = TRUE;
    } else {
        fprintf(stderr, "Error: obj has no container\n");
    }
}

mercurial