287 lines
7.6 KiB
C++
287 lines
7.6 KiB
C++
|
#include "precomp.h"
|
||
|
|
||
|
#include "itemlistwnd.h"
|
||
|
#include "../../common/metatags.h"
|
||
|
|
||
|
#include "../../studio/api.h"
|
||
|
|
||
|
#include "../skinclr.h"
|
||
|
#include "../../common/filename.h"
|
||
|
|
||
|
#include "../../common/dragitemi.h"
|
||
|
#include "../../common/contextmenu.h"
|
||
|
|
||
|
#define NIFTY_OUTLINE
|
||
|
|
||
|
static SkinColor current("wasabi.itemlist.outline.current");
|
||
|
static SkinColor selborder("wasabi.itemlist.selborder");
|
||
|
static SkinColor focus("wasabi.itemlist.outline.focus");
|
||
|
|
||
|
ItemListColumn_MetaTag::ItemListColumn_MetaTag(const char *newtag, int centered, const char *label)
|
||
|
: ItemListColumn() {
|
||
|
if (label == NULL) label = newtag;
|
||
|
setLabel(label);
|
||
|
tag = newtag;
|
||
|
center = centered;
|
||
|
datatype = api->metadb_getMetaDataType(tag);
|
||
|
}
|
||
|
|
||
|
ItemListColumn_Callback::ItemListColumn_Callback(ItemListWnd *_parent, LPARAM _lparam, const char *name)
|
||
|
: ItemListColumn(name)
|
||
|
{
|
||
|
parent = _parent;
|
||
|
lparam = _lparam;
|
||
|
}
|
||
|
|
||
|
void ItemListColumn_Callback::render(int pos, const char *playstring, Canvas &c, RECT &r) {
|
||
|
parent->userRender(pos, playstring, c, r, lparam);
|
||
|
}
|
||
|
|
||
|
void ItemListColumn_Callback::columnToText(int pos, const char *playstring, char *str, int maxlen) {
|
||
|
parent->userColumnToText(pos, playstring, lparam, str, maxlen);
|
||
|
}
|
||
|
|
||
|
void ItemListColumn_MetaTag::render(int pos, const char *playstring, Canvas &canvas, RECT &r) {
|
||
|
char buf[4096]="";
|
||
|
if (api->metadb_getMetaData(playstring, tag, buf, 4096) <= 1) return;
|
||
|
api->metadb_renderData(&canvas, r, buf, datatype, center);
|
||
|
}
|
||
|
|
||
|
void ItemListColumn_MetaTag::columnToText(int pos, const char *playstring, char *str, int maxlen) {
|
||
|
api->metadb_getMetaData(playstring, tag, str, maxlen);
|
||
|
}
|
||
|
|
||
|
const char *ItemListColumn_MetaTag::getTag() {
|
||
|
return tag;
|
||
|
}
|
||
|
|
||
|
void ItemListColumn_Numbered::render(int pos, const char *playstring, Canvas &c, RECT &r) {
|
||
|
StringPrintf buf("%d.", pos+1);
|
||
|
c.textOutEllipsed(r.left, r.top, r.right - r.left, r.bottom-r.top, buf);
|
||
|
}
|
||
|
|
||
|
void ItemListColumn_Numbered::columnToText(int pos, const char *playstring, char *str, int maxlen) {
|
||
|
StringPrintf buf("%d", pos+1);
|
||
|
STRNCPY(str, buf, maxlen);
|
||
|
}
|
||
|
|
||
|
ItemListWnd::ItemListWnd() {
|
||
|
keep = NULL;
|
||
|
item_invalidate_border++;
|
||
|
}
|
||
|
|
||
|
ItemListWnd::~ItemListWnd() {
|
||
|
api->syscb_deregisterCallback(static_cast<MetaCallbackI *>(this));
|
||
|
}
|
||
|
|
||
|
int ItemListWnd::onInit() {
|
||
|
|
||
|
ITEMLISTWND_PARENT::onInit();
|
||
|
|
||
|
api->syscb_registerCallback(static_cast<MetaCallbackI *>(this));
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int ItemListWnd::insertColumn(ItemListColumn *column, int width, int pos) {
|
||
|
column->setWidth(width);
|
||
|
return ITEMLISTWND_PARENT::insertColumn(column, pos);
|
||
|
}
|
||
|
|
||
|
int ItemListWnd::onBeginDrag(int iItem) {
|
||
|
|
||
|
if (!wantAutoDrag()) return ITEMLISTWND_PARENT::onBeginDrag(iItem);
|
||
|
|
||
|
// add all the entries
|
||
|
int n, i, c = 0;
|
||
|
n = getNumItems();
|
||
|
if (n == 0) return 0; // empty list
|
||
|
|
||
|
ASSERT(keep == NULL);
|
||
|
keep = new PtrList<FilenameNC>();
|
||
|
|
||
|
// count up the items
|
||
|
for (i = 0; i < n; i++) {
|
||
|
if (getItemSelected(i)) { // expose all the pointers we can
|
||
|
LPARAM lparam = getItemData(i);
|
||
|
if (!addMoreDragTypes(i)) {
|
||
|
FilenameNC *fn = keep->addItem(new FilenameNC(convertlParam(lparam)));
|
||
|
addDragItem(DD_FILENAME, static_cast<Filename*>(fn));
|
||
|
}
|
||
|
c++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (keep->getNumItems() == 0 || c <= 0) {
|
||
|
delete keep; keep = NULL;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
handleDrag();
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int ItemListWnd::dragComplete(int success) {
|
||
|
ASSERT(keep != NULL);
|
||
|
|
||
|
keep->deleteAll();
|
||
|
delete keep; keep = NULL;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int ItemListWnd::ownerDraw(Canvas *canvas, int pos, RECT *r, LPARAM lParam, int isselected, int isfocused) {
|
||
|
const char *playstring = convertlParam(lParam);
|
||
|
if (playstring == NULL) return 0;
|
||
|
COLORREF bgcolor = isfocused ? getFocusColor(lParam) : getSelBgColor(lParam);
|
||
|
COLORREF fgcolor = getTextColor(lParam);
|
||
|
int iscur = getSelected(lParam);
|
||
|
|
||
|
RECT box;
|
||
|
canvas->getClipBox(&box);
|
||
|
|
||
|
if (!getBgBitmap()) {
|
||
|
RECT r2 = *r;
|
||
|
r2.left = box.left;
|
||
|
RegionI *reg = new RegionI(&r2);
|
||
|
canvas->selectClipRgn(reg);
|
||
|
delete reg;
|
||
|
canvas->fillRect(r, getBgColor());
|
||
|
}
|
||
|
|
||
|
canvas->setTextColor(fgcolor);
|
||
|
|
||
|
// ASSERT(cols.getNumItems() == getNumColumns());
|
||
|
|
||
|
if (isselected) {
|
||
|
RECT mr = *r;
|
||
|
canvas->fillRect(&mr, bgcolor);
|
||
|
/*au gratin potatoes/broccoli
|
||
|
chicken^2
|
||
|
salad, croutons, cheese, ranch
|
||
|
fries */
|
||
|
#ifdef NIFTY_OUTLINE
|
||
|
int prevsel = getItemSelected(pos-1);
|
||
|
int nextsel = getItemSelected(pos+1);
|
||
|
mr.bottom--;
|
||
|
canvas->pushPen(selborder);
|
||
|
canvas->lineDraw(mr.left, mr.top, mr.left, mr.bottom);
|
||
|
canvas->lineDraw(mr.right-1, mr.top, mr.right-1, mr.bottom);
|
||
|
if (!prevsel) canvas->lineDraw(mr.left, mr.top, mr.right, mr.top);
|
||
|
if (!nextsel) canvas->lineDraw(mr.left, mr.bottom, mr.right, mr.bottom);
|
||
|
canvas->popPen();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if (isfocused || iscur) {
|
||
|
int pentype = isfocused ? FALSE : TRUE;
|
||
|
int boxcolor = iscur ? current : focus;
|
||
|
canvas->drawRect(r, pentype, boxcolor);
|
||
|
}
|
||
|
|
||
|
canvas->pushTextSize(getFontSize());
|
||
|
|
||
|
int x = 1+r->left;
|
||
|
for (int i = 0; i < getNumColumns(); i++) {
|
||
|
ItemListColumn *col = (ItemListColumn *)enumListColumn(i);
|
||
|
RECT ir;
|
||
|
ir.left = x;
|
||
|
ir.right = x + getColumnWidth(i);
|
||
|
ir.top = r->top;
|
||
|
ir.bottom = r->bottom;
|
||
|
if (ir.right >= box.left && ir.bottom >= box.top && ir.left <= box.right && ir.top <= box.bottom) {
|
||
|
col->render(pos, playstring, *canvas, ir);
|
||
|
}
|
||
|
x = ir.right;
|
||
|
}
|
||
|
canvas->popTextSize();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void ItemListWnd::convertlParamColumn(int col, int pos, LPARAM param, char *str, int maxlen) {
|
||
|
ASSERT(str != NULL);
|
||
|
ItemListColumn *cl = (ItemListColumn *)enumListColumn(col);
|
||
|
const char *playstring = convertlParam(param);
|
||
|
cl->columnToText(pos, playstring, str, maxlen);
|
||
|
}
|
||
|
|
||
|
|
||
|
int ItemListWnd::onContextMenu(int x, int y) {
|
||
|
PtrList<FilenameNC> filenames;
|
||
|
DragItemI *dragitem = NULL;
|
||
|
|
||
|
if ((dragitem = itemlistwnd_getDragItem(x, y)) == NULL) {
|
||
|
DragItemT<Filename> *di = new DragItemT<Filename>;
|
||
|
int n = getNumItems();
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
if (getItemSelected(i)) {
|
||
|
LPARAM lparam = getItemData(i);
|
||
|
const char *playstring = convertlParam(lparam);
|
||
|
di->addDatum(filenames.addItem(new FilenameNC(playstring)));
|
||
|
}
|
||
|
}
|
||
|
dragitem = di;
|
||
|
}
|
||
|
|
||
|
ContextMenu cm(this, filenames.getNumItems() ? dragitem : NULL, false);
|
||
|
|
||
|
PtrList<DragItemI> drags;
|
||
|
for (int i = 0; ; i++) {
|
||
|
DragItemI *aitem = itemlistwnd_getSecondDragItem(i);
|
||
|
if (aitem == NULL) break;
|
||
|
drags.addItem(aitem);
|
||
|
if (cm.getNumCommands()) cm.addSeparator();
|
||
|
cm.addDragItem(aitem);
|
||
|
}
|
||
|
itemlistwnd_addCustomContextMenuCommands(&cm);
|
||
|
int r = cm.popAtMouse();
|
||
|
if (r < -10) itemlistwnd_contextMenuResult(r);
|
||
|
drags.deleteAll();
|
||
|
|
||
|
filenames.deleteAll();
|
||
|
|
||
|
delete dragitem;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
int ItemListWnd::onRightClick(int itemnum, int _x, int _y) {
|
||
|
// figure out which column they clicked on
|
||
|
int x, l = 0, r = 0;
|
||
|
for (int i = 0; i < cols.getNumItems(); i++) {
|
||
|
l = r;
|
||
|
r += getColumnWidth(i);
|
||
|
if (_x >= l && y <= r) break;
|
||
|
}
|
||
|
if (i >= cols.getNumItems()) return 0;
|
||
|
PlayItem *item = convertlParam(itemnum);
|
||
|
if (!allowEdition(item, cols[i]->getTag())) return 0;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void ItemListWnd::metacb_onItemChange(const char *playstring, const char *tag) {
|
||
|
int n = getNumItems();
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
const char *ps = convertlParam(getItemData(i));
|
||
|
if (ps != NULL && STREQL(ps, playstring)) {
|
||
|
onItemChange(i, ps);
|
||
|
invalidateItem(i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ItemListWnd::metacb_onItemDel(const char *playstring) {
|
||
|
int n = getNumItems();
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
const char *ps = convertlParam(getItemData(i));
|
||
|
if (ps != NULL && STREQL(ps, playstring)) {
|
||
|
onItemDel(i, ps);
|
||
|
invalidateItem(i);
|
||
|
}
|
||
|
}
|
||
|
}
|