208 lines
4.8 KiB
C++
208 lines
4.8 KiB
C++
// 16 may 2016
|
|
#include "uipriv_windows.hpp"
|
|
|
|
struct colorDialog {
|
|
HWND hwnd;
|
|
|
|
HWND svChooser;
|
|
HWND hSlider;
|
|
HWND opacitySlider;
|
|
HWND editH;
|
|
HWND editS;
|
|
HWND editV;
|
|
HWND editRDouble, editRInt;
|
|
HWND editGDouble, editGInt;
|
|
HWND editBDouble, editBInt;
|
|
HWND editADouble, editAInt;
|
|
HWND editHex;
|
|
|
|
double r;
|
|
double g;
|
|
double b;
|
|
double a;
|
|
struct colorDialogRGBA *out;
|
|
};
|
|
|
|
static void endColorDialog(struct colorDialog *c, INT_PTR code)
|
|
{
|
|
if (EndDialog(c->hwnd, code) == 0)
|
|
logLastError(L"error ending color dialog");
|
|
uiFree(c);
|
|
}
|
|
|
|
static BOOL tryFinishDialog(struct colorDialog *c, WPARAM wParam)
|
|
{
|
|
// cancelling
|
|
if (LOWORD(wParam) != IDOK) {
|
|
endColorDialog(c, 1);
|
|
return TRUE;
|
|
}
|
|
|
|
// OK
|
|
c->out->r = c->r;
|
|
c->out->g = c->g;
|
|
c->out->b = c->b;
|
|
c->out->a = c->a;
|
|
endColorDialog(c, 2);
|
|
return TRUE;
|
|
}
|
|
|
|
// a few issues:
|
|
// - some controls are positioned wrong; see http://stackoverflow.com/questions/37263267/why-are-some-of-my-controls-positioned-slightly-off-in-a-dialog-template-in-a-re
|
|
// - labels are too low; need to adjust them by the font's internal leading
|
|
// fixupControlPositions() and the following helper routines fix that for us
|
|
|
|
static LONG offsetTo(HWND a, HWND b)
|
|
{
|
|
RECT ra, rb;
|
|
|
|
uiWindowsEnsureGetWindowRect(a, &ra);
|
|
uiWindowsEnsureGetWindowRect(b, &rb);
|
|
return rb.top - ra.bottom;
|
|
}
|
|
|
|
static void moveWindowsUp(struct colorDialog *c, LONG by, ...)
|
|
{
|
|
va_list ap;
|
|
HWND cur;
|
|
RECT r;
|
|
|
|
va_start(ap, by);
|
|
for (;;) {
|
|
cur = va_arg(ap, HWND);
|
|
if (cur == NULL)
|
|
break;
|
|
uiWindowsEnsureGetWindowRect(cur, &r);
|
|
mapWindowRect(NULL, c->hwnd, &r);
|
|
r.top -= by;
|
|
r.bottom -= by;
|
|
// TODO this isn't technically during a resize
|
|
uiWindowsEnsureMoveWindowDuringResize(cur,
|
|
r.left, r.top,
|
|
r.right - r.left, r.bottom - r.top);
|
|
}
|
|
va_end(ap);
|
|
}
|
|
|
|
static void fixupControlPositions(struct colorDialog *c)
|
|
{
|
|
HWND labelH;
|
|
HWND labelS;
|
|
HWND labelV;
|
|
HWND labelR;
|
|
HWND labelG;
|
|
HWND labelB;
|
|
HWND labelA;
|
|
HWND labelHex;
|
|
LONG offset;
|
|
uiWindowsSizing sizing;
|
|
|
|
labelH = getDlgItem(c->hwnd, rcHLabel);
|
|
labelS = getDlgItem(c->hwnd, rcSLabel);
|
|
labelV = getDlgItem(c->hwnd, rcVLabel);
|
|
labelR = getDlgItem(c->hwnd, rcRLabel);
|
|
labelG = getDlgItem(c->hwnd, rcGLabel);
|
|
labelB = getDlgItem(c->hwnd, rcBLabel);
|
|
labelA = getDlgItem(c->hwnd, rcALabel);
|
|
labelHex = getDlgItem(c->hwnd, rcHexLabel);
|
|
|
|
offset = offsetTo(c->editH, c->editS);
|
|
moveWindowsUp(c, offset,
|
|
labelS, c->editS,
|
|
labelG, c->editGDouble, c->editGInt,
|
|
NULL);
|
|
offset = offsetTo(c->editS, c->editV);
|
|
moveWindowsUp(c, offset,
|
|
labelV, c->editV,
|
|
labelB, c->editBDouble, c->editBInt,
|
|
NULL);
|
|
offset = offsetTo(c->editBDouble, c->editADouble);
|
|
moveWindowsUp(c, offset,
|
|
labelA, c->editADouble, c->editAInt,
|
|
NULL);
|
|
|
|
// TODO this uses the message font, not the dialog font
|
|
uiWindowsGetSizing(c->hwnd, &sizing);
|
|
offset = sizing.InternalLeading;
|
|
moveWindowsUp(c, offset,
|
|
labelH, labelS, labelV,
|
|
labelR, labelG, labelB, labelA,
|
|
labelHex,
|
|
NULL);
|
|
}
|
|
|
|
static struct colorDialog *beginColorDialog(HWND hwnd, LPARAM lParam)
|
|
{
|
|
struct colorDialog *c;
|
|
|
|
c = uiNew(struct colorDialog);
|
|
c->hwnd = hwnd;
|
|
c->out = (struct colorDialogRGBA *) lParam;
|
|
c->r = c->out->r; // load initial values now
|
|
c->g = c->out->g;
|
|
c->b = c->out->b;
|
|
c->a = c->out->a;
|
|
|
|
// TODO set up d2dscratches
|
|
|
|
c->editH = getDlgItem(c->hwnd, rcH);
|
|
c->editS = getDlgItem(c->hwnd, rcS);
|
|
c->editV = getDlgItem(c->hwnd, rcV);
|
|
c->editRDouble = getDlgItem(c->hwnd, rcRDouble);
|
|
c->editRInt = getDlgItem(c->hwnd, rcRInt);
|
|
c->editGDouble = getDlgItem(c->hwnd, rcGDouble);
|
|
c->editGInt = getDlgItem(c->hwnd, rcGInt);
|
|
c->editBDouble = getDlgItem(c->hwnd, rcBDouble);
|
|
c->editBInt = getDlgItem(c->hwnd, rcBInt);
|
|
c->editADouble = getDlgItem(c->hwnd, rcADouble);
|
|
c->editAInt = getDlgItem(c->hwnd, rcAInt);
|
|
c->editHex = getDlgItem(c->hwnd, rcHex);
|
|
|
|
fixupControlPositions(c);
|
|
|
|
return c;
|
|
}
|
|
|
|
static INT_PTR CALLBACK colorDialogDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
struct colorDialog *c;
|
|
|
|
c = (struct colorDialog *) GetWindowLongPtrW(hwnd, DWLP_USER);
|
|
if (c == NULL) {
|
|
if (uMsg == WM_INITDIALOG) {
|
|
c = beginColorDialog(hwnd, lParam);
|
|
SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR) c);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
switch (uMsg) {
|
|
case WM_COMMAND:
|
|
SetWindowLongPtrW(c->hwnd, DWLP_MSGRESULT, 0); // just in case
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
if (HIWORD(wParam) != BN_CLICKED)
|
|
return FALSE;
|
|
return tryFinishDialog(c, wParam);
|
|
}
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL showColorDialog(HWND parent, struct colorDialogRGBA *c)
|
|
{
|
|
switch (DialogBoxParamW(hInstance, MAKEINTRESOURCE(rcColorDialog), parent, colorDialogDlgProc, (LPARAM) c)) {
|
|
case 1: // cancel
|
|
return FALSE;
|
|
case 2: // ok
|
|
// make the compiler happy by putting the return after the switch
|
|
break;
|
|
default:
|
|
logLastError(L"error running color dialog");
|
|
}
|
|
return TRUE;
|
|
}
|