diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/NewStory/src/history_array.cpp | 6 | ||||
-rw-r--r-- | plugins/NewStory/src/history_array.h | 5 | ||||
-rw-r--r-- | plugins/NewStory/src/history_control.cpp | 177 | ||||
-rw-r--r-- | plugins/NewStory/src/history_control.h | 46 |
4 files changed, 112 insertions, 122 deletions
diff --git a/plugins/NewStory/src/history_array.cpp b/plugins/NewStory/src/history_array.cpp index 5767b91330..0a68338f2a 100644 --- a/plugins/NewStory/src/history_array.cpp +++ b/plugins/NewStory/src/history_array.cpp @@ -46,6 +46,12 @@ bool Filter::check(ItemData *item) ///////////////////////////////////////////////////////////////////////////////////////// // Event +ItemData::ItemData() +{ + memset(this, 0, sizeof(*this)); + savedHeight = -1; +} + ItemData::~ItemData() { mir_free(wtext); diff --git a/plugins/NewStory/src/history_array.h b/plugins/NewStory/src/history_array.h index 0de2c23f68..4e353aadf6 100644 --- a/plugins/NewStory/src/history_array.h +++ b/plugins/NewStory/src/history_array.h @@ -10,7 +10,8 @@ struct ItemData bool m_bSelected; bool m_bLoaded; bool m_bOfflineFile, m_bOfflineDownloaded; - int savedTop; + + int savedTop, savedHeight; DB::EventInfo dbe; wchar_t *wtext; @@ -19,7 +20,7 @@ struct ItemData HANDLE data; ItemData *pPrev; - ItemData() { memset(this, 0, sizeof(*this)); } + ItemData(); ~ItemData(); void checkCreate(HWND hwnd); diff --git a/plugins/NewStory/src/history_control.cpp b/plugins/NewStory/src/history_control.cpp index 7f25cfbc94..52bdb600c8 100644 --- a/plugins/NewStory/src/history_control.cpp +++ b/plugins/NewStory/src/history_control.cpp @@ -27,6 +27,16 @@ void NewstoryListData::OnContextMenu(int index, POINT pt) Menu_DestroyNestedMenu(hMenu); } +void NewstoryListData::OnResize(int newWidth) +{ + if (newWidth == cachedWindowWidth) + return; + + int count = items.getCount(); + for (int i = 0; i < count; i++) + items[i]->savedHeight = -1; +} + void NewstoryListData::OnTimer(CTimer *pTimer) { pTimer->Stop(); @@ -44,25 +54,25 @@ void NewstoryListData::BeginEditItem(int index, bool bReadOnly) if (scrollTopItem > index) return; + ItemData *item = items[index]; + if (item->dbe.eventType != EVENTTYPE_MESSAGE) + return; + RECT rc; GetClientRect(hwnd, &rc); int height = rc.bottom - rc.top; int top = scrollTopPixel; int idx = scrollTopItem; - int itemHeight = LayoutItem(idx); + int itemHeight = GetItemHeight(idx); while (top < height) { if (idx == index) break; top += itemHeight; idx++; - itemHeight = LayoutItem(idx); + itemHeight = GetItemHeight(idx); } - ItemData *item = items[index]; - if (item->dbe.eventType != EVENTTYPE_MESSAGE) - return; - int fontid, colorid; item->getFontColor(fontid, colorid); @@ -130,6 +140,7 @@ void NewstoryListData::EndEditItem(bool bAccept) } MTextDestroy(pItem->data); pItem->data = 0; + pItem->savedHeight = -1; pItem->checkCreate(hwnd); } } @@ -150,19 +161,17 @@ void NewstoryListData::EnsureVisible(int item) int height = rc.bottom - rc.top; int top = scrollTopPixel; int idx = scrollTopItem; - int itemHeight = LayoutItem(idx); + int itemHeight = GetItemHeight(idx); bool found = false; while (top < height) { if (idx == item) { - itemHeight = LayoutItem(idx); - if (top + itemHeight > height) - ScrollListBy(0, height - top - itemHeight); + itemHeight = GetItemHeight(idx); found = true; break; } top += itemHeight; idx++; - itemHeight = LayoutItem(idx); + itemHeight = GetItemHeight(idx); } if (!found) { scrollTopItem = item; @@ -184,7 +193,7 @@ void NewstoryListData::FixScrollPosition() int maxTopItem = 0; int tmp = 0; for (maxTopItem = items.getCount(); (maxTopItem > 0) && (tmp < windowHeight); maxTopItem--) - tmp += LayoutItem(maxTopItem - 1); + tmp += GetItemHeight(maxTopItem - 1); cachedMaxTopItem = maxTopItem; cachedWindowHeight = windowHeight; cachedMaxTopPixel = (windowHeight < tmp) ? windowHeight - tmp : 0; @@ -215,45 +224,45 @@ int NewstoryListData::GetItemFromPixel(int yPos) int height = rc.bottom - rc.top; int current = scrollTopItem; int top = scrollTopPixel; - int bottom = top + LayoutItem(current); + int bottom = top + GetItemHeight(current); while (top <= height) { if (yPos >= top && yPos <= bottom) return current; if (++current >= count) break; top = bottom; - bottom = top + LayoutItem(current); + bottom = top + GetItemHeight(current); } return -1; } -int NewstoryListData::LayoutItem(int index) +int NewstoryListData::GetItemHeight(int index) { - HDC hdc = GetDC(hwnd); - RECT rc; GetClientRect(hwnd, &rc); - int width = rc.right - rc.left; - ItemData *item = items[index]; - if (!item) { - DeleteDC(hdc); + if (!item) return 0; - } + + if (item->savedHeight >= 0) + return item->savedHeight; int fontid, colorid; item->getFontColor(fontid, colorid); item->checkCreate(hwnd); - HFONT hfnt = (HFONT)SelectObject(hdc, g_fontTable[fontid].hfnt); + HDC hdc = GetDC(hwnd); + HFONT hOldFont = (HFONT)SelectObject(hdc, g_fontTable[fontid].hfnt); + + RECT rc; GetClientRect(hwnd, &rc); + int width = rc.right - rc.left; SIZE sz; sz.cx = width - 6; MTextMeasure(hdc, &sz, (HANDLE)item->data); - SelectObject(hdc, hfnt); - + SelectObject(hdc, hOldFont); ReleaseDC(hwnd, hdc); - return sz.cy + 5; + return item->savedHeight = sz.cy + 5; } int NewstoryListData::PaintItem(HDC hdc, int index, int top, int width) @@ -316,15 +325,13 @@ int NewstoryListData::PaintItem(HDC hdc, int index, int top, int width) void NewstoryListData::RecalcScrollBar() { - SCROLLINFO si = { 0 }; - RECT clRect; - GetClientRect(hwnd, &clRect); + SCROLLINFO si = {}; si.cbSize = sizeof(si); si.fMask = SIF_ALL; si.nMin = 0; - si.nMax = items.getCount() * AVERAGE_ITEM_HEIGHT; - si.nPage = clRect.bottom; - si.nPos = scrollTopItem * AVERAGE_ITEM_HEIGHT; + si.nMax = items.getCount(); + si.nPage = si.nMax / 10; + si.nPos = caret; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); } @@ -334,39 +341,6 @@ void NewstoryListData::ScheduleDraw() redrawTimer.Start(100); } -void NewstoryListData::ScrollListBy(int scrollItems, int scrollPixels) -{ - if (scrollItems) { - scrollTopItem += scrollItems; - scrollTopPixel = 0; - } - else if (scrollPixels) { - scrollTopPixel += scrollPixels; - if (scrollTopPixel > 0) { - while ((scrollTopPixel > 0) && scrollTopItem) { - scrollTopItem--; - int itemHeight = LayoutItem(scrollTopItem); - scrollTopPixel -= itemHeight; - } - - if (scrollTopPixel > 0) { - scrollTopPixel = 0; - } - } - else if (scrollTopPixel < 0) { - int maxItem = items.getCount(); - int itemHeight = LayoutItem(scrollTopItem); - while ((-scrollTopPixel > itemHeight) && (scrollTopItem < maxItem)) { - scrollTopPixel += itemHeight; - scrollTopItem++; - itemHeight = LayoutItem(scrollTopItem); - } - } - } - - FixScrollPosition(); -} - void NewstoryListData::SetPos(int pos) { caret = pos; @@ -444,10 +418,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM case NSM_CLEAR: data->items.clear(); - - data->redrawTimer.Stop(); - data->redrawTimer.Start(100); - InvalidateRect(hwnd, nullptr, FALSE); + data->ScheduleDraw(); break; case NSM_GETARRAY: @@ -640,6 +611,7 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM break; case WM_SIZE: + data->OnResize(LOWORD(lParam)); InvalidateRect(hwnd, 0, FALSE); break; @@ -746,38 +718,27 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM switch (wParam) { case VK_UP: - if (data->caret > 0) - data->SetPos(data->caret - 1); + data->LineUp(); break; case VK_DOWN: - if (data->caret < data->items.getCount()-1) - data->SetPos(data->caret + 1); + data->LineDown(); break; case VK_PRIOR: - if (!isCtrl && data->caret > 10) - data->SetPos(data->caret - 10); - else - data->SetPos(0); + data->PageUp(); break; case VK_NEXT: - if (int count = data->items.getCount()) { - if (!isCtrl && data->caret + 10 < count-1) - data->SetPos(data->caret + 10); - else - data->SetPos(count - 1); - } + data->PageDown(); break; case VK_HOME: - data->SetPos(0); + data->ScrollTop(); break; case VK_END: - if (int count = data->items.getCount()) - data->SetPos(count - 1); + data->ScrollBottom(); break; case VK_F2: @@ -874,18 +835,10 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM break; case WM_MOUSEWHEEL: - { - int s_scrollTopItem = data->scrollTopItem; - int s_scrollTopPixel = data->scrollTopPixel; - - UINT scrollLines; - if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, FALSE)) - scrollLines = 3; - data->ScrollListBy(0, (short)HIWORD(wParam) * 10 * (signed)scrollLines / WHEEL_DELTA); - - if (s_scrollTopItem != data->scrollTopItem || s_scrollTopPixel != data->scrollTopPixel) - InvalidateRect(hwnd, 0, FALSE); - } + if ((int)HIWORD(wParam) < 0) + data->LineUp(); + else + data->LineDown(); return TRUE; case WM_VSCROLL: @@ -895,24 +848,22 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM switch (LOWORD(wParam)) { case SB_LINEUP: - data->ScrollListBy(0, -10); + data->LineUp(); break; case SB_LINEDOWN: - data->ScrollListBy(0, 10); + data->LineDown(); break; case SB_PAGEUP: - data->ScrollListBy(-10, 0); + data->PageUp(); break; case SB_PAGEDOWN: - data->ScrollListBy(10, 0); + data->PageDown(); break; case SB_BOTTOM: - data->scrollTopItem = data->items.getCount() - 1; - data->scrollTopPixel = 0; + data->ScrollBottom(); break; case SB_TOP: - data->scrollTopItem = 0; - data->scrollTopPixel = 0; + data->ScrollTop(); break; case SB_THUMBTRACK: { @@ -920,18 +871,8 @@ LRESULT CALLBACK NewstoryListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM si.cbSize = sizeof(si); si.fMask = SIF_TRACKPOS | SIF_RANGE; GetScrollInfo(hwnd, SB_VERT, &si); - int pos = si.nTrackPos; - - if (pos == si.nMax) { - data->scrollTopItem = data->items.getCount(); - data->scrollTopPixel = -1000; - } - else { - data->scrollTopItem = pos / AVERAGE_ITEM_HEIGHT; - int itemHeight = data->LayoutItem(data->scrollTopItem); - data->scrollTopPixel = -pos % AVERAGE_ITEM_HEIGHT * itemHeight / AVERAGE_ITEM_HEIGHT; - } - data->FixScrollPosition(); + data->SetPos(data->items.getCount() * si.nTrackPos / si.nMax); + //data->FixScrollPosition(); } break; diff --git a/plugins/NewStory/src/history_control.h b/plugins/NewStory/src/history_control.h index 9c63d44df2..3b84558539 100644 --- a/plugins/NewStory/src/history_control.h +++ b/plugins/NewStory/src/history_control.h @@ -102,6 +102,7 @@ struct NewstoryListData : public MZeroedObject int cachedWindowHeight; int cachedMaxTopItem; // the largest ID of top item to avoid empty space int cachedMaxTopPixel; + int cachedWindowWidth = -1; RECT rcLastPaint; @@ -114,6 +115,7 @@ struct NewstoryListData : public MZeroedObject CSrmmBaseDialog *pMsgDlg = nullptr; void OnContextMenu(int index, POINT pt); + void OnResize(int newWidth); void OnTimer(CTimer *pTimer); void BeginEditItem(int index, bool bReadOnly); void DeleteItems(void); @@ -121,12 +123,52 @@ struct NewstoryListData : public MZeroedObject void EnsureVisible(int item); void FixScrollPosition(); int GetItemFromPixel(int yPos); - int LayoutItem(int index); + int GetItemHeight(int index); int PaintItem(HDC hdc, int index, int top, int width); void RecalcScrollBar(); void ScheduleDraw(); - void ScrollListBy(int scrollItems, int scrollPixels); void SetPos(int pos); + + void LineUp() + { + if (caret > 0) + SetPos(caret - 1); + } + + void LineDown() + { + if (caret < items.getCount() - 1) + SetPos(caret + 1); + } + + void PageUp() + { + if (caret > 10) + SetPos(caret - 10); + else + SetPos(0); + } + + void PageDown() + { + if (int count = items.getCount()) { + if (caret + 10 < count - 1) + SetPos(caret + 10); + else + SetPos(count - 1); + } + } + + void ScrollTop() + { + SetPos(0); + } + + void ScrollBottom() + { + if (int count = items.getCount()) + SetPos(count - 1); + } }; void InitNewstoryControl(); |