Turned the direct method calls on uiTableModel into functions to make the call sites look a bit cleaner. More stuff will go into common/tablemodel.c...

This commit is contained in:
Pietro Gagliardi 2018-06-23 23:35:42 -04:00
parent 9a79eed2ac
commit 74ec21f4c7
15 changed files with 121 additions and 46 deletions

View File

@ -10,6 +10,7 @@ list(APPEND _LIBUI_SOURCES
common/matrix.c
common/opentype.c
common/shouldquit.c
common/tablemodel.c
common/tablevalue.c
common/userbugs.c
common/utf.c

17
common/table.h Normal file
View File

@ -0,0 +1,17 @@
// 23 june 2018
#ifdef __cplusplus
extern "C" {
#endif
// tablemodel.c
extern uiTableModelHandler *uiprivTableModelHandler(uiTableModel *m);
extern int uiprivTableModelNumColumns(uiTableModel *m);
extern uiTableValueType uiprivTableModelColumnType(uiTableModel *m, int column);
extern int uiprivTableModelNumRows(uiTableModel *m);
extern uiTableValue *uiprivTableModelCellValue(uiTableModel *m, int row, int column);
extern void uiprivTableModelSetCellValue(uiTableModel *m, int row, int column, const uiTableValue *value);
#ifdef __cplusplus
}
#endif

44
common/tablemodel.c Normal file
View File

@ -0,0 +1,44 @@
// 23 june 2018
#include "../ui.h"
#include "uipriv.h"
#include "table.h"
int uiprivTableModelNumColumns(uiTableModel *m)
{
uiTableModelHandler *mh;
mh = uiprivTableModelHandler(m);
return (*(mh->NumColumns))(mh, m);
}
uiTableValueType uiprivTableModelColumnType(uiTableModel *m, int column)
{
uiTableModelHandler *mh;
mh = uiprivTableModelHandler(m);
return (*(mh->ColumnType))(mh, m, column);
}
int uiprivTableModelNumRows(uiTableModel *m)
{
uiTableModelHandler *mh;
mh = uiprivTableModelHandler(m);
return (*(mh->NumRows))(mh, m);
}
uiTableValue *uiprivTableModelCellValue(uiTableModel *m, int row, int column)
{
uiTableModelHandler *mh;
mh = uiprivTableModelHandler(m);
return (*(mh->CellValue))(mh, m, row, column);
}
void uiprivTableModelSetCellValue(uiTableModel *m, int row, int column, const uiTableValue *value)
{
uiTableModelHandler *mh;
mh = uiprivTableModelHandler(m);
(*(mh->SetCellValue))(mh, m, row, column, value);
}

View File

@ -1,6 +1,7 @@
// 3 june 2018
#include "../ui.h"
#include "uipriv.h"
#include "table.h"
struct uiTableValue {
uiTableValueType type;

View File

@ -1,4 +1,5 @@
// 3 june 2018
#import "../common/table.h"
// table.m
// TODO get rid of forward declaration

View File

@ -37,7 +37,7 @@ static void setBackgroundColor(uiprivTableView *t, NSTableRowView *rv, NSInteger
if (t->uiprivT->backgroundColumn == -1)
return;
value = (*(t->uiprivM->mh->CellValue))(t->uiprivM->mh, t->uiprivM, row, t->uiprivT->backgroundColumn);
value = uiprivTableModelCellValue(t->uiprivM, row, t->uiprivT->backgroundColumn);
if (value != NULL) {
uiTableValueColor(value, &r, &g, &b, &a);
uiFreeTableValue(value);
@ -70,7 +70,7 @@ static void setBackgroundColor(uiprivTableView *t, NSTableRowView *rv, NSInteger
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tv
{
return (*(self->m->mh->NumRows))(self->m->mh, self->m);
return uiprivTableModelNumRows(self->m);
}
- (NSView *)tableView:(NSTableView *)tv viewForTableColumn:(NSTableColumn *)cc row:(NSInteger)row
@ -155,6 +155,11 @@ void uiTableModelRowDeleted(uiTableModel *m, int oldIndex)
// set is autoreleased
}
uiTableModelHandler *uiprivTableModelHandler(uiTableModel *m)
{
return m->mh;
}
uiDarwinControlAllDefaultsExceptDestroy(uiTable, sv)
static void uiTableDestroy(uiControl *c)

View File

@ -45,7 +45,7 @@ static BOOL isCellEditable(uiTableModel *m, NSInteger row, int modelColumn)
case uiTableModelColumnAlwaysEditable:
return YES;
}
value = (*(m->mh->CellValue))(m->mh, m, row, modelColumn);
value = uiprivTableModelCellValue(m, row, modelColumn);
editable = uiTableValueInt(value);
uiFreeTableValue(value);
return editable != 0;
@ -271,7 +271,7 @@ struct textColumnCreateParams {
NSString *str;
NSColor *color;
value = (*(self->m->mh->CellValue))(self->m->mh, self->m, row, self->textModelColumn);
value = uiprivTableModelCellValue(self->m, row, self->textModelColumn);
str = uiprivToNSString(uiTableValueString(value));
uiFreeTableValue(value);
[self->tf setStringValue:str];
@ -282,7 +282,7 @@ struct textColumnCreateParams {
if (self->textParams.ColorModelColumn != -1) {
double r, g, b, a;
value = (*(self->m->mh->CellValue))(self->m->mh, self->m, row, self->textParams.ColorModelColumn);
value = uiprivTableModelCellValue(self->m, row, self->textParams.ColorModelColumn);
// TODO document this is allowed
if (value != NULL) {
uiTableValueColor(value, &r, &g, &b, &a);
@ -298,13 +298,13 @@ struct textColumnCreateParams {
if (self->iv != nil) {
uiImage *img;
value = (*(self->m->mh->CellValue))(self->m->mh, self->m, row, self->imageModelColumn);
value = uiprivTableModelCellValue(self->m, row, self->imageModelColumn);
img = uiTableValueImage(value);
uiFreeTableValue(value);
[self->iv setImage:uiprivImageNSImage(img)];
}
if (self->cb != nil) {
value = (*(self->m->mh->CellValue))(self->m->mh, self->m, row, self->imageModelColumn);
value = uiprivTableModelCellValue(self->m, row, self->imageModelColumn);
if (uiTableValueInt(value) != 0)
[self->cb setState:NSOnState];
else
@ -322,8 +322,7 @@ struct textColumnCreateParams {
row = [self->t->tv rowForView:self->tf];
value = uiNewTableValueString([[self->tf stringValue] UTF8String]);
(*(self->m->mh->SetCellValue))(self->m->mh, self->m,
row, self->textModelColumn, value);
uiprivTableModelSetCellValue(self->m, row, self->textModelColumn, value);
uiFreeTableValue(value);
// always refresh the value in case the model rejected it
// TODO document that we do this, but not for the whole row (or decide to do both, or do neither...)
@ -337,8 +336,7 @@ struct textColumnCreateParams {
row = [self->t->tv rowForView:self->cb];
value = uiNewTableValueInt([self->cb state] != NSOffState);
(*(self->m->mh->SetCellValue))(self->m->mh, self->m,
row, self->checkboxModelColumn, value);
uiprivTableModelSetCellValue(self->m, row, self->checkboxModelColumn, value);
uiFreeTableValue(value);
// always refresh the value in case the model rejected it
[self uiprivUpdate:row];
@ -436,7 +434,7 @@ struct textColumnCreateParams {
uiTableValue *value;
int progress;
value = (*(self->m->mh->CellValue))(self->m->mh, self->m, row, self->modelColumn);
value = uiprivTableModelCellValue(self->m, row, self->modelColumn);
progress = uiTableValueInt(value);
uiFreeTableValue(value);
if (progress == -1) {
@ -559,7 +557,7 @@ struct textColumnCreateParams {
uiTableValue *value;
NSString *str;
value = (*(self->m->mh->CellValue))(self->m->mh, self->m, row, self->modelColumn);
value = uiprivTableModelCellValue(self->m, row, self->modelColumn);
str = uiprivToNSString(uiTableValueString(value));
uiFreeTableValue(value);
[self->b setTitle:str];
@ -572,8 +570,7 @@ struct textColumnCreateParams {
NSInteger row;
row = [self->t->tv rowForView:self->b];
(*(self->m->mh->SetCellValue))(self->m->mh, self->m,
row, self->modelColumn, NULL);
uiprivTableModelSetCellValue(self->m, row, self->modelColumn, NULL);
// TODO document we DON'T update the cell after doing this
}

View File

@ -84,7 +84,7 @@ static void onEdited(uiTableModel *m, int column, const char *pathstr, const uiT
if (iter != NULL)
gtk_tree_model_get_iter(GTK_TREE_MODEL(m), iter, path);
gtk_tree_path_free(path);
(*(m->mh->SetCellValue))(m->mh, m, row, column, tvalue);
uiprivTableModelSetCellValue(m, row, column, tvalue);
}
// TODO deduplicate this between platforms

View File

@ -1,4 +1,5 @@
// 4 june 2018
#include "../common/table.h"
// tablemodel.c
#define uiTableModelType (uiTableModel_get_type())

View File

@ -31,14 +31,14 @@ static gint uiTableModel_get_n_columns(GtkTreeModel *mm)
{
uiTableModel *m = uiTableModel(mm);
return (*(m->mh->NumColumns))(m->mh, m);
return uiprivTableModelNumColumns(m);
}
static GType uiTableModel_get_column_type(GtkTreeModel *mm, gint index)
{
uiTableModel *m = uiTableModel(mm);
switch ((*(m->mh->ColumnType))(m->mh, m, index)) {
switch (uiprivTableModelColumnType(m, index)) {
case uiTableValueTypeString:
return G_TYPE_STRING;
case uiTableValueTypeImage:
@ -65,7 +65,7 @@ static gboolean uiTableModel_get_iter(GtkTreeModel *mm, GtkTreeIter *iter, GtkTr
row = gtk_tree_path_get_indices(path)[0];
if (row < 0)
goto bad;
if (row >= (*(m->mh->NumRows))(m->mh, m))
if (row >= uiprivTableModelNumRows(m))
goto bad;
iter->stamp = STAMP_GOOD;
iter->user_data = GINT_TO_POINTER(row);
@ -98,8 +98,8 @@ static void uiTableModel_get_value(GtkTreeModel *mm, GtkTreeIter *iter, gint col
if (iter->stamp != STAMP_GOOD)
return;
row = GPOINTER_TO_INT(iter->user_data);
tvalue = (*(m->mh->CellValue))(m->mh, m, row, column);
switch ((*(m->mh->ColumnType))(m->mh, m, column)) {
tvalue = uiprivTableModelCellValue(m, row, column);
switch (uiprivTableModelColumnType(m, column)) {
case uiTableValueTypeString:
g_value_init(value, G_TYPE_STRING);
g_value_set_string(value, uiTableValueString(tvalue));
@ -142,7 +142,7 @@ static gboolean uiTableModel_iter_next(GtkTreeModel *mm, GtkTreeIter *iter)
return FALSE;
row = GPOINTER_TO_INT(iter->user_data);
row++;
if (row >= (*(m->mh->NumRows))(m->mh, m)) {
if (row >= uiprivTableModelNumRows(m)) {
iter->stamp = STAMP_BAD;
return FALSE;
}
@ -182,7 +182,7 @@ static gint uiTableModel_iter_n_children(GtkTreeModel *mm, GtkTreeIter *iter)
if (iter != NULL)
return 0;
return (*(m->mh->NumRows))(m->mh, m);
return uiprivTableModelNumRows(m);
}
static gboolean uiTableModel_iter_nth_child(GtkTreeModel *mm, GtkTreeIter *iter, GtkTreeIter *parent, gint n)
@ -195,7 +195,7 @@ static gboolean uiTableModel_iter_nth_child(GtkTreeModel *mm, GtkTreeIter *iter,
goto bad;
if (n < 0)
goto bad;
if (n >= (*(m->mh->NumRows))(m->mh, m))
if (n >= uiprivTableModelNumRows(m))
goto bad;
iter->stamp = STAMP_GOOD;
iter->user_data = GINT_TO_POINTER(n);
@ -281,3 +281,8 @@ void uiTableModelRowDeleted(uiTableModel *m, int oldIndex)
gtk_tree_model_row_deleted(GTK_TREE_MODEL(m), path);
gtk_tree_path_free(path);
}
uiTableModelHandler *uiprivTableModelHandler(uiTableModel *m)
{
return m->mh;
}

View File

@ -33,7 +33,7 @@ void uiTableModelRowInserted(uiTableModel *m, int newIndex)
LVITEMW item;
int newCount;
newCount = (*(m->mh->NumRows))(m->mh, m);
newCount = uiprivTableModelNumRows(m);
ZeroMemory(&item, sizeof (LVITEMW));
item.mask = 0;
item.iItem = newIndex;
@ -66,7 +66,7 @@ void uiTableModelRowDeleted(uiTableModel *m, int oldIndex)
{
int newCount;
newCount = (*(m->mh->NumRows))(m->mh, m);
newCount = uiprivTableModelNumRows(m);
newCount--;
for (auto t : *(m->tables)) {
// update selection state
@ -82,6 +82,11 @@ void uiTableModelRowDeleted(uiTableModel *m, int oldIndex)
}
}
uiTableModelHandler *uiprivTableModelHandler(uiTableModel *m)
{
return m->mh;
}
// TODO explain all this
static LRESULT CALLBACK tableSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIDSubclass, DWORD_PTR dwRefData)
{
@ -195,7 +200,7 @@ int uiprivTableProgress(uiTable *t, int item, int subitem, int modelColumn, LONG
bool startTimer = false;
bool stopTimer = false;
value = (*(t->model->mh->CellValue))(t->model->mh, t->model, item, modelColumn);
value = uiprivTableModelCellValue(t->model, item, modelColumn);
progress = uiTableValueInt(value);
uiFreeTableValue(value);
@ -508,7 +513,7 @@ uiTable *uiNewTable(uiTableModel *model)
SendMessageW(t->hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE,
(WPARAM) (LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP | LVS_EX_SUBITEMIMAGES),
(LPARAM) (LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP | LVS_EX_SUBITEMIMAGES));
n = (*(model->mh->NumRows))(model->mh, model);
n = uiprivTableModelNumRows(model);
if (SendMessageW(t->hwnd, LVM_SETITEMCOUNT, (WPARAM) n, 0) == 0)
logLastError(L"error calling LVM_SETITEMCOUNT in uiNewTable()");

View File

@ -1,4 +1,5 @@
// 10 june 2018
#include "../common/table.h"
// table.cpp
#define uiprivNumLVN_GETDISPINFOSkip 3

View File

@ -22,7 +22,7 @@ static HRESULT handleLVIF_TEXT(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnP
else if (p->buttonModelColumn != -1)
strcol = p->buttonModelColumn;
if (strcol != -1) {
value = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, strcol);
value = uiprivTableModelCellValue(t->model, nm->item.iItem, strcol);
wstr = toUTF16(uiTableValueString(value));
uiFreeTableValue(value);
// We *could* just make pszText into a freshly allocated

View File

@ -5,9 +5,6 @@
// TODOs:
// - properly hide selection when not focused (or switch on LVS_SHOWSELALWAYS and draw that state)
// TODO
#define cellValue(model, row, column) ((*((model)->mh->CellValue))((model)->mh, (model), (row), (column)))
// TODO maybe split this into item and subitem structs?
struct drawState {
uiTable *t;
@ -78,7 +75,7 @@ static HRESULT drawImagePart(HRESULT hr, struct drawState *s)
if (s->p->imageModelColumn == -1)
return S_OK;
value = cellValue(s->model, s->iItem, s->p->imageModelColumn);
value = uiprivTableModelCellValue(s->model, s->iItem, s->p->imageModelColumn);
wb = uiprivImageAppropriateForDC(uiTableValueImage(value), s->dc);
uiFreeTableValue(value);
@ -197,7 +194,7 @@ static HRESULT drawCheckboxPart(HRESULT hr, struct drawState *s)
if (s->p->checkboxModelColumn == -1)
return S_OK;
value = cellValue(s->model, s->iItem, s->p->checkboxModelColumn);
value = uiprivTableModelCellValue(s->model, s->iItem, s->p->checkboxModelColumn);
checked = uiTableValueInt(value);
uiFreeTableValue(value);
switch (s->p->checkboxEditableColumn) {
@ -208,7 +205,7 @@ static HRESULT drawCheckboxPart(HRESULT hr, struct drawState *s)
enabled = 1;
break;
default:
value = cellValue(s->model, s->iItem, s->p->checkboxEditableColumn);
value = uiprivTableModelCellValue(s->model, s->iItem, s->p->checkboxEditableColumn);
enabled = uiTableValueInt(value);
uiFreeTableValue(value);
}
@ -258,7 +255,7 @@ static HRESULT drawTextPart(HRESULT hr, struct drawState *s)
return E_FAIL;
}
value = cellValue(s->model, s->iItem, s->p->textModelColumn);
value = uiprivTableModelCellValue(s->model, s->iItem, s->p->textModelColumn);
wstr = toUTF16(uiTableValueString(value));
uiFreeTableValue(value);
// These flags are a menagerie of flags from various sources:
@ -414,7 +411,7 @@ static HRESULT drawButtonPart(HRESULT hr, struct drawState *s)
if (s->p->buttonModelColumn == -1)
return S_OK;
value = cellValue(s->model, s->iItem, s->p->buttonModelColumn);
value = uiprivTableModelCellValue(s->model, s->iItem, s->p->buttonModelColumn);
wstr = toUTF16(uiTableValueString(value));
uiFreeTableValue(value);
switch (s->p->buttonClickableModelColumn) {
@ -425,7 +422,7 @@ static HRESULT drawButtonPart(HRESULT hr, struct drawState *s)
enabled = 1;
break;
default:
value = cellValue(s->model, s->iItem, s->p->checkboxEditableColumn);
value = uiprivTableModelCellValue(s->model, s->iItem, s->p->checkboxEditableColumn);
enabled = uiTableValueInt(value);
uiFreeTableValue(value);
}
@ -580,7 +577,7 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
s->bgColor = GetSysColor(COLOR_WINDOW);
s->bgBrush = GetSysColorBrush(COLOR_WINDOW);
if (t->backgroundColumn != -1) {
value = cellValue(s->model, s->iItem, t->backgroundColumn);
value = uiprivTableModelCellValue(s->model, s->iItem, t->backgroundColumn);
if (value != NULL) {
uiTableValueColor(value, &r, &g, &b, &a);
uiFreeTableValue(value);
@ -597,7 +594,7 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
s->textColor = GetSysColor(COLOR_WINDOWTEXT);
s->textBrush = GetSysColorBrush(COLOR_WINDOWTEXT);
if (p->textParams.ColorModelColumn != -1) {
value = cellValue(s->model, s->iItem, p->textParams.ColorModelColumn);
value = uiprivTableModelCellValue(s->model, s->iItem, p->textParams.ColorModelColumn);
if (value != NULL) {
uiTableValueColor(value, &r, &g, &b, &a);
uiFreeTableValue(value);

View File

@ -105,7 +105,7 @@ static HRESULT openEditControl(uiTable *t, int iItem, int iSubItem, uiprivTableC
return hr;
// the real list view creates the edit control with the string
value = (*(t->model->mh->CellValue))(t->model->mh, t->model, iItem, p->textModelColumn);
value = uiprivTableModelCellValue(t->model, iItem, p->textModelColumn);
wstr = toUTF16(uiTableValueString(value));
uiFreeTableValue(value);
// TODO copy WS_EX_RTLREADING
@ -166,7 +166,7 @@ HRESULT uiprivTableFinishEditingText(uiTable *t)
value = uiNewTableValueString(text);
uiFreeText(text);
p = (*(t->columns))[t->editedSubitem];
(*(t->model->mh->SetCellValue))(t->model->mh, t->model, t->editedItem, p->textModelColumn, value);
uiprivTableModelSetCellValue(t->model, t->editedItem, p->textModelColumn, value);
uiFreeTableValue(value);
// always refresh the value in case the model rejected it
if (SendMessageW(t->hwnd, LVM_UPDATE, (WPARAM) (t->editedItem), 0) == (LRESULT) (-1)) {
@ -238,7 +238,7 @@ HRESULT uiprivTableHandleNM_CLICK(uiTable *t, NMITEMACTIVATE *nm, LRESULT *lResu
case uiTableModelColumnAlwaysEditable:
break;
default:
value = (*(t->model->mh->CellValue))(t->model->mh, t->model, ht.iItem, editableColumn);
value = uiprivTableModelCellValue(t->model, ht.iItem, editableColumn);
editable = uiTableValueInt(value);
uiFreeTableValue(value);
if (!editable)
@ -252,14 +252,14 @@ HRESULT uiprivTableHandleNM_CLICK(uiTable *t, NMITEMACTIVATE *nm, LRESULT *lResu
} else if (checkbox) {
if ((ht.flags & LVHT_ONITEMICON) == 0)
goto done;
value = (*(t->model->mh->CellValue))(t->model->mh, t->model, ht.iItem, modelColumn);
value = uiprivTableModelCellValue(t->model, ht.iItem, modelColumn);
checked = uiTableValueInt(value);
uiFreeTableValue(value);
value = uiNewTableValueInt(!checked);
(*(t->model->mh->SetCellValue))(t->model->mh, t->model, ht.iItem, modelColumn, value);
uiprivTableModelSetCellValue(t->model, ht.iItem, modelColumn, value);
uiFreeTableValue(value);
} else
(*(t->model->mh->SetCellValue))(t->model->mh, t->model, ht.iItem, modelColumn, NULL);
uiprivTableModelSetCellValue(t->model, ht.iItem, modelColumn, NULL);
// always refresh the value in case the model rejected it
if (SendMessageW(t->hwnd, LVM_UPDATE, (WPARAM) (ht.iItem), 0) == (LRESULT) (-1)) {
logLastError(L"LVM_UPDATE");