/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#include "stdafx.h"
#include
#include
#include "autocomplete.h"
#include "autocompletehandler.h"
extern HINSTANCE hInst;
AutoCompleteInfo::AutoCompleteInfo(HWND hWnd, const string &widgetId, gdioutput &gdi) : hWnd(hWnd),
widgetId(widgetId), lock(false), gdi(gdi),
currentIx(0), handler(0), lastVisible(0), modifedAutoComplete(false) {
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)this);
}
AutoCompleteInfo::~AutoCompleteInfo() {
if (hWnd) {
SetWindowLongPtr(hWnd, GWLP_USERDATA, 0);
destoy();
}
}
LRESULT CALLBACK completeProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
HDC hDC;
void *ptr = (void *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
AutoCompleteInfo *aci = (AutoCompleteInfo *)ptr;
switch (message)
{
case WM_CREATE:
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
if (aci)
aci->paint(hDC);
//TextOut(hDC, 5, 5, L"BAE", 3);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONUP: {
int x = GET_X_LPARAM(lParam);
int y = GET_Y_LPARAM(lParam);
if (aci)
aci->click(x,y);
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void AutoCompleteInfo::registerAutoClass() {
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)completeProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInst;
wcex.hIcon = 0;// LoadIcon(hInstance, (LPCTSTR)IDI_MEOS);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = 0;
wcex.lpszClassName = L"AUTOCOMPLETE";
wcex.hIconSm = 0;// LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
RegisterClassEx(&wcex);
}
void AutoCompleteInfo::show() {
lock = true;
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(hWnd, SW_SHOW);
InvalidateRect(hWnd, nullptr, true);
UpdateWindow(hWnd);
lock = false;
}
void AutoCompleteInfo::paint(HDC hDC) {
RECT rc;
GetClientRect(hWnd, &rc);
SetDCBrushColor(hDC, RGB(247, 245, 250));
SelectObject(hDC, GetStockObject(DC_BRUSH));
Rectangle(hDC, -1, -1, rc.right+1, rc.bottom+1);
int h = int(gdi.getLineHeight()*1.2);
int rows = min((rc.bottom -10) / h, data.size());
TextInfo ti;
ti.format = 0;
ti.format = absolutePosition;
lastVisible = rows;
rendered.resize(rows);
for (int i = 0; i < rows; i++) {
ti.xp = 10;
ti.yp = 10 + i * h;
rendered[i].first = i;
auto &rend = rendered[i].second;
rend.top = ti.yp-5;
rend.bottom = ti.yp + h;
rend.left = 5;
rend.right = rc.right - 5;
if (i == currentIx) {
ti.color = colorBlack;
SetDCBrushColor(hDC, RGB(237, 235, 242));
SelectObject(hDC, GetStockObject(DC_PEN));
SetDCPenColor(hDC, RGB(165, 160, 180));
Rectangle(hDC, rend.left, rend.top+2, rend.right, rend.bottom-2);
}
else
ti.color = colorBlack;
gdi.RenderString(ti, data[i].display, hDC);
}
}
void AutoCompleteInfo::click(int x, int y) {
POINT pt = { x,y };
for (auto &r : rendered) {
if (PtInRect(&r.second, pt)) {
currentIx = r.first;
if (handler) {
handler->handleAutoComplete(gdi, *this);
return;
}
}
}
}
void AutoCompleteInfo::upDown(int direction) {
currentIx -= direction;
if (currentIx < 0)
currentIx = 0;
else if (currentIx >= lastVisible)
currentIx = lastVisible - 1;
modifedAutoComplete = true;
HDC hDC = GetDC(hWnd);
paint(hDC);
ReleaseDC(hWnd, hDC);
}
void AutoCompleteInfo::enter() {
if (handler && currentIx >= 0 && size_t(currentIx) < data.size()) {
handler->handleAutoComplete(gdi, *this);
return;
}
}
void AutoCompleteInfo::setData(vector &items) {
int newDataIx = -1;
if (modifedAutoComplete && size_t(currentIx) < data.size()) {
for (size_t k = 0; k < items.size(); k++) {
if (data[currentIx].id == items[k].id)
newDataIx = k;
}
}
if (newDataIx == -1 && !items.empty()) {
newDataIx = 0;
modifedAutoComplete = false;
}
data = items;
currentIx = newDataIx;
}