Changeset 243 for trunk/src/helpers/cctl_cnr_dtls.c
- Timestamp:
- Jan 29, 2003, 7:41:39 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/cctl_cnr_dtls.c
r242 r243 26 26 // as unsigned char 27 27 28 #define INCL_DOSMISC 29 28 30 #define INCL_WINWINDOWMGR 29 31 #define INCL_WINFRAMEMGR 30 32 #define INCL_WINSYS 33 #define INCL_WININPUT 31 34 #define INCL_WINSTDCNR 32 35 #define INCL_GPIPRIMITIVES … … 61 64 62 65 /* 66 *@@ InvalidateColumn: 67 * 68 */ 69 70 VOID InvalidateColumn(PCNRDATA pData, 71 const DETAILCOLUMN *pColumn) 72 { 73 RECTL rcl; 74 rcl.xLeft = pColumn->xLeft - pData->scrw.ptlScrollOfs.x; 75 rcl.xRight = rcl.xLeft + pColumn->cxContent + 2 * COLUMN_PADDING_X + 1; 76 rcl.yBottom = 0; 77 rcl.yTop = pData->dwdContent.szlWin.cy; 78 79 WinInvalidateRect(pData->dwdContent.hwnd, &rcl, FALSE); 80 81 // and titles too 82 rcl.yTop = pData->dwdMain.szlWin.cy; 83 WinInvalidateRect(pData->dwdMain.hwnd, &rcl, FALSE); 84 } 85 86 /* 63 87 *@@ cdtlRecalcDetails: 64 88 * worker routine for refreshing all internal DETAILCOLUMN … … 68 92 * in with sufficient update flags. 69 93 * 70 * Returns the following ORed flags: 94 * This sets the following flags in *pfl: 95 * 96 * -- DDFL_INVALIDATECOLUMNS: columns have to be 97 * repositioned, so details window needs a full 98 * repaint. 71 99 * 72 100 * -- DDFL_WINDOWSIZECHANGED: cnr titles area changed, … … 79 107 VOID cdtlRecalcDetails(PCNRDATA pData, 80 108 HPS hps, 81 PULONG pfl) 109 PULONG pfl) // in/out: DDFL_* flags 82 110 { 83 111 LONG xCurrent = 0; 84 112 PLISTNODE pColNode; 85 ULONG c Row= 0;113 ULONG cColumn = 0; 86 114 87 115 // compute total padding for one row: 88 LONG cxPaddingRow = pData->CnrInfo.cFields * 2 * COLUMN_PADDING_X, 89 yOfsNow = 0; 90 116 LONG cxPaddingRow = pData->CnrInfo.cFields * 2 * COLUMN_PADDING_X; 91 117 LONG cyColTitlesContent = 0, 92 118 cyColTitlesBox = 0; 93 119 120 BOOL fRefreshAll = (*pfl & (DDFL_INVALIDATECOLUMNS | DDFL_INVALIDATERECORDS)); 121 122 LONG yNow = 0; 123 124 // list of records to invalidate while we're running; 125 // this only gets appended to if we're not invalidating 126 // all records anyway 127 LINKLIST llInvalidateRecords; 128 lstInit(&llInvalidateRecords, FALSE); // receives RECORDLISTITEM's 129 94 130 GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &pData->fm); 95 131 … … 97 133 FOR_ALL_NODES(&pData->llColumns, pColNode) 98 134 { 99 PDETAILCOLUMN pCol = (PDETAILCOLUMN)pColNode->pItemData;100 const FIELDINFO *pfi = pCol ->pfi;135 PDETAILCOLUMN pColumn = (PDETAILCOLUMN)pColNode->pItemData; 136 const FIELDINFO *pfi = pColumn->pfi; 101 137 PLISTNODE pRecNode; 102 138 103 pCol->xLeft = xCurrent; 104 105 pCol->cxTotal 106 = pCol->cxWidestRecord 107 = 0; 108 109 // inner loop: records (go DOWN) 110 FOR_ALL_NODES(&pData->llRootRecords, pRecNode) 111 { 112 PRECORDLISTITEM prliThis = (PRECORDLISTITEM)pRecNode->pItemData; 113 const RECORDCORE *preccThis = prliThis->precc; 114 PVOID pColumnData = (PVOID)((PBYTE)preccThis + pfi->offStruct); 115 116 SIZEL szlThis = {10, 10}; 117 ULONG cLines; 118 PCSZ pcsz = NULL; 119 CHAR szTemp[30]; 120 121 if (!cRow) 122 prliThis->szlContent.cy = 0; 123 124 switch (pfi->flData & ( CFA_BITMAPORICON 125 | CFA_DATE 126 | CFA_STRING 127 | CFA_TIME 128 | CFA_ULONG)) 139 LONG cxContent; 140 141 if (fRefreshAll) 142 pColumn->cxWidestRecord = 0; 143 144 // skip invisible columns 145 if (!(pfi->flData & CFA_INVISIBLE)) 146 { 147 yNow = 0; 148 149 // inner loop: records (go UP) 150 // (we start with the LAST record so we can calculate 151 // the y coordinates correctly) 152 pRecNode = lstQueryLastNode(&pData->llRootRecords); 153 while (pRecNode) 129 154 { 130 case CFA_BITMAPORICON: 131 // @@todo 132 break; 133 134 case CFA_STRING: 135 pcsz = *(PSZ*)pColumnData; 136 break; 137 138 case CFA_DATE: 139 nlsDate(&pData->cs, 140 szTemp, 141 ((PCDATE)pColumnData)->year, 142 ((PCDATE)pColumnData)->month, 143 ((PCDATE)pColumnData)->day); 144 pcsz = szTemp; 145 break; 146 147 case CFA_TIME: 148 nlsTime(&pData->cs, 149 szTemp, 150 ((PCTIME)pColumnData)->hours, 151 ((PCTIME)pColumnData)->minutes, 152 ((PCTIME)pColumnData)->seconds); 153 pcsz = szTemp; 154 break; 155 156 case CFA_ULONG: 157 nlsThousandsULong(szTemp, 158 *((PULONG)pColumnData), 159 pData->cs.cs.cThousands); 160 pcsz = szTemp; 161 break; 162 } 163 164 if (pcsz) 155 PRECORDLISTITEM prliThis = (PRECORDLISTITEM)pRecNode->pItemData; 156 const RECORDCORE *preccThis = prliThis->precc; 157 PVOID pColumnData = (PVOID)((PBYTE)preccThis + pfi->offStruct); 158 159 if (!(prliThis->flRecordAttr & CRA_FILTERED)) 160 { 161 // skip filtered records 162 if ( (*pfl & DDFL_INVALIDATERECORDS) 163 || (prliThis->flInvalidate) 164 ) 165 { 166 ULONG cLines; 167 SIZEL szlThis = {10, 10}; 168 PCSZ pcsz = NULL; 169 CHAR szTemp[30]; 170 171 if (!cColumn) 172 { 173 // we're in the leftmost column: 174 prliThis->szlContent.cx 175 = prliThis->szlContent.cy 176 = prliThis->szlBox.cx 177 = prliThis->szlBox.cy 178 = 0; 179 } 180 181 switch (pfi->flData & ( CFA_BITMAPORICON 182 | CFA_DATE 183 | CFA_STRING 184 | CFA_TIME 185 | CFA_ULONG)) 186 { 187 case CFA_BITMAPORICON: 188 // @@todo 189 break; 190 191 case CFA_STRING: 192 pcsz = *(PSZ*)pColumnData; 193 break; 194 195 case CFA_DATE: 196 nlsDate(&pData->cs, 197 szTemp, 198 ((PCDATE)pColumnData)->year, 199 ((PCDATE)pColumnData)->month, 200 ((PCDATE)pColumnData)->day); 201 pcsz = szTemp; 202 break; 203 204 case CFA_TIME: 205 nlsTime(&pData->cs, 206 szTemp, 207 ((PCTIME)pColumnData)->hours, 208 ((PCTIME)pColumnData)->minutes, 209 ((PCTIME)pColumnData)->seconds); 210 pcsz = szTemp; 211 break; 212 213 case CFA_ULONG: 214 nlsThousandsULong(szTemp, 215 *((PULONG)pColumnData), 216 pData->cs.cs.cThousands); 217 pcsz = szTemp; 218 break; 219 } 220 221 if (pcsz) 222 { 223 gpihCalcTextExtent(hps, 224 pcsz, 225 &szlThis.cx, 226 &cLines); 227 szlThis.cy = cLines * (pData->fm.lMaxBaselineExt + pData->fm.lExternalLeading); 228 } 229 230 // increment record's total width 231 prliThis->szlContent.cx += szlThis.cx; 232 prliThis->szlBox.cx += szlThis.cx 233 + cxPaddingRow; // computed at top 234 235 // record's content height = height of tallest column of that record 236 if (szlThis.cy > prliThis->szlContent.cy) 237 prliThis->szlContent.cy = szlThis.cy; 238 239 // remember max width of this record's column 240 // for the entire column 241 if (szlThis.cx > pColumn->cxWidestRecord) 242 pColumn->cxWidestRecord = szlThis.cx; 243 244 if (!pColNode->pNext) 245 { 246 // last column of outer loop: 247 248 // clear refresh flags, if any 249 prliThis->flInvalidate = 0; 250 251 // compute box cy from content 252 prliThis->szlBox.cy = prliThis->szlContent.cy 253 + pData->CnrInfo.cyLineSpacing; 254 255 // store record's position in workarea coords 256 prliThis->ptl.x = 0; // we're in Details view 257 prliThis->ptl.y = yNow; 258 259 if (!fRefreshAll) 260 // invalidate this record's rectangle 261 lstAppendItem(&llInvalidateRecords, 262 prliThis); 263 } 264 } 265 266 // go down for next record 267 yNow += prliThis->szlBox.cy; 268 269 } // if (!(prliThis->flRecordAttr & CRA_FILTERED)) 270 271 pRecNode = pRecNode->pPrevious; 272 273 } // while (pRecNode) 274 275 if (!(cxContent = pfi->cxWidth)) 165 276 { 166 gpihCalcTextExtent(hps, 167 pcsz, 168 &szlThis.cx, 169 &cLines); 170 szlThis.cy = cLines * (pData->fm.lMaxBaselineExt + pData->fm.lExternalLeading); 171 } 172 173 // remember max width of this record's column 174 // for the entire column 175 if (szlThis.cx > pCol->cxWidestRecord) 176 pCol->cxWidestRecord = szlThis.cx; 177 178 // record's content height = height of tallest column of that record 179 if (szlThis.cy > prliThis->szlContent.cy) 180 prliThis->szlContent.cy = szlThis.cy; 181 182 if (!pColNode->pNext) 183 { 184 // last column: compute box from content 185 prliThis->szlBox.cx = prliThis->szlContent.cx 186 + cxPaddingRow; // computed at top 187 prliThis->szlBox.cy = prliThis->szlContent.cy 188 + pData->CnrInfo.cyLineSpacing; 189 190 prliThis->yOfs = yOfsNow; 191 192 yOfsNow += prliThis->szlBox.cy; 193 } 194 195 ++cRow; 196 } 197 198 if (!(pCol->cxTotal = pfi->cxWidth)) 199 { 200 // this is an auto-size column: 201 202 if (pData->CnrInfo.flWindowAttr & CA_DETAILSVIEWTITLES) 203 { 204 // compute space needed for title 205 206 pCol->szlTitleData.cx 207 = pCol->szlTitleData.cy 208 = 0; 209 210 if (pfi->flTitle & CFA_BITMAPORICON) 211 // @@todo 212 ; 277 // this is an auto-size column: 278 279 if (pData->CnrInfo.flWindowAttr & CA_DETAILSVIEWTITLES) 280 { 281 if (*pfl & DDFL_INVALIDATECOLUMNS) 282 { 283 // compute space needed for title 284 285 pColumn->szlTitleData.cx 286 = pColumn->szlTitleData.cy 287 = 0; 288 289 if (pfi->flTitle & CFA_BITMAPORICON) 290 // @@todo 291 ; 292 else 293 { 294 ULONG cLines; 295 gpihCalcTextExtent(hps, 296 (PCSZ)pfi->pTitleData, 297 &pColumn->szlTitleData.cx, 298 &cLines); 299 pColumn->szlTitleData.cy = cLines * (pData->fm.lMaxBaselineExt + pData->fm.lExternalLeading); 300 } 301 } 302 303 cxContent = max(pColumn->cxWidestRecord, pColumn->szlTitleData.cx); 304 305 if (pColumn->szlTitleData.cy > cyColTitlesContent) 306 cyColTitlesContent = pColumn->szlTitleData.cy; 307 } 213 308 else 214 309 { 215 ULONG cLines; 216 gpihCalcTextExtent(hps, 217 (PCSZ)pfi->pTitleData, 218 &pCol->szlTitleData.cx, 219 &cLines); 220 pCol->szlTitleData.cy = cLines * (pData->fm.lMaxBaselineExt + pData->fm.lExternalLeading); 310 pColumn->szlTitleData.cx 311 = 0; 221 312 } 222 223 pCol->cxTotal = max(pCol->cxWidestRecord, pCol->szlTitleData.cx);224 225 if (pCol->szlTitleData.cy > cyColTitlesContent)226 cyColTitlesContent = pCol->szlTitleData.cy;227 313 } 228 else 314 315 // check if column needs invalidating 316 if ( (fRefreshAll) 317 || (pColumn->xLeft != xCurrent) 318 || (pColumn->cxContent != cxContent) 319 ) 229 320 { 230 pCol->szlTitleData.cx 231 = 0; 321 pColumn->xLeft = xCurrent; 322 pColumn->cxContent = cxContent; 323 324 if (!fRefreshAll) 325 InvalidateColumn(pData, 326 pColumn); 232 327 } 233 } 234 235 // go one column to the right 236 xCurrent += pCol->cxTotal + 2 * COLUMN_PADDING_X; 237 238 if ( (pfi->flData & CFA_SEPARATOR) 239 && (pColNode->pNext) 240 ) 241 xCurrent += DEFAULT_BORDER_WIDTH; 242 } 243 244 if ( (pData->szlWorkarea.cx != xCurrent) 245 || (pData->szlWorkarea.cy != yOfsNow) 328 329 // go one column to the right 330 xCurrent += cxContent + 2 * COLUMN_PADDING_X; 331 332 if ( (pfi->flData & CFA_SEPARATOR) 333 && (pColNode->pNext) 334 ) 335 xCurrent += DEFAULT_BORDER_WIDTH; 336 337 ++cColumn; 338 } 339 } 340 341 // has workarea changed? 342 if ( (pData->scrw.szlWorkarea.cx != xCurrent) 343 || (pData->scrw.szlWorkarea.cy != yNow) 246 344 ) 247 345 { 248 pData->s zlWorkarea.cx = xCurrent;249 pData->s zlWorkarea.cy = yOfsNow;346 pData->scrw.szlWorkarea.cx = xCurrent; 347 pData->scrw.szlWorkarea.cy = yNow; 250 348 *pfl |= DDFL_WORKAREACHANGED; 251 349 } 252 350 351 // has details title box changed? 253 352 if (pData->CnrInfo.flWindowAttr & CA_DETAILSVIEWTITLES) 254 353 cyColTitlesBox = cyColTitlesContent … … 265 364 *pfl |= DDFL_WINDOWSIZECHANGED | DDFL_WORKAREACHANGED; 266 365 } 366 367 // now invalidate records 368 if (fRefreshAll) 369 WinInvalidateRect(pData->dwdMain.hwnd, NULL, TRUE); 370 else 371 { 372 PLISTNODE pNode = lstQueryFirstNode(&llInvalidateRecords); 373 while (pNode) 374 { 375 ctnrRepaintRecord(pData, (PRECORDLISTITEM)pNode->pItemData); 376 pNode = pNode->pNext; 377 } 378 } 379 380 lstClear(&llInvalidateRecords); 267 381 } 268 382 … … 276 390 MRESULT DetailsCreate(HWND hwnd, MPARAM mp1, MPARAM mp2) 277 391 { 278 if (!mp1) 392 HWND hwndParent; 393 394 if ( (!mp1) 395 || (!mp2) 396 || (!(hwndParent = (((PCREATESTRUCT)mp2)->hwndParent))) 397 ) 279 398 return (MRESULT)TRUE; 280 399 … … 282 401 283 402 // initialize DEFWINDOWDATA 284 ctlInitDWD(hwnd, 285 mp2, 286 &((PCNRDATA)mp1)->dwdContent, 287 WinDefWindowProc, 288 &G_scsCnr); 403 ctnrInit(hwnd, 404 mp2, 405 winhQueryWindowStyle(hwndParent), // main container 406 &((PCNRDATA)mp1)->dwdContent); 407 408 // the cnr appears to always grab the focus on creation 409 WinSetFocus(HWND_DESKTOP, hwnd); // @@todo how do we do this on creation only? 289 410 290 411 return (MRESULT)FALSE; … … 297 418 */ 298 419 299 VOID DetailsPaint( HWND hwnd)420 VOID DetailsPaint(PCNRDATA pData) 300 421 { 301 422 HPS hps; 302 PCNRDATA pData; 303 RECTL rclPaint; 304 305 if ( (pData = (PCNRDATA)WinQueryWindowPtr(hwnd, QWL_USER + 1)) 306 && (hps = WinBeginPaint(hwnd, NULLHANDLE, &rclPaint)) 307 ) 308 { 309 PLISTNODE pColNode; 310 311 POINTL ptl; 312 RECTL rcl; 423 RECTL rclClip; 424 425 if (hps = WinBeginPaint(pData->dwdContent.hwnd, NULLHANDLE, &rclClip)) 426 { 427 PLISTNODE pColNode, 428 pRecNodeFirst2Paint = NULL; // first one to paint 429 313 430 LONG yPadding = pData->CnrInfo.cyLineSpacing / 2; 314 431 ULONG cColumn = 0; 432 BOOL fFirstCol = TRUE; 433 434 BOOL fHasFocus; 435 HWND hwndFocus; 436 437 if ( (hwndFocus = WinQueryFocus(HWND_DESKTOP)) 438 && (hwndFocus == pData->dwdContent.hwnd) 439 ) 440 fHasFocus = TRUE; 441 else 442 fHasFocus = FALSE; 315 443 316 444 gpihSwitchToRGB(hps); 445 446 #if 0 447 { 448 ULONG ulTimeNow; 449 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, 450 &ulTimeNow, 451 sizeof(ulTimeNow)); 452 WinFillRect(hps, 453 &rclClip, 454 ulTimeNow & 0xFFFFFF); 455 } 456 #else 317 457 WinFillRect(hps, 318 &rclPaint, 319 pData->dwdMain.lcolBackground); 320 321 FOR_ALL_NODES(&pData->llColumns, pColNode) 458 &rclClip, 459 ctlQueryColor(&pData->dwdMain, CTLCOL_BGND)); 460 #endif 461 462 // skip columns that are not in paint rectangle 463 pColNode = lstQueryFirstNode(&pData->llColumns); 464 while (pColNode) 465 { 466 PDETAILCOLUMN pCol = (PDETAILCOLUMN)pColNode->pItemData; 467 const FIELDINFO *pfi = pCol->pfi; 468 if ( (!(pfi->flData & CFA_INVISIBLE)) 469 && (pCol->xLeft + pCol->cxContent - pData->scrw.ptlScrollOfs.x >= rclClip.xLeft) 470 ) 471 break; 472 473 pColNode = pColNode->pNext; 474 } 475 476 // now loop for the remaining columns (go RIGHT) 477 while (pColNode) 322 478 { 323 479 PDETAILCOLUMN pCol = (PDETAILCOLUMN)pColNode->pItemData; 324 480 const FIELDINFO *pfi = pCol->pfi; 325 481 PLISTNODE pRecNode; 326 ULONG cRow; 327 328 rcl.xLeft = pCol->xLeft + COLUMN_PADDING_X - pData->ptlScrollOfs.x; 329 rcl.xRight = rcl.xLeft + pCol->cxTotal; 330 331 // we start out at the top and work our way down, 332 // decrementing rcl.yTop with every item we painted 333 rcl.yTop = pData->dwdContent.szlWin.cy + pData->ptlScrollOfs.y; 334 335 PMPF_RECT("rcl: ", &rcl); 336 337 // now paint this column's data for all records! 338 cRow = 0; 339 FOR_ALL_NODES(&pData->llRootRecords, pRecNode) 482 483 if (!(pfi->flData & CFA_INVISIBLE)) 340 484 { 341 PRECORDLISTITEM prliThis = (PRECORDLISTITEM)pRecNode->pItemData; 342 const RECORDCORE *preccThis = prliThis->precc; 343 PVOID pColumnData = (PVOID)((PBYTE)preccThis + pfi->offStruct); 344 CHAR szTemp[30]; 345 PCSZ pcsz = NULL; 346 347 rcl.yTop -= yPadding; 348 rcl.yBottom = rcl.yTop 349 - prliThis->szlContent.cy; 350 351 switch (pfi->flData & ( CFA_BITMAPORICON 352 | CFA_DATE 353 | CFA_STRING 354 | CFA_TIME 355 | CFA_ULONG)) 485 RECTL rclRecc, 486 rcl; 487 488 rcl.xLeft = pCol->xLeft + COLUMN_PADDING_X - pData->scrw.ptlScrollOfs.x; 489 rcl.xRight = rcl.xLeft + pCol->cxContent; 490 491 if (fFirstCol) 356 492 { 357 case CFA_BITMAPORICON: 358 // @@todo 359 break; 360 361 case CFA_STRING: 362 pcsz = *(PSZ*)pColumnData; 363 break; 364 365 case CFA_DATE: 366 nlsDate(&pData->cs, 367 szTemp, 368 ((PCDATE)pColumnData)->year, 369 ((PCDATE)pColumnData)->month, 370 ((PCDATE)pColumnData)->day); 371 pcsz = szTemp; 372 break; 373 374 case CFA_TIME: 375 nlsTime(&pData->cs, 376 szTemp, 377 ((PCTIME)pColumnData)->hours, 378 ((PCTIME)pColumnData)->minutes, 379 ((PCTIME)pColumnData)->seconds); 380 pcsz = szTemp; 381 break; 382 383 case CFA_ULONG: 384 nlsThousandsULong(szTemp, 385 *((PULONG)pColumnData), 386 pData->cs.cs.cThousands); 387 pcsz = szTemp; 388 break; 493 // first time we get here: skip all records that 494 // are outside the paint rectangle 495 496 pRecNode = lstQueryFirstNode(&pData->llRootRecords); 497 while (pRecNode) 498 { 499 PRECORDLISTITEM prliThis = (PRECORDLISTITEM)pRecNode->pItemData; 500 501 if (!(prliThis->flRecordAttr & CRA_FILTERED)) 502 { 503 ctnrGetRecordRect(pData, &rclRecc, prliThis); 504 if (rclRecc.yBottom <= rclClip.yTop) 505 { 506 pRecNodeFirst2Paint = pRecNode; 507 508 break; 509 } 510 } 511 512 pRecNode = pRecNode->pNext; 513 } 389 514 } 390 515 391 if (pcsz) 392 cnrDrawString(hps, 393 pcsz, 394 &rcl, 395 pfi->flData, 396 &pData->fm); 397 398 ++cRow; 399 400 rcl.yTop = rcl.yBottom - yPadding; 516 // now inner loop for the remaining records (go DOWN) 517 pRecNode = pRecNodeFirst2Paint; 518 while (pRecNode) 519 { 520 PRECORDLISTITEM prliThis = (PRECORDLISTITEM)pRecNode->pItemData; 521 522 if (!(prliThis->flRecordAttr & CRA_FILTERED)) 523 { 524 const RECORDCORE *preccThis = prliThis->precc; 525 PVOID pColumnData = (PVOID)((PBYTE)preccThis + pfi->offStruct); 526 CHAR szTemp[100]; 527 PCSZ pcsz = NULL; 528 LONG lcolBackground, 529 lcolForeground; 530 531 ctnrGetRecordRect(pData, &rclRecc, prliThis); 532 533 PMPF_RECT("rclRecc: ", &rclRecc); 534 535 if (prliThis->flRecordAttr & CRA_SELECTED) 536 { 537 lcolBackground = ctlQueryColor(&pData->dwdMain, CNRCOL_HILITEBGND); 538 lcolForeground = ctlQueryColor(&pData->dwdMain, CNRCOL_HILITEFGND); 539 540 if (fFirstCol) 541 WinFillRect(hps, 542 &rclRecc, 543 lcolBackground); 544 } 545 else 546 { 547 lcolBackground = ctlQueryColor(&pData->dwdMain, CTLCOL_BGND); 548 lcolForeground = ctlQueryColor(&pData->dwdMain, CTLCOL_FGND); 549 } 550 551 GpiSetColor(hps, lcolForeground); 552 GpiSetBackColor(hps, lcolBackground); 553 554 rcl.yTop = rclRecc.yTop - yPadding; 555 rcl.yBottom = rcl.yTop - prliThis->szlContent.cy; 556 557 if ( (fFirstCol) 558 && (prliThis->flRecordAttr & CRA_CURSORED) 559 ) 560 { 561 RECTL rcl2; 562 rcl2.xLeft = rclRecc.xLeft + 1; 563 rcl2.xRight = rclRecc.xRight - 2; 564 rcl2.yBottom = rclRecc.yBottom + 1; 565 rcl2.yTop = rclRecc.yTop - 2; 566 GpiSetLineType(hps, LINETYPE_ALTERNATE); 567 gpihBox(hps, 568 DRO_OUTLINE, 569 &rcl2); 570 GpiSetLineType(hps, LINETYPE_DEFAULT); 571 } 572 573 switch (pfi->flData & ( CFA_BITMAPORICON 574 | CFA_DATE 575 | CFA_STRING 576 | CFA_TIME 577 | CFA_ULONG)) 578 { 579 case CFA_BITMAPORICON: 580 // @@todo 581 break; 582 583 case CFA_STRING: 584 pcsz = *(PSZ*)pColumnData; 585 break; 586 587 case CFA_DATE: 588 nlsDate(&pData->cs, 589 szTemp, 590 ((PCDATE)pColumnData)->year, 591 ((PCDATE)pColumnData)->month, 592 ((PCDATE)pColumnData)->day); 593 pcsz = szTemp; 594 break; 595 596 case CFA_TIME: 597 nlsTime(&pData->cs, 598 szTemp, 599 ((PCTIME)pColumnData)->hours, 600 ((PCTIME)pColumnData)->minutes, 601 ((PCTIME)pColumnData)->seconds); 602 pcsz = szTemp; 603 break; 604 605 case CFA_ULONG: 606 nlsThousandsULong(szTemp, 607 *((PULONG)pColumnData), 608 pData->cs.cs.cThousands); 609 pcsz = szTemp; 610 break; 611 } 612 613 if (pcsz) 614 ctnrDrawString(hps, 615 pcsz, 616 &rcl, 617 pfi->flData, 618 &pData->fm); 619 620 // if we're outside the paint rect now, 621 // we can quit 622 // _Pmpf(("rcl.yBottom: %d, rclClip.yBottom: %d", 623 // rcl.yBottom, 624 // rclClip.yBottom)); 625 if (rclRecc.yBottom <= rclClip.yBottom) 626 break; 627 628 } // if (!(prliThis->flRecordAttr & CRA_FILTERED)) 629 630 pRecNode = pRecNode->pNext; 631 632 } // while (pRecNode) 633 634 // paint vertical separators after this column? 635 if (pfi->flData & CFA_SEPARATOR) 636 { 637 POINTL ptl; 638 GpiSetColor(hps, ctlQueryColor(&pData->dwdMain, CNRCOL_BORDER)); 639 ptl.x = rcl.xRight + COLUMN_PADDING_X; 640 ptl.y = pData->dwdContent.szlWin.cy; 641 GpiMove(hps, 642 &ptl); 643 ptl.y = 0; 644 GpiLine(hps, 645 &ptl); 646 } 647 648 fFirstCol = FALSE; 649 650 ++cColumn; 651 652 // we're done if this column is outside the 653 // paint rectangle 654 if ( (!(pCol->pfi->flData & CFA_INVISIBLE)) 655 && (pCol->xLeft + pCol->cxContent - pData->scrw.ptlScrollOfs.x >= rclClip.xRight) 656 ) 657 break; // while (pColNode) 658 659 } // if (!(pfi->flData & CFA_INVISIBLE)) 660 661 pColNode = pColNode->pNext; 662 663 } // while (pColNode) 664 665 WinEndPaint(hps); 666 } 667 } 668 669 /* 670 *@@ FindRecordFromMouseY: 671 * 672 */ 673 674 PRECORDLISTITEM FindRecordFromMouseY(PCNRDATA pData, 675 SHORT y) 676 { 677 // convert y clickpos from window to workspace coordinates 678 LONG deltaWorkspace = ( pData->scrw.szlWorkarea.cy 679 - pData->dwdContent.szlWin.cy) 680 - pData->scrw.ptlScrollOfs.y; 681 LONG yWorkspace = (LONG)y + deltaWorkspace; 682 683 PLISTNODE pRecNode = lstQueryFirstNode(&pData->llRootRecords); 684 while (pRecNode) 685 { 686 PRECORDLISTITEM prliThis = (PRECORDLISTITEM)pRecNode->pItemData; 687 688 if (!(prliThis->flRecordAttr & CRA_FILTERED)) 689 { 690 if (prliThis->ptl.y < yWorkspace) 691 return prliThis; 692 } 693 694 pRecNode = pRecNode->pNext; 695 } 696 697 return NULL; 698 } 699 700 /* 701 *@@ DeselectExcept: 702 * 703 */ 704 705 VOID DeselectExcept(PCNRDATA pData, 706 PRECORDLISTITEM prliMouse) 707 { 708 // deselect all selected 709 PLISTNODE pRecNode; 710 pRecNode = lstQueryFirstNode(&pData->llRootRecords); 711 while (pRecNode) 712 { 713 PRECORDLISTITEM prliThis = (PRECORDLISTITEM)pRecNode->pItemData; 714 715 if ( (prliThis != prliMouse) 716 && (prliThis->flRecordAttr & CRA_SELECTED) 717 ) 718 { 719 ctnrChangeEmphasis(pData, 720 prliThis, 721 FALSE, 722 CRA_SELECTED); 723 } 724 725 pRecNode = pRecNode->pNext; 726 } 727 } 728 729 /* 730 *@@ DetailsSingleSelect: 731 * implementation for WM_SINGLESELECT in fnwpCnrDetails. 732 */ 733 734 MRESULT DetailsSingleSelect(PCNRDATA pData, 735 SHORT y) 736 { 737 if (pData) 738 { 739 BOOL fCtrl = WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000; 740 ULONG ulSel = ctnrQuerySelMode(pData); 741 742 // find record under mouse 743 PRECORDLISTITEM prliMouse = FindRecordFromMouseY(pData, y); 744 745 if ( (ulSel == CCS_SINGLESEL) 746 || (!fCtrl) 747 ) 748 { 749 DeselectExcept(pData, prliMouse); 750 } 751 752 if (prliMouse) // can be null with click on whitespace 753 { 754 // when ctrl is pressed, toggle the state of 755 // the record under the mouse; otherwise select it 756 ctnrChangeEmphasis(pData, 757 prliMouse, 758 (!fCtrl) || (!(prliMouse->flRecordAttr & CRA_SELECTED)), 759 CRA_SELECTED | CRA_CURSORED); 760 } 761 762 return (MRESULT)TRUE; 763 } 764 765 return (MRESULT)FALSE; 766 } 767 768 /* 769 *@@ DetailsBeginSelect: 770 * implementation for WM_BEGINSELECT in fnwpCnrDetails. 771 * 772 */ 773 774 MRESULT DetailsBeginSelect(PCNRDATA pData, 775 SHORT y) 776 { 777 if (pData) 778 { 779 BOOL fCtrl = WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000; 780 ULONG ulSel = ctnrQuerySelMode(pData); 781 PRECORDLISTITEM prliMouse; 782 783 // find record under mouse 784 prliMouse 785 = pData->prliSwipingFirst 786 = FindRecordFromMouseY(pData, y); 787 788 if ( (ulSel == CCS_SINGLESEL) 789 || (!fCtrl) 790 ) 791 { 792 DeselectExcept(pData, prliMouse ); 793 } 794 795 if (prliMouse ) 796 { 797 // when ctrl is pressed, toggle the state of 798 // the record under the mouse; otherwise select it; 799 // perform this operation on all the records that 800 // user swipes over (seems to be how pm cnr does it) 801 pData->fSwipeTurnOn = (!fCtrl) || (!(prliMouse->flRecordAttr & CRA_SELECTED)); 802 803 ctnrChangeEmphasis(pData, 804 prliMouse , 805 pData->fSwipeTurnOn, 806 CRA_SELECTED | CRA_CURSORED); 807 WinSetCapture(HWND_DESKTOP, pData->dwdContent.hwnd); 808 } 809 810 return (MRESULT)TRUE; 811 } 812 813 return (MRESULT)FALSE; 814 } 815 816 /* 817 *@@ DetailsMouseMove: 818 * implementation for WM_MOUSEMOVE in fnwpCnrDetails. 819 */ 820 821 MRESULT DetailsMouseMove(PCNRDATA pData, 822 MPARAM mp1, 823 MPARAM mp2) 824 { 825 if (pData) 826 { 827 if (pData->prliSwipingFirst) 828 { 829 // we're swiping: 830 PRECORDLISTITEM prliThis; 831 if (prliThis = FindRecordFromMouseY(pData, 832 SHORT2FROMMP(mp1))) 833 ctnrChangeEmphasis(pData, 834 prliThis, 835 pData->fSwipeTurnOn, 836 CRA_SELECTED | CRA_CURSORED); 837 } 838 839 return ctlDefWindowProc(&pData->dwdContent, WM_MOUSEMOVE, mp1, mp2); 840 } 841 842 return (MRESULT)FALSE; 843 } 844 845 /* 846 *@@ DetailsEndSelect: 847 * implementation for WM_ENDSELECT in fnwpCnrDetails. 848 */ 849 850 MRESULT DetailsEndSelect(PCNRDATA pData) 851 { 852 if (pData) 853 { 854 if (pData->prliSwipingFirst) 855 { 856 WinSetCapture(HWND_DESKTOP, NULLHANDLE); 857 pData->prliSwipingFirst = NULL; 858 } 859 860 return (MRESULT)TRUE; 861 } 862 863 return (MRESULT)FALSE; 864 } 865 866 /* 867 *@@ DetailsOpen: 868 * implementation for WM_OPEN in fnwpCnrDetails. 869 */ 870 871 MRESULT DetailsOpen(PCNRDATA pData) 872 { 873 if (pData) 874 { 875 ctnrRecordEnter(pData, 876 pData->prliCursored, 877 FALSE); // mouse, not keyboard 878 879 return (MRESULT)TRUE; 880 } 881 882 return (MRESULT)FALSE; 883 } 884 885 /* 886 *@@ ScrollToRecord: 887 * scrolls the content area so that the given record becomes 888 * visible. 889 * 890 + If fMakeTop == TRUE, we scroll so that the top of the 891 * record's box is scrolled to the top of the window. 892 * Otherwise we scroll so that the bottom of the record's 893 * box is at the bottom of the rectangle. 894 */ 895 896 VOID ScrollToRecord(PCNRDATA pData, 897 PRECORDLISTITEM prliThis, 898 BOOL fMakeTop, 899 BOOL fForce) // in: if TRUE, we scroll even if the record is already visible 900 { 901 RECTL rcl; 902 LONG lNewY = -100; 903 904 ctnrGetRecordRect(pData, &rcl, prliThis); 905 if (fMakeTop) 906 { 907 if ( (rcl.yTop > pData->dwdContent.szlWin.cy) 908 || (fForce) 909 ) 910 { 911 /* 912 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ä¿ 913 ³ ³ ³ pData->scrw.ptlScrollOfs.y 914 +-----------------------------+ ÄÙ 915 +-----------------------------+ 916 º º 917 º º 918 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ 919 ³ ³ 920 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ 921 */ 922 lNewY = pData->scrw.szlWorkarea.cy 923 - (prliThis->ptl.y + prliThis->szlBox.cy); 924 } 925 } 926 else if ( (rcl.yBottom < 0) 927 || (fForce) 928 ) 929 { 930 /* 931 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ä¿ 932 ³ ³ ³ pData->scrw.ptlScrollOfs.y 933 ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ³ 934 º º ³ 935 +-----------------------------+ ³ 936 +-----------------------------+ ÄÙ 937 ³ ³ 938 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ 939 */ 940 lNewY = pData->scrw.szlWorkarea.cy 941 - pData->dwdContent.szlWin.cy 942 - prliThis->ptl.y; 943 } 944 945 if (lNewY != -100) 946 { 947 POINTL ptlScroll; 948 949 if (lNewY < 0) 950 lNewY = 0; 951 else if (lNewY >= pData->scrw.szlWorkarea.cy) 952 lNewY = pData->scrw.szlWorkarea.cy - 1; 953 954 ptlScroll.x = 0; 955 ptlScroll.y = lNewY - pData->scrw.ptlScrollOfs.y; 956 957 winhScrollWindow(pData->dwdContent.hwnd, 958 NULL, 959 &ptlScroll); 960 961 pData->scrw.ptlScrollOfs.y = lNewY; 962 963 WinPostMsg(pData->dwdMain.hwnd, 964 WM_SEM2, 965 (MPARAM)DDFL_WORKAREACHANGED, 966 0); 967 } 968 } 969 970 /* 971 *@@ DetailsChar: 972 * implementation for WM_CHAR in fnwpCnrDetails. 973 */ 974 975 MRESULT DetailsChar(PCNRDATA pData, 976 MPARAM mp1, 977 MPARAM mp2) 978 { 979 if (pData) 980 { 981 USHORT usFlags = SHORT1FROMMP(mp1); 982 USHORT usch = SHORT1FROMMP(mp2); 983 USHORT usvk = SHORT2FROMMP(mp2); 984 985 PRECORDLISTITEM prliThis; 986 PLISTNODE pNode; 987 PRECORDLISTITEM prliScrollTo = NULL; 988 BOOL fMakeTop = FALSE, 989 fForce = FALSE; 990 991 if (usFlags & KC_VIRTUALKEY) 992 { 993 switch (usvk) 994 { 995 case VK_ENTER: 996 case VK_NEWLINE: 997 if (!(usFlags & KC_KEYUP)) 998 if (pData->prliCursored) 999 ctnrRecordEnter(pData, 1000 pData->prliCursored, 1001 TRUE); // keyboard 1002 1003 return (MRESULT)TRUE; 1004 1005 case VK_SPACE: 1006 if (!(usFlags & KC_KEYUP)) 1007 { 1008 if ( (CCS_SINGLESEL != ctnrQuerySelMode(pData)) 1009 && (prliThis = pData->prliCursored) 1010 ) 1011 { 1012 if (prliThis->flRecordAttr & CRA_SELECTED) 1013 DeselectExcept(pData, NULL); 1014 else 1015 ctnrChangeEmphasis(pData, 1016 prliThis, 1017 TRUE, 1018 CRA_SELECTED); 1019 } 1020 } 1021 1022 return (MRESULT)TRUE; 1023 1024 case VK_DOWN: 1025 case VK_UP: 1026 if (!(usFlags & KC_KEYUP)) 1027 { 1028 if ( (prliThis = pData->prliCursored) 1029 && (pNode = ctnrFindListNodeForRecc(pData, prliThis->precc)) 1030 ) 1031 { 1032 while (TRUE) 1033 { 1034 if (usvk == VK_UP) 1035 { 1036 if (!(pNode = pNode->pPrevious)) 1037 break; 1038 } 1039 else 1040 if (!(pNode = pNode->pNext)) 1041 break; 1042 1043 prliThis = (PRECORDLISTITEM)pNode->pItemData; 1044 if (!(prliThis->flRecordAttr & CRA_FILTERED)) 1045 { 1046 prliScrollTo = prliThis; 1047 fMakeTop = (usvk == VK_UP); 1048 break; 1049 } 1050 } 1051 } 1052 } 1053 break; 1054 1055 case VK_HOME: 1056 case VK_END: 1057 if (!(usFlags & KC_KEYUP)) 1058 { 1059 if (usvk == VK_HOME) 1060 pNode = lstQueryFirstNode(&pData->llRootRecords); 1061 else 1062 pNode = lstQueryLastNode(&pData->llRootRecords); 1063 1064 while (pNode) 1065 { 1066 prliThis = (PRECORDLISTITEM)pNode->pItemData; 1067 if (!(prliThis->flRecordAttr & CRA_FILTERED)) 1068 { 1069 prliScrollTo = prliThis; 1070 if (usvk == VK_HOME) 1071 fMakeTop = TRUE; 1072 fForce = TRUE; 1073 break; 1074 } 1075 1076 if (usvk == VK_HOME) 1077 pNode = pNode->pNext; 1078 else 1079 pNode = pNode->pPrevious; 1080 } 1081 } 1082 break; 1083 1084 case VK_PAGEDOWN: 1085 if (!(usFlags & KC_KEYUP)) 1086 { 1087 // find the bottommost record currently visible in the 1088 // viewport and make that one the topmost 1089 prliScrollTo = FindRecordFromMouseY(pData, 1090 0); // window y 1091 fMakeTop = TRUE; 1092 fForce = TRUE; 1093 } 1094 break; 1095 1096 case VK_PAGEUP: 1097 if (!(usFlags & KC_KEYUP)) 1098 { 1099 // find the topmost record currently visible in the 1100 // viewport 1101 prliScrollTo = FindRecordFromMouseY(pData, 1102 pData->dwdContent.szlWin.cy); // window y 1103 // @@todo this is slightly different from the pm cnr behavior 1104 fForce = TRUE; 1105 } 1106 break; 401 1107 } 402 1108 403 // paint vertical separators after this column? 404 if (pfi->flData & CFA_SEPARATOR) 1109 if (prliScrollTo) 405 1110 { 406 ptl.x = rcl.xRight + COLUMN_PADDING_X; 407 ptl.y = pData->dwdContent.szlWin.cy; 408 GpiMove(hps, 409 &ptl); 410 ptl.y = 0; 411 GpiLine(hps, 412 &ptl); 1111 DeselectExcept(pData, prliScrollTo); 1112 1113 ctnrChangeEmphasis(pData, 1114 prliScrollTo, 1115 TRUE, 1116 CRA_SELECTED | CRA_CURSORED); 1117 1118 // now make sure the new record is visible 1119 // in the viewport 1120 ScrollToRecord(pData, 1121 prliScrollTo, 1122 fMakeTop, 1123 fForce); 1124 1125 return (MRESULT)TRUE; 413 1126 } 414 415 ++cColumn; 416 417 } // FOR_ALL_NODES(&pData->llColumns, pColNode) 418 419 WinEndPaint(hps); 420 } 1127 } 1128 } 1129 1130 return (MRESULT)FALSE; 421 1131 } 422 1132 … … 434 1144 MRESULT EXPENTRY fnwpCnrDetails(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) 435 1145 { 436 MRESULT mrc = 0;437 PCNRDATA pData ;1146 MRESULT mrc = 0; 1147 PCNRDATA pData = (PCNRDATA)WinQueryWindowPtr(hwnd, QWL_USER + 1); 438 1148 439 1149 switch (msg) 440 1150 { 1151 /* ****************************************************************** 1152 * 1153 * Standard window messages 1154 * 1155 ********************************************************************/ 1156 441 1157 case WM_CREATE: 442 1158 mrc = DetailsCreate(hwnd, mp1, mp2); … … 444 1160 445 1161 case WM_PAINT: 446 DetailsPaint( hwnd);1162 DetailsPaint(pData); 447 1163 break; 448 1164 1165 case WM_SYSCOLORCHANGE: 1166 ctnrPresParamChanged(hwnd, 0); 1167 break; 1168 449 1169 case WM_PRESPARAMCHANGED: 450 c nrPresParamChanged(hwnd, (ULONG)mp1);1170 ctnrPresParamChanged(hwnd, (ULONG)mp1); 451 1171 break; 452 1172 1173 /* ****************************************************************** 1174 * 1175 * Mouse and keyboard input 1176 * 1177 ********************************************************************/ 1178 1179 case WM_MOUSEMOVE: 1180 mrc = DetailsMouseMove(pData, 1181 mp1, 1182 mp2); 1183 break; 1184 1185 case WM_BUTTON1DOWN: 1186 case WM_BUTTON2DOWN: 1187 case WM_BUTTON3DOWN: 1188 WinSetFocus(HWND_DESKTOP, pData->dwdContent.hwnd); 1189 mrc = (MPARAM)TRUE; 1190 break; 1191 1192 case WM_SINGLESELECT: 1193 mrc = DetailsSingleSelect(pData, 1194 SHORT2FROMMP(mp1)); // we only need y in details view 1195 break; 1196 1197 case WM_BEGINSELECT: 1198 mrc = DetailsBeginSelect(pData, 1199 SHORT2FROMMP(mp1)); 1200 break; 1201 1202 case WM_ENDSELECT: 1203 mrc = DetailsEndSelect(pData); 1204 break; 1205 1206 case WM_OPEN: 1207 mrc = DetailsOpen(pData); 1208 break; 1209 1210 case WM_CHAR: 1211 mrc = DetailsChar(pData, mp1, mp2); 1212 break; 1213 1214 /* ****************************************************************** 1215 * 1216 * Direct manipulation 1217 * 1218 ********************************************************************/ 1219 1220 case DM_DRAGOVER: 1221 case DM_DRAGLEAVE: 1222 case DM_DROPNOTIFY: 1223 case DM_DROP: 1224 case DM_DROPHELP: 1225 453 1226 default: 454 if (pData = (PCNRDATA)WinQueryWindowPtr(hwnd, QWL_USER + 1))1227 if (pData) 455 1228 mrc = ctlDefWindowProc(&pData->dwdContent, msg, mp1, mp2); 456 1229 break; 457 458 1230 } 459 1231
Note:
See TracChangeset
for help on using the changeset viewer.