Sun, 07 Dec 2025 20:00:33 +0100
fix settings dialog doesn't open when there is no .dav/config.xml file
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2025 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. */ #include "grid.h" #include "../../ucx/cx/array_list.h" #include "../common/context.h" #include <stdio.h> #include <stdlib.h> UiGridLayout* ui_grid_layout_create(const CxAllocator *a, short columnspacing, short rowspacing) { UiGridLayout *grid = cxZalloc(a, sizeof(UiGridLayout)); grid->widgets = cxArrayListCreate(a, NULL, sizeof(GridElm), 32); grid->columnspacing = columnspacing; grid->rowspacing = rowspacing; return grid; } void ui_grid_add_widget( UiGridLayout *grid, short x, short y, W32Widget *widget, GridLayoutInfo *layout) { // add the widget GridElm elm; elm.widget = widget; elm.gridx = x; elm.gridy = y; elm.layout = *layout; cxListAdd(grid->widgets, &elm); // adjust max col/row count if (x > grid->max_column) { grid->max_column = x; } if (y > grid->max_row) { grid->max_row = y; } } void ui_grid_layout(UiGridLayout *grid, int width, int height) { if (width == 0 || height == 0) { return; } int ncols = grid->max_column+1; int nrows = grid->max_row+1; GridDef *cols = calloc(ncols, sizeof(GridDef)); GridDef *rows = calloc(nrows, sizeof(GridDef)); int colspacing = grid->columnspacing; int rowspacing = grid->rowspacing; int span_max = 1; for(int r=0;r<2;r++) { CxIterator i = cxListIterator(grid->widgets); cx_foreach(GridElm *, elm, i) { int x = elm->gridx; int y = elm->gridy; GridDef *col = &cols[x]; GridDef *row = &rows[y]; W32Size size = w32_widget_get_preferred_size(elm->widget); elm->layout.preferred_width = size.width; elm->layout.preferred_height = size.height; int elm_width = size.width + elm->layout.margin.left + elm->layout.margin.right; if(elm_width > cols[elm->gridx].preferred_size && elm->layout.colspan <= 1 && span_max == 1) { cols[elm->gridx].preferred_size = elm_width; } int elm_height = size.height + elm->layout.margin.top + elm->layout.margin.bottom; if(elm_height > rows[elm->gridy].preferred_size && elm->layout.rowspan <= 1 && span_max == 1) { rows[elm->gridy].preferred_size = elm_height; } if(elm->layout.rowspan > span_max || elm->layout.colspan > span_max) { continue; } int end_col = x+elm->layout.colspan; if(end_col > ncols) { end_col = ncols; } int end_row = y+elm->layout.rowspan; if(end_row > nrows) { end_row = nrows; } // are all columns in the span > preferred_width? if(elm->layout.colspan > 1) { int span_width = 0; GridDef *last_col = col; for(int c=x;c<end_col;c++) { span_width += cols[c].size; last_col = &cols[c]; } if(span_width < elm->layout.preferred_width) { last_col->size += elm->layout.preferred_width - span_width; } } // are all rows in the span > preferred_height? if(elm->layout.rowspan > 1) { int span_height = 0; GridDef *last_row = row; for(int c=x;c<end_row;c++) { span_height += rows[c].size; last_row = &rows[c]; } if(span_height < elm->layout.preferred_height) { last_row->size += elm->layout.preferred_height - span_height; } } if(elm->layout.hexpand) { if(elm->layout.colspan > 1) { // check if any column in the span is expanding // if not, make the last column expanding GridDef *last_col = col; for(int c=x;c<end_col;c++) { last_col = &cols[c]; if(last_col->expand) { break; } } last_col->expand = TRUE; } else { col->expand = TRUE; } } if(elm->layout.vexpand) { if(elm->layout.rowspan > 1) { // same as colspan GridDef *last_row = row; for(int c=x;c<nrows;c++) { last_row = &rows[c]; if(last_row->expand) { break; } } last_row->expand = TRUE; } else { row->expand = TRUE; } } } span_max = 50000; // not sure if this is unreasonable low or high } int col_ext = 0; int row_ext = 0; int preferred_width = 0; int preferred_height = 0; for(int j=0;j<ncols;j++) { preferred_width += cols[j].preferred_size; if(cols[j].expand) { col_ext++; } } for(int j=0;j<nrows;j++) { preferred_height += rows[j].preferred_size; if(rows[j].expand) { row_ext++; } } if(ncols > 0) { preferred_width += (ncols-1) * colspacing; } if(nrows > 0) { preferred_height += (nrows-1) * rowspacing; } grid->preferred_width = preferred_width; grid->preferred_height = preferred_height; int hremaining = width - preferred_width; int vremaining = height - preferred_height; int hext = col_ext > 0 ? hremaining/col_ext : 0; int vext = row_ext > 0 ? vremaining/row_ext : 0; for(int j=0;j<ncols;j++) { GridDef *col = &cols[j]; if(col->expand) { col->size = col->preferred_size + hext; } else { col->size = col->preferred_size; } } for(int j=0;j<nrows;j++) { GridDef *row = &rows[j]; if(row->expand) { row->size = row->preferred_size + vext; } else { row->size = row->preferred_size; } } int pos = 0; for(int j=0;j<ncols;j++) { cols[j].pos = pos; pos += cols[j].size + colspacing; } pos = 0; for(int j=0;j<nrows;j++) { rows[j].pos = pos; pos += rows[j].size + rowspacing; } CxIterator i = cxListIterator(grid->widgets); cx_foreach(GridElm *, elm, i) { GridDef *col = &cols[elm->gridx]; GridDef *row = &rows[elm->gridy]; int child_width = 0; int child_height = 0; int child_x = 0; int child_y = 0; if(elm->layout.hfill) { if(elm->layout.colspan > 1) { int cwidth = 0; int end_col = elm->gridx + elm->layout.colspan; if(end_col > ncols) { end_col = ncols; } int real_span = 0; for(int c=elm->gridx;c<end_col;c++) { cwidth += cols[c].size; real_span++; } if(real_span > 0) { cwidth += (real_span-1) * colspacing; } child_width = cwidth; } else { child_width = col->size; } child_width -= elm->layout.margin.left + elm->layout.margin.right; } else { child_width = elm->layout.preferred_width; } if(elm->layout.vfill) { if(elm->layout.rowspan > 1) { int rheight = 0; int end_row = elm->gridy + elm->layout.rowspan; if(end_row > nrows) { end_row = nrows; } int real_span = 0; for(int r=elm->gridy;r<end_row;r++) { rheight += rows[r].size; real_span++; } if(real_span > 0) { rheight += (real_span-1) * rowspacing; } child_height = rheight; } child_height = row->size - elm->layout.margin.top - elm->layout.margin.bottom; } else { child_height = elm->layout.preferred_height; } child_x = col->pos + elm->layout.margin.left; child_y = row->pos + elm->layout.margin.top; SetWindowPos(elm->widget->hwnd, NULL, child_x, child_y, child_width, child_height, SWP_NOZORDER); if (elm->widget->layout) { elm->widget->layout(elm->widget->layoutmanager, child_width, child_height); } } free(cols); free(rows); }