#include "uipriv_windows.hpp"
#include "table.hpp"
static HRESULT resizeEdit(uiTable *t, WCHAR *wstr, int iItem, int iSubItem)
{
uiprivTableMetrics *m;
RECT r;
HDC dc;
HFONT prevFont;
TEXTMETRICW tm;
SIZE textSize;
RECT editRect, clientRect;
HRESULT hr;
hr = uiprivTableGetMetrics(t, iItem, iSubItem, &m);
if (hr != S_OK)
return hr;
r = m->realTextRect;
uiprivFree(m);
dc = GetDC(t->hwnd); prevFont = (HFONT) SelectObject(dc, hMessageFont);
GetTextMetricsW(dc, &tm);
GetTextExtentPoint32W(dc, wstr, wcslen(wstr), &textSize);
SelectObject(dc, prevFont);
ReleaseDC(t->hwnd, dc);
SendMessageW(t->edit, EM_GETRECT, 0, (LPARAM) (&editRect));
r.left -= editRect.left;
r.top += ((r.bottom - r.top) - tm.tmHeight) / 2;
r.top -= editRect.top;
r.right = r.left + textSize.cx;
r.right += 4 * GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CYEDGE);
r.bottom = r.top + editRect.top + tm.tmHeight + editRect.top;
GetClientRect(t->hwnd, &clientRect);
IntersectRect(&r, &r, &clientRect);
SetWindowPos(t->edit, NULL,
r.left, r.top,
r.right - r.left, r.bottom - r.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
return S_OK;
}
static LRESULT CALLBACK editSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIDSubclass, DWORD_PTR dwRefData)
{
uiTable *t = (uiTable *) dwRefData;
HRESULT hr;
switch (uMsg) {
case WM_KEYDOWN:
switch (wParam) {
case VK_RETURN:
hr = uiprivTableFinishEditingText(t);
if (hr != S_OK) {
}
return 0; case VK_ESCAPE:
hr = uiprivTableAbortEditingText(t);
if (hr != S_OK) {
}
return 0;
}
break;
case WM_GETDLGCODE:
return DLGC_HASSETSEL | DLGC_WANTALLKEYS;
case WM_NCDESTROY:
if (RemoveWindowSubclass(hwnd, editSubProc, uIDSubclass) == FALSE)
logLastError(L"RemoveWindowSubclass()");
}
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
static HRESULT openEditControl(uiTable *t, int iItem, int iSubItem, uiprivTableColumnParams *p)
{
uiTableValue *value;
WCHAR *wstr;
HRESULT hr;
hr = uiprivTableFinishEditingText(t);
if (hr != S_OK)
return hr;
value = uiprivTableModelCellValue(t->model, iItem, p->textModelColumn);
wstr = toUTF16(uiTableValueString(value));
uiFreeTableValue(value);
t->edit = CreateWindowExW(0,
L"EDIT", wstr,
WS_CHILD | WS_CLIPSIBLINGS | WS_BORDER | ES_AUTOHSCROLL,
0, 0, 16384, 16384,
t->hwnd, (HMENU) 1, hInstance, NULL);
if (t->edit == NULL) {
logLastError(L"CreateWindowExW()");
uiprivFree(wstr);
return E_FAIL;
}
SendMessageW(t->edit, WM_SETFONT, (WPARAM) hMessageFont, (LPARAM) TRUE);
SetWindowSubclass(t->edit, editSubProc, 0, (DWORD_PTR) t);
hr = resizeEdit(t, wstr, iItem, iSubItem);
if (hr != S_OK)
return hr;
SetFocus(t->edit);
ShowWindow(t->edit, SW_SHOW);
SendMessageW(t->edit, EM_SETSEL, 0, (LPARAM) (-1));
uiprivFree(wstr);
t->editedItem = iItem;
t->editedSubitem = iSubItem;
return S_OK;
}
HRESULT uiprivTableResizeWhileEditing(uiTable *t)
{
WCHAR *text;
HRESULT hr;
if (t->edit == NULL)
return S_OK;
text = windowText(t->edit);
hr = resizeEdit(t, text, t->editedItem, t->editedSubitem);
uiprivFree(text);
return hr;
}
HRESULT uiprivTableFinishEditingText(uiTable *t)
{
uiprivTableColumnParams *p;
uiTableValue *value;
char *text;
if (t->edit == NULL)
return S_OK;
text = uiWindowsWindowText(t->edit);
value = uiNewTableValueString(text);
uiFreeText(text);
p = (*(t->columns))[t->editedSubitem];
uiprivTableModelSetCellValue(t->model, t->editedItem, p->textModelColumn, value);
uiFreeTableValue(value);
return uiprivTableAbortEditingText(t);
}
HRESULT uiprivTableAbortEditingText(uiTable *t)
{
HWND edit;
if (t->edit == NULL)
return S_OK;
edit = t->edit;
t->edit = NULL;
if (DestroyWindow(edit) == 0) {
logLastError(L"DestroyWindow()");
return E_FAIL;
}
return S_OK;
}
HRESULT uiprivTableHandleNM_CLICK(uiTable *t, NMITEMACTIVATE *nm, LRESULT *lResult)
{
LVHITTESTINFO ht;
uiprivTableColumnParams *p;
int modelColumn, editableColumn;
bool text, checkbox;
uiTableValue *value;
int checked;
HRESULT hr;
ZeroMemory(&ht, sizeof (LVHITTESTINFO));
ht.pt = nm->ptAction;
if (SendMessageW(t->hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM) (&ht)) == (LRESULT) (-1))
goto done;
modelColumn = -1;
editableColumn = -1;
text = false;
checkbox = false;
p = (*(t->columns))[ht.iSubItem];
if (p->textModelColumn != -1) {
modelColumn = p->textModelColumn;
editableColumn = p->textEditableModelColumn;
text = true;
} else if (p->checkboxModelColumn != -1) {
modelColumn = p->checkboxModelColumn;
editableColumn = p->checkboxEditableModelColumn;
checkbox = true;
} else if (p->buttonModelColumn != -1) {
modelColumn = p->buttonModelColumn;
editableColumn = p->buttonClickableModelColumn;
}
if (modelColumn == -1)
goto done;
if (text && t->inDoubleClickTimer)
goto done;
if (!uiprivTableModelCellEditable(t->model, ht.iItem, editableColumn))
goto done;
if (text) {
hr = openEditControl(t, ht.iItem, ht.iSubItem, p);
if (hr != S_OK)
return hr;
} else if (checkbox) {
if ((ht.flags & LVHT_ONITEMICON) == 0)
goto done;
value = uiprivTableModelCellValue(t->model, ht.iItem, modelColumn);
checked = uiTableValueInt(value);
uiFreeTableValue(value);
value = uiNewTableValueInt(!checked);
uiprivTableModelSetCellValue(t->model, ht.iItem, modelColumn, value);
uiFreeTableValue(value);
} else
uiprivTableModelSetCellValue(t->model, ht.iItem, modelColumn, NULL);
done:
*lResult = 0;
return S_OK;
}