-
Notifications
You must be signed in to change notification settings - Fork 616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add minimal uiTable implementation for windows #361
Conversation
msys2 build is fixed on master branch - so maybe we need to merge |
Yes, I'll merge those branches shortly. |
Done. |
struct uiImage { | ||
double width; | ||
double height; | ||
// HIMAGELIST images; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a review comment, just a bit of information: I don't think we'll be able to use HIMAGELIST here, since that deals with a set of visually distinct images that have the same pixel sizes, while uiImage deals with a set of visually identical images that has different pixel sizes but the same physical size (for DPI independence). Don't worry about changing anything; I'll work on it later if you don't already have another PR with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I agree. Wasn't planning to go anywhere further with HIMAGELIST, Just stubbing out enough to get the tables compiling. and threw in the comment while I was in listview mode. I didn't spot the multi-size vs different-images distinction.
windows/table.cpp
Outdated
@@ -0,0 +1,277 @@ | |||
#include "uipriv_windows.hpp" | |||
|
|||
#include <vector> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This include is already in winapi.hpp, so it's not needed.
Huh, does github still not let you see merge conflicts? |
I merged the Windows fixes into the table branch now; you may need to pull for that to be reflected. |
I rebased my changes to try and keep the history clean. This is nudging against the outer limits of my git-fu, so fingers crossed :- ) |
Seems to have worked. Will review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly fine with the functionality this provides; most of these comments are consistency-related. Thanks again!
windows/table.cpp
Outdated
item.iItem = newIndex; | ||
item.iSubItem = 0; //? | ||
for (auto t : m->tables) { | ||
ListView_InsertItem( t->hwnd, &item ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consistency note: don't use the commctrl.h wrappers; use SendMessageW()
explicitly.
if (SendMesageW(t->hwnd, LVM_INSERTITEM, 0, (LPARAM) (&item)) == (LRESULT) (-1))
logLastError(L"error calling LVM_INSERTITEM in uiTableModelRowInserted()");
(Note this also checks for errors; a thing I still need to rationalize properly.)
Likewise for consistency, no braces around single-line loop bodies
windows/table.cpp
Outdated
void uiTableModelRowDeleted(uiTableModel *m, int oldIndex) | ||
{ | ||
for (auto t : m->tables) { | ||
ListView_DeleteItem( t->hwnd, oldIndex ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise here.
if (SendMesageW(t->hwnd, LVM_DELETEITEM, (WPARAM) oldIndex, 0) == (LRESULT) (FALSE))
logLastError(L"error calling LVM_DELETEITEM in uiTableModelRowDeleted()");
windows/table.cpp
Outdated
void uiTableModelRowChanged(uiTableModel *m, int index) | ||
{ | ||
for (auto t : m->tables) { | ||
ListView_Update( t->hwnd, index ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise here.
if (SendMesageW(t->hwnd, LVM_UPDATE, (WPARAM) oldIndex, 0) == (LRESULT) (FALSE))
logLastError(L"error calling LVM_UPDATE in uiTableModelRowDeleted()");
windows/table.cpp
Outdated
} | ||
} | ||
|
||
LV_COLUMN lvc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consistency: declarations at the top
More important, though:
a) use LVCOLUMNW
— LV_COLUMN
is technically a deprecated name as of at least Vista if not earlier, and the W
is consistency to explicitly use Unicode
b) you should call ZeroMemory(&lvc, sizeof (LVCOLUMNW))
before setting any fields (partially consistency, partially correctness)
windows/table.cpp
Outdated
lvc.fmt = LVCFMT_LEFT; | ||
lvc.cx = 120; // TODO | ||
lvc.pszText = c->name; | ||
ListView_InsertColumn(c->t->hwnd, lvIndex, &lvc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (SendMessageW(c->t->hwnd, LVM_INSERTCOLUMN, lvIndex, (LPARAM) (&lvc)) == (LRESULT) (-1))
logLastError(L"error calling LVM_INSERTCOLUMN in uiTableColumnAppendTextPart()");
windows/table.cpp
Outdated
// Don't think that'll cut it when some cells have overlong data (eg | ||
// stupidly long URLs). So for now, just hardcode a minimum: | ||
|
||
x = 107; // in line with other controls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would name these constants somehow, for consistency
windows/table.cpp
Outdated
} | ||
break; | ||
} | ||
default: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for default: break;
windows/table.cpp
Outdated
switch (nm->code) { | ||
case LVN_GETDISPINFO: | ||
{ | ||
NMLVDISPINFO* di = (NMLVDISPINFO*)nm; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style consistency:
NMLVDISPINFO *di = (NMLVDISPINFO *) nm;
LVITEM *item = &(di->item);
Note that the rest of this function isn't consistent either, but we can worry about that later.
windows/table.cpp
Outdated
uiTableModelColumnType typ = (*mh->ColumnType)(mh,t->model,mcol); | ||
if (typ == uiTableModelColumnString) { | ||
void* data = (*(mh->CellValue))(mh, t->model, row, mcol); | ||
int n = MultiByteToWideChar(CP_UTF8, 0, (const char*)data, -1, item->pszText, item->cchTextMax); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be a problem. It should be using toUTF16()
, but I forget what the behavior is if you overwrite the pszText
pointer with your own... or when it's safe to free. Just mark this as a TODO; I'll probably resolve it a different way.
windows/table.cpp
Outdated
if (n>=item->cchTextMax) { | ||
item->pszText[item->cchTextMax-1] = L'\0'; | ||
} | ||
} else if (typ == uiTableModelColumnInt) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a note: this won't be used for strings, but will be for progressbars. I will need to explicitly document that... Mark that as a TODO for now, anyway; this code can stay for now.
Just a quick note to assure you I'm still here ;-) It's been a crazy-busy week or so, so I've not been able to spend any time on this. The feedback is great and all makes sense to me, and I'm aiming to apply it all over the next few days. |
Okay; good luck with everything else going on! |
This uses the win32 common controls listview to implement uiTable. There are limitations: - It supports only a single TextPart per column. - ImagePart, CheckboxPart and ProgessBarPart are not implemented. - There is no support for cell coloring. - Cell editing is not implemented. Some of these will be very hard to support using the standard common control listview, and probably require an entire custom listview.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly good to go; just a few minor stuff to fix up first. Thanks again!
I'll talk more about parts stuff on the main issue.
@@ -132,6 +132,8 @@ uiBox *makePage16(void) | |||
|
|||
uiTableSetRowBackgroundColorModelColumn(t, 3); | |||
|
|||
uiTableAppendTextColumn(t, "Numbers", 8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned in another comment, the integer column type is for progress-bar parts. not for text strings. I don't remember what happens with other platforms though, so keep this around and I'll remove it if it causes issues.
However, this does raise the question of whether to provide helpers for displaying numbers as text. That might be outside the scope of libui, but it's still an interesting question...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that the type of the cell used in the table display is independent from datatype of the column in the model. While most mappings between the data and display types are clearly pretty bonkers (eg colour => progress bar doesn't sound too useful), it doesn't seem unreasonable for the table to have a good stab at the sane ones (one?). Particularly the numeric => text mapping.
It's a pretty common case to want to display numeric data in a table, so forcing the client app to present it's numeric data as text when the model already has perfectly good support for numeric data seems like a recipe for confusion...
windows/table.cpp
Outdated
|
||
//static void uiTableMinimumSize(uiWindowsControl *c, int *width, int *height); | ||
|
||
struct uiTable; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this; ui_table.h
already does this.
windows/table.cpp
Outdated
@@ -0,0 +1,295 @@ | |||
#include "uipriv_windows.hpp" | |||
|
|||
//static void uiTableMinimumSize(uiWindowsControl *c, int *width, int *height); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this; ui_windows.h
already does this.
windows/table.cpp
Outdated
ZeroMemory(&item, sizeof (LVITEMW)); | ||
item.mask = 0; | ||
item.iItem = newIndex; | ||
item.iSubItem = 0; //? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0 appears to be correct here. yes, since a subitem index of 0 means the item itself, not any of its subitems. (The leftmost column is not considered as "subitem" because of how listview is basically an extended listbox.)
windows/table.cpp
Outdated
item.mask = 0; | ||
item.iItem = newIndex; | ||
item.iSubItem = 0; //? | ||
for (auto t : m->tables) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style consistency nit: no need for braces here since the body is one statement.
windows/table.cpp
Outdated
|
||
void uiTableModelRowDeleted(uiTableModel *m, int oldIndex) | ||
{ | ||
for (auto t : m->tables) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style consistency nit: no need for braces here since the body is one statement.
windows/table.cpp
Outdated
int lvIndex = 0; | ||
LVCOLUMNW lvc; | ||
|
||
if (c->modelColumn >=0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style consistency nits: space after >=
, no need for braces here since the body is one statement. I'll stop this second one for the rest of the review, but it still applies.
*width = x; | ||
*height = y; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style consistency nit applied to everything: use only a single blank line between functions. not two.
windows/table.cpp
Outdated
// Don't think that'll cut it when some cells have overlong data (eg | ||
// stupidly long URLs). So for now, just hardcode a minimum: | ||
#define tableMinWidth 107 /* in line with other controls */ | ||
#define tableMinHeight (14*3) /* header + 2 lines (roughly) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There might be a way to use LVM_GETHEADER
to get the necessary size of the header control, perhaps combined with HDM_LAYOUT
, but I'm not sure how this cooperates with listview controls. Mark this as a TODO for now.
windows/table.cpp
Outdated
SendMessageW(t->hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, | ||
(WPARAM) (LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP), | ||
(LPARAM) (LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP)); | ||
// TODO: try LVS_EX_AUTOSIZECOLUMNS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this above the SendMessage()
call.
OK, I think that addresses them all. Let me know if I missed any! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last comment.
windows/table.cpp
Outdated
@@ -130,7 +119,7 @@ void uiTableColumnAppendProgressBarPart(uiTableColumn *c, int modelColumn, int e | |||
|
|||
void uiTableColumnPartSetEditable(uiTableColumn *c, int part, int editable) | |||
{ | |||
// TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep this as a TODO for now, so that it shows up in my occasional grep TODO
s and thus isn't forgotten.
All right; thanks! I'll merge this into table now at last, though there are a few other minor changes and one last runthrough before I merge this into master. Thanks a lot again! |
(The first two commits are cherry-picked from the msys fixes - I needed them to build. The table changes are in a single commit)
This uses the win32 common controls listview to implement uiTable.
There are limitations:
Some of these will be very hard to support using the standard
common control listview, and probably require an entire custom
listview.