📄 listmodel.c
字号:
/*
** $Id: listmodel.c,v 1.6 2004/10/18 00:49:28 snig Exp $
**
** listmodel.c: List data model.
**
** Copyright (C) 2004 Feynman Software.
**
** Current maintainer: Zhong Shuyi (zhongsy@minigui.org).
**
** Create date: 2004/10/09
*/
/*
** 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 2 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, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "control.h"
#include "cliprect.h"
#include "internals.h"
#include "ctrlclass.h"
#ifdef _CTRL_SCROLLVIEW
#include "ctrlmisc.h"
#include "listmodel.h"
#include "scrolled.h"
/*
* mglist_get_sort_index : Get sort index of an item
*/
int mglist_get_sort_index (MgList *mglst, MgItem *newci, BOOL bAdd)
{
list_t *me;
MgItem *pci = NULL;
int i = 0;
mglist_for_each (me, mglst) {
pci = mglist_entry (me);
if (mglst->itemCmp ((HITEM)newci, (HITEM)pci) < 0) {
if (bAdd)
list_add_tail (&newci->list, &pci->list);
return i;
}
i++;
}
if (bAdd)
list_add_tail (&newci->list, &mglst->queue);
return i;
}
/*
* mgitem_add : add an item to the list
*/
int mglist_add_item (MgList *mglst, MgItem *ci, MgItem* preitem,
MgItem* nextitem, int nItem, int *idx)
{
int ret;
ci->flags = CTST_NORMAL;
if (mglst->iop.initItem) {
if (mglst->iop.initItem (mglst->hLst, (HITEM)ci) <0) {
return -1;
}
}
if (mglst->flags & CF_AUTOSORT && mglst->itemCmp) {
ret = mglist_get_sort_index (mglst, ci, TRUE);
}
else {
if (preitem) {
list_add (&ci->list, &preitem->list);
ret = -1;
}
else if (nextitem) {
list_add_tail (&ci->list, &nextitem->list);
ret = -1;
}
else {
ret = list_add_by_index (&ci->list, &mglst->queue, nItem);
}
}
mglst->nItemNr ++;
if (idx)
*idx = ( ret<0 ? mglst->nItemNr-1 : ret);
return 0;
}
int mglist_del_item (MgList *mglst, MgItem* pci)
{
if (mglst->iop.destroyItem) {
mglst->iop.destroyItem (mglst->hLst, (HITEM)pci);
}
list_del (&pci->list);
mglst->nItemNr --;
if (pci == mglst->pItemHilighted)
mglst->pItemHilighted = NULL;
if (pci->flags & CTST_SELECTED)
list_del (&pci->sel_list);
return 0;
}
int
mglist_move_item (MgList *mglst, MgItem* pci, MgItem* preitem)
{
list_del (&pci->list);
if (preitem)
list_add_tail(&pci->list, &preitem->list);
else
list_add_tail(&pci->list, &mglst->queue);
return 0;
}
int mglist_adjust_items_height (HWND hWnd, MgList *mglst, PSCRDATA pscrdata, int diff)
{
mglst->nTotalItemH += diff;
if (mglist_is_frozen(mglst))
return 0;
scrolled_set_cont_height (hWnd, pscrdata, mglst->nTotalItemH);
scrolled_refresh_content (pscrdata);
return 0;
}
/* ---------------------------------------------------------------------------- */
int mglist_init (MgList *mglst, HWND hWnd)
{
INIT_LIST_HEAD(&mglst->queue);
INIT_LIST_HEAD(&mglst->sel_queue);
mglst->nItemNr = 0;
mglst->pItemHilighted = NULL;
mglst->nTotalItemH = 0;
mglst->itemCmp = NULL;
mglst->hLst = hWnd;
mglst->flags = 0;
memset (&mglst->iop, 0, sizeof(mglst->iop));
return 0;
}
GET_ENTRY_BY_INDEX(mlGetItemByIndex, MgItem, list)
GET_ENTRY_INDEX(mlGetItemIndex, MgItem, list)
MgItem* mglist_getitem_byindex (MgList *mglst, int index)
{
return mlGetItemByIndex(&mglst->queue, index);
}
int mglist_get_item_index (MgList *mglst, MgItem *item)
{
return mlGetItemIndex(&mglst->queue, item);
}
MgItem* mglist_get_next_item (MgList *mglst, MgItem* hitem)
{
list_t *me = hitem ? hitem->list.next : mglst->queue.next;
return ( (me == &mglst->queue) ? 0 : mglist_entry(me) );
}
MgItem* mglist_get_prev_item (MgList *mglst, MgItem* hitem)
{
list_t *me = hitem ? hitem->list.prev : mglst->queue.prev;
return ( (me == &mglst->queue) ? 0 : mglist_entry(me) );
}
void mglist_hilight_item (MgList *mglst, MgItem* hitem)
{
if (hitem) {
MgItem* oldhitem;
oldhitem = mglst->pItemHilighted;
mglst->pItemHilighted = hitem;
mglist_select_item (mglst, hitem, TRUE);
mglist_refresh_item (mglst, (HITEM)oldhitem);
mglist_refresh_item (mglst, (HITEM)hitem);
}
}
DWORD mglist_get_item_adddata (HITEM hitem)
{
return hitem ? ((MgItem *)hitem)->addData : 0;
}
DWORD mglist_set_item_adddata (HITEM hitem, DWORD adddata)
{
DWORD old;
if (!hitem)
return 0;
old = ((MgItem *)hitem)->addData;
((MgItem *)hitem)->addData = adddata;
return old;
}
void mglist_freeze (HWND hWnd, MgList *mglst, BOOL lock)
{
if (lock) {
mglst->flags |= MGLIST_ST_FROZEN;
}
else {
PSCRDATA pscrdata = (PSCRDATA)GetWindowAdditionalData2(hWnd);
mglst->flags &= ~MGLIST_ST_FROZEN;
scrolled_set_cont_height (hWnd, pscrdata, mglst->nTotalItemH);
//FIXME
scrolled_refresh_content (pscrdata);
}
}
int mglstSortItems (MgList *mglst, void* pfn, int fn_type)
{
MgItem *pci, *pci2;
list_t *me, *me2;
MGITEM_CMP pcmp = NULL;
MGITEM_CMP_EX pcmp_ex = NULL;
int ret;
if (fn_type == MG_CMP_TYPE_NORMAL) {
if ( !(pcmp = (MGITEM_CMP)pfn) )
return -1;
}
else if (fn_type == MG_CMP_TYPE_EX) {
if ( !(pcmp_ex = (MGITEM_CMP_EX)pfn) )
return -1;
}
else
return -1;
mglist_for_each (me, mglst) {
pci = mglist_entry (me);
pci2 = NULL;
ret = 0;
mglist_for_each (me2, mglst) {
if (me == me2)
break;
pci2 = mglist_entry (me2);
if (pcmp)
ret = pcmp ((HITEM)pci, (HITEM)pci2);
else
ret = pcmp_ex (mglst, (HITEM)pci, (HITEM)pci2);
if (ret < 0)
break;
}
if (ret < 0) {
me = me->prev;
mglist_move_item (mglst, pci, pci2);
}
}
return 0;
}
int mglist_sort_items (MgList *mglst, void* pfn, int fn_type)
{
int ret;
mglist_freeze (mglst->hLst, mglst, TRUE);
ret = mglstSortItems (mglst, pfn, fn_type);
mglist_freeze (mglst->hLst, mglst, FALSE);
return ret;
}
void mglist_refresh_item (MgList *mglst, HITEM hitem)
{
RECT rcItem;
if (!hitem || mglst->flags & MGLIST_ST_FROZEN)
return;
mglst->iop.getRect (mglst->hLst, hitem, &rcItem, TRUE);
InvalidateRect (mglst->hLst, &rcItem, TRUE);
}
void mglist_redraw_item (MgList *mglst, HITEM hivi)
{
RECT rcItem;
HDC hdc = GetClientDC (mglst->hLst);
if (!hivi)
return;
mglst->iop.getRect (mglst->hLst, hivi, &rcItem, TRUE);
mglst->iop.drawItem (mglst->hLst, hivi, hdc, &rcItem);
ReleaseDC (hdc);
}
BOOL mglist_make_item_visible (MgList *mglst, PSCRDATA pscrdata, HITEM hitem)
{
int pos_x, pos_y;
RECT rcItem;
int ret;
if (!hitem) return FALSE;
ret = mglst->iop.getRect (mglst->hLst, hitem, &rcItem, FALSE);
if (ret < 0)
return FALSE;
else if (ret == 1) { /* make y pos visible */
pos_x = -1;
}
else { /* x/y all visible */
pos_x = (rcItem.left >= pscrdata->nContX) ? rcItem.right : rcItem.left;
}
pos_y = (rcItem.top >= pscrdata->nContY) ? rcItem.bottom : rcItem.top;
return scrolled_make_pos_visible (mglst->hLst, pscrdata, pos_x, pos_y);
}
/* -------------------------------------------------------------------------- */
SVITEM_DRAWFUNC mglist_set_itemdraw (MgList *mglst, SVITEM_DRAWFUNC draw_func)
{
SVITEM_DRAWFUNC oldfn;
oldfn = mglst->iop.drawItem;
mglst->iop.drawItem = draw_func;
//FIXME, repaint ?
return oldfn;
}
void mglist_set_itemops (MgList *mglst, PMGITEMOPS iop)
{
mglst->iop = *iop;
}
int DefaultItemViewProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam,
PSCRDATA pscrdata, MgList *mglst)
{
switch (message) {
case MSG_RBUTTONDOWN:
case MSG_LBUTTONDOWN:
{
int mouseY = HISWORD (lParam);
int mouseX = LOSWORD (lParam);
int nItem;
RECT rcVis;
MgItem *hitem;
if ( !mglst->iop.isInItem )
break;
scrolled_get_visible_rect (pscrdata, &rcVis);
/* not in the visible area */
if (!PtInRect (&rcVis, mouseX, mouseY))
break;
scrolled_window_to_content (pscrdata, &mouseX, &mouseY);
if ( (nItem = mglst->iop.isInItem(mglst, mouseX, mouseY, &hitem, NULL)) >= 0 ) {
NotifyParentEx (hWnd, GetDlgCtrlID(hWnd), SVN_CLICKED, (DWORD)hitem);
if (!mglist_is_item_hilight(mglst, hitem)) {
mglist_hilight_item (mglst, hitem);
mglist_make_item_visible (mglst, pscrdata, (HITEM)hitem);
NotifyParentEx (hWnd, GetDlgCtrlID(hWnd), SVN_SELCHANGED, (DWORD)hitem);
}
/* FIXME: should we auto-select the item? */
//mglist_select_item (mglst, hitem, TRUE);
}
break;
}
case MSG_FREEZECTRL:
mglist_freeze (hWnd, mglst, wParam);
return 0;
case SVM_SETITEMDRAW:
return (int)mglist_set_itemdraw (mglst, (SVITEM_DRAWFUNC)lParam);
case SVM_SETITEMINIT:
{
SVITEM_INITFUNC old_pfn;
old_pfn = mglst->iop.initItem;
mglst->iop.initItem = (SVITEM_INITFUNC)lParam;
return (int)old_pfn;
}
case SVM_SETITEMDESTROY:
{
SVITEM_DESTROYFUNC old_pfn;
old_pfn = mglst->iop.destroyItem;
mglst->iop.destroyItem = (SVITEM_DESTROYFUNC)lParam;
return (int)old_pfn;
}
case SVM_GETITEMADDDATA:
{
if (lParam)
return mglist_get_item_adddata(lParam);
else {
HITEM hitem = (HITEM)mglist_getitem_byindex(mglst, wParam);
return mglist_get_item_adddata(hitem);
}
}
case SVM_SETITEMADDDATA:
{
HITEM hitem = (HITEM)mglist_getitem_byindex(mglst, wParam);
mglist_set_item_adddata (hitem, lParam);
return 0;
}
case SVM_REFRESHITEM:
{
if (lParam)
mglist_refresh_item (mglst, (HITEM)lParam);
else {
HITEM hitem = (HITEM) mglist_getitem_byindex(mglst, wParam);
mglist_refresh_item (mglst, hitem);
}
return 0;
}
case SVM_SETITEMOPS:
*(SVITEMOPS*)&mglst->iop = *(SVITEMOPS*)lParam;
//mglist_set_itemops ((MgList *)&psvdata->svlist, (SVITEMOPS*)lParam);
return 0;
case SVM_GETCURSEL:
return mglist_get_item_index(mglst, mglist_get_hilighted_item(mglst));
case SVM_SETCURSEL:
{
HITEM hitem = (HITEM)mglist_getitem_byindex(mglst, wParam);
if (hitem) {
//FIXME, should we automatically refresh hilighted item ?
//mglist_set_hilighted_item (mglst, (MgItem *)hitem);
mglist_hilight_item (mglst, (MgItem *)hitem);
// make this item visible
if (lParam)
mglist_make_item_visible (mglst, pscrdata, hitem);
}
return 0;
}
case SVM_SHOWITEM:
{
if (lParam)
mglist_make_item_visible (mglst, pscrdata, (HITEM)lParam);
else {
HITEM hitem = (HITEM)mglist_getitem_byindex(mglst, wParam);
mglist_make_item_visible (mglst, pscrdata, hitem);
}
return 0;
}
case SVM_SELECTITEM:
{
HITEM hitem = (HITEM)mglist_getitem_byindex(mglst, wParam);
if (hitem) {
mglist_select_item (mglst, (MgItem *)hitem, lParam);
}
return 0;
}
case SVM_CHOOSEITEM:
{
HITEM hitem;
if (lParam)
hitem = (HITEM)lParam;
else
hitem = (HITEM)mglist_getitem_byindex(mglst, wParam);
mglist_select_item (mglst, (MgItem *)hitem, TRUE);
mglist_make_item_visible (mglst, pscrdata, hitem);
return 0;
}
case SVM_SETITEMCMP:
{
SVITEM_CMP oldcmp = mglst->itemCmp;
mglst->itemCmp = (SVITEM_CMP)lParam;
return (int)oldcmp;
}
case SVM_SORTITEMS:
{
SVITEM_CMP pfn = (SVITEM_CMP)lParam;
if (mglist_sort_items (mglst, (void*)pfn, MG_CMP_TYPE_NORMAL) == 0) {
//FIXME, need ?
InvalidateRect (hWnd, NULL, TRUE);
}
return 0;
}
case SVM_GETITEMCOUNT:
return mglist_get_item_count(mglst);
}/* end switch */
return DefaultScrolledProc (hWnd, message, wParam, lParam);
}
/* -------------------------------------------------------------------------- */
#endif /* _CTRL_SCROLLVIEW */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -