diff --git a/src/CandidateWindow.cpp b/src/CandidateWindow.cpp index 4a4149f..aacd319 100644 --- a/src/CandidateWindow.cpp +++ b/src/CandidateWindow.cpp @@ -41,7 +41,10 @@ CandidateWindow::CandidateWindow(TextService* service, EditSession* session): currentSel_(0), hasResult_(false), useCursor_(true), - selKeyWidth_(0) { + selKeyWidth_(0), + page_(0), + pageCount_(0), + pageTextSize_({0, 0}) { if(service->isImmersive()) { // windows 8 app mode margin_ = 10; @@ -234,6 +237,15 @@ void CandidateWindow::onPaint(WPARAM wp, LPARAM lp) { x += colSpacing_ + selKeyWidth_ + textWidth_; } } + + // paint the page indicator at the bottom right + if(pageCount_ > 1) { + wstring text = pageText(); + COLORREF oldColor = ::SetTextColor(hDC, GetSysColor(COLOR_GRAYTEXT)); + ::ExtTextOut(hDC, rc.right - margin_ - pageTextSize_.cx, rc.bottom - margin_ - pageTextSize_.cy, + 0, NULL, text.c_str(), static_cast(text.length()), NULL); + ::SetTextColor(hDC, oldColor); + } SelectObject(hDC, oldFont); EndPaint(hwnd_, &ps); } @@ -272,6 +284,11 @@ void CandidateWindow::recalculateSize() { if(itemHeight > itemHeight_) itemHeight_ = itemHeight; } + pageTextSize_ = {0, 0}; + if(pageCount_ > 1) { + wstring text = pageText(); + ::GetTextExtentPoint32W(hDC, text.c_str(), static_cast(text.length()), &pageTextSize_); + } ::SelectObject(hDC, oldFont); ::ReleaseDC(hwnd(), hDC); @@ -300,6 +317,13 @@ void CandidateWindow::recalculateSize() { ++rowCount; height = itemHeight_ * rowCount + rowSpacing_ * (rowCount - 1) + margin_ * 2; } + // reserve a line for the page indicator + if(pageCount_ > 1) { + height += rowSpacing_ + pageTextSize_.cy; + int pageWidth = pageTextSize_.cx + margin_ * 2; + if(pageWidth > width) + width = pageWidth; + } resize(width, height); } @@ -372,6 +396,20 @@ void CandidateWindow::setUseCursor(bool use) { ::InvalidateRect(hwnd_, NULL, TRUE); } +void CandidateWindow::setPageInfo(int page, int pageCount) { + if(page != page_ || pageCount != pageCount_) { + page_ = page; + pageCount_ = pageCount; + if(isVisible()) + ::InvalidateRect(hwnd_, NULL, TRUE); + } +} + +wstring CandidateWindow::pageText() const { + // Name the keys that turn pages, so the user knows how to reach the others. + return L"PgUp " + to_wstring(page_) + L"/" + to_wstring(pageCount_) + L" PgDn"; +} + void CandidateWindow::paintItem(HDC hDC, int i, int x, int y) { RECT textRect = {x, y, 0, y + itemHeight_}; wchar_t selKey[] = L"?. "; diff --git a/src/CandidateWindow.h b/src/CandidateWindow.h index 2ea3635..fc28adf 100644 --- a/src/CandidateWindow.h +++ b/src/CandidateWindow.h @@ -100,11 +100,18 @@ class CandidateWindow: void setUseCursor(bool use); + // Show "PgUp page/pageCount PgDn" under the items when pageCount > 1, so + // the user can tell that more candidates are on other pages and how to + // reach them. page is 1-based. + // Call recalculateSize() afterwards. + void setPageInfo(int page, int pageCount); + protected: LRESULT wndProc(UINT msg, WPARAM wp , LPARAM lp); void onPaint(WPARAM wp, LPARAM lp); void paintItem(HDC hDC, int i, int x, int y); void itemRect(int i, RECT& rect); + std::wstring pageText() const; protected: // COM object should not be deleted directly. calling Release() instead. ~CandidateWindow(void); @@ -123,6 +130,9 @@ class CandidateWindow: int currentSel_; bool hasResult_; bool useCursor_; + int page_; + int pageCount_; + SIZE pageTextSize_; }; }