2
* Copyright(c) 1992 Bell Communications Research, Inc. (Bellcore)
3
* Copyright(c) 1995-99 Andrew Lister
5
* Permission to use, copy, modify and distribute this material for
6
* any purpose and without fee is hereby granted, provided that the
7
* above copyright notice and this permission notice appear in all
8
* copies, and that the name of Bellcore not be used in advertising
9
* or publicity pertaining to this material without the specific,
10
* prior written permission of an authorized representative of
13
* BELLCORE MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES, EX-
14
* PRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, INCLUDING, BUT
15
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
* FITNESS FOR ANY PARTICULAR PURPOSE, AND THE WARRANTY AGAINST IN-
17
* FRINGEMENT OF PATENTS OR OTHER INTELLECTUAL PROPERTY RIGHTS. THE
18
* SOFTWARE IS PROVIDED "AS IS", AND IN NO EVENT SHALL BELLCORE OR
19
* ANY OF ITS AFFILIATES BE LIABLE FOR ANY DAMAGES, INCLUDING ANY
20
* LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES RELAT-
21
* ING TO THE SOFTWARE.
23
* $Id: Shadow.c,v 1.1 1999/09/11 01:25:38 fnevgeny Exp $
28
* Shadow.c created by Andrew Lister (30 October, 1995)
41
#include <Xbae/MatrixP.h>
42
#include <Xbae/Shadow.h>
43
#include <Xbae/Draw.h>
44
#include <Xbae/Utils.h>
46
static void DrawRowShadow P((XbaeMatrixWidget, Window, int, int, int,
47
int, int, int, GC, GC));
49
static void DrawColumnShadow P((XbaeMatrixWidget, Window, int, int, int,
50
int, int, int, GC, GC));
52
static void DrawRowHighlight P((XbaeMatrixWidget, Window, GC, int, int,
53
int, int, int, int, int));
54
static void DrawColumnHighlight P((XbaeMatrixWidget, Window, GC, int,
55
int, int, int, int, int, int));
58
#if NeedFunctionPrototypes
59
xbaeDrawCellShadow(XbaeMatrixWidget mw, Window win, int row, int column, int x,
60
int y, int width, int height, Boolean label,
61
Boolean clipped, Boolean pressed)
63
xbaeDrawCellShadow(mw, win, row, column, x, y, width, height, label, clipped,
78
unsigned char grid_type;
81
if ((mw->matrix.cell_shadow_thickness == 0) &&
82
(!IN_GRID_ROW_MODE(mw)) && (!IN_GRID_COLUMN_MODE(mw)))
86
* Surround the cell with a shadow.
90
shadow = pressed ? XmSHADOW_IN : XmSHADOW_OUT;
91
grid_type = XmGRID_CELL_SHADOW;
95
shadow = mw->matrix.cell_shadow_types ?
96
mw->matrix.cell_shadow_types[row][column] :
97
mw->matrix.cell_shadow_type;
98
grid_type = mw->matrix.grid_type;
105
case XmGRID_CELL_SHADOW:
106
DRAW_SHADOW(XtDisplay(mw), win,
107
mw->matrix.cell_top_shadow_clip_gc,
108
mw->matrix.cell_bottom_shadow_clip_gc,
109
mw->matrix.cell_shadow_thickness,
110
x, y, width, height, shadow);
113
/* Deprecated types. To be removed in next version. */
114
case XmGRID_SHADOW_OUT:
115
DRAW_SHADOW(XtDisplay(mw), win,
116
mw->matrix.cell_bottom_shadow_clip_gc,
117
mw->matrix.cell_top_shadow_clip_gc,
118
mw->matrix.cell_shadow_thickness,
119
x, y, width, height, shadow);
121
case XmGRID_SHADOW_IN:
122
DRAW_SHADOW(XtDisplay(mw), win,
123
mw->matrix.cell_top_shadow_clip_gc,
124
mw->matrix.cell_bottom_shadow_clip_gc,
125
mw->matrix.cell_shadow_thickness,
126
x, y, width, height, shadow);
136
case XmGRID_ROW_SHADOW:
137
DrawRowShadow(mw, win, row, column, x, y, width, height,
138
mw->manager.top_shadow_GC,
139
mw->manager.bottom_shadow_GC);
141
case XmGRID_ROW_LINE:
142
DrawRowShadow(mw, win, row, column, x, y, width, height,
143
mw->matrix.grid_line_gc, mw->matrix.grid_line_gc);
145
case XmGRID_COLUMN_SHADOW:
146
DrawColumnShadow(mw, win, row, column, x, y, width, height,
147
mw->manager.top_shadow_GC,
148
mw->manager.bottom_shadow_GC);
150
case XmGRID_COLUMN_LINE:
151
DrawColumnShadow(mw, win, row, column, x, y, width, height,
152
mw->matrix.grid_line_gc, mw->matrix.grid_line_gc);
154
case XmGRID_CELL_LINE:
155
DRAW_SHADOW(XtDisplay(mw), win,
156
mw->matrix.grid_line_gc,
157
mw->matrix.grid_line_gc,
158
mw->matrix.cell_shadow_thickness,
159
x, y, width, height, shadow);
161
case XmGRID_CELL_SHADOW:
162
DRAW_SHADOW(XtDisplay(mw), win,
163
mw->manager.top_shadow_GC,
164
mw->manager.bottom_shadow_GC,
165
mw->matrix.cell_shadow_thickness,
166
x, y, width, height, shadow);
169
/* Deprecated types. To be removed in next version. */
171
DRAW_SHADOW(XtDisplay(mw), win,
172
mw->matrix.grid_line_gc,
173
mw->matrix.grid_line_gc,
174
mw->matrix.cell_shadow_thickness,
175
x, y, width, height, shadow);
177
case XmGRID_SHADOW_OUT:
178
DRAW_SHADOW(XtDisplay(mw), win,
179
mw->manager.bottom_shadow_GC,
180
mw->manager.top_shadow_GC,
181
mw->matrix.cell_shadow_thickness,
182
x, y, width, height, shadow);
184
case XmGRID_SHADOW_IN:
185
DRAW_SHADOW(XtDisplay(mw), win,
186
mw->manager.top_shadow_GC,
187
mw->manager.bottom_shadow_GC,
188
mw->matrix.cell_shadow_thickness,
189
x, y, width, height, shadow);
195
#if XmVersion >= 1002
197
xbaeDrawCellHighlight(mw, win, gc, row, column, x, y, width, height, reason)
211
if (!mw->matrix.highlighted_cells) /* Just a precaution */
214
if (!mw->matrix.highlighted_cells[row][column])
215
return; /* Nothing to do! */
217
if (reason & HIGHLIGHTING_SOMETHING)
218
gc = mw->manager.highlight_GC;
220
if (IN_GRID_ROW_MODE(mw) &&
221
(reason & HighlightRow || reason & UnhighlightRow) &&
222
mw->matrix.highlighted_cells[row][column] == HighlightRow)
223
DrawRowHighlight(mw, win, gc, row, column, x, y, width, height,
225
else if (IN_GRID_COLUMN_MODE(mw) &&
226
(reason & HighlightColumn || reason & UnhighlightColumn) &&
227
mw->matrix.highlighted_cells[row][column] == HighlightColumn)
228
DrawColumnHighlight(mw, win, gc, row, column, x, y, width, height,
232
thick = (2 * mw->matrix.cell_shadow_thickness);
234
DRAW_HIGHLIGHT(XtDisplay(mw), win, gc,
235
x + mw->matrix.cell_shadow_thickness,
236
y + mw->matrix.cell_shadow_thickness,
237
width - thick, height - thick,
238
mw->matrix.cell_highlight_thickness,
244
DrawRowHighlight(mw, win, gc, row, column, x, y, width, height, reason)
260
rect[0].width = width;
261
rect[0].height = height;
263
XSetClipRectangles(XtDisplay(mw), gc, x, y, rect, 1, Unsorted);
265
y += mw->matrix.cell_shadow_thickness;
266
height -= 2 * mw->matrix.cell_shadow_thickness;
268
if (column != mw->matrix.columns - 1)
271
x -= (mw->matrix.cell_shadow_thickness +
272
mw->matrix.cell_highlight_thickness);
274
x += mw->matrix.cell_shadow_thickness;
275
DRAW_HIGHLIGHT(XtDisplay(mw), win, gc, x, y, mw->core.width, height,
276
mw->matrix.cell_highlight_thickness,
281
if (NEED_HORIZ_FILL(mw))
282
width = mw->core.width;
284
x -= (mw->matrix.cell_shadow_thickness +
285
mw->matrix.cell_highlight_thickness);
286
width += mw->matrix.cell_highlight_thickness;
288
DRAW_HIGHLIGHT(XtDisplay(mw), win, gc, x, y, width,
289
height, mw->matrix.cell_highlight_thickness,
292
if (NEED_HORIZ_FILL(mw))
296
xbaeCalcHorizFill(mw, win, x, y, row, column, &ax, &ay,
298
rect[0].width = width;
299
rect[0].height = height;
300
XSetClipRectangles(XtDisplay(mw), gc, ax, ay, rect, 1,
302
height -= mw->matrix.cell_shadow_thickness * 2;
303
ax -= mw->matrix.cell_highlight_thickness;
304
width += (mw->matrix.cell_highlight_thickness -
305
mw->matrix.cell_shadow_thickness);
307
DRAW_HIGHLIGHT(XtDisplay(mw), XtWindow(mw), gc, ax, ay,
309
mw->matrix.cell_highlight_thickness,
313
XSetClipMask(XtDisplay(mw), gc, None);
317
DrawColumnHighlight(mw, win, gc, row, column, x, y, width, height, reason)
330
int vert_dead_space_height = VERT_DEAD_SPACE_HEIGHT(mw);
331
int clip_vert_visible_space = CLIP_VERT_VISIBLE_SPACE(mw);
332
int vert_sb_height = VERT_SB_HEIGHT(mw);
333
Boolean need_vert_dead_space_fill = NEED_VERT_DEAD_SPACE_FILL(mw);
335
/* This adjustment takes care of that little open area
336
* between the last nonfixed row and the first trailing
337
* fixed row when the matrix is smaller than its max height */
338
if ((vert_dead_space_height == 0) &&
339
((TRAILING_VERT_ORIGIN(mw) - 1) == row) &&
340
(vert_sb_height < clip_vert_visible_space))
341
height += (mw->matrix.cell_shadow_thickness +
342
clip_vert_visible_space - vert_sb_height);
346
rect[0].width = width;
347
rect[0].height = height;
349
XSetClipRectangles(XtDisplay(mw), gc, x, y, rect, 1, Unsorted);
351
x += mw->matrix.cell_shadow_thickness;
352
width -= 2 * mw->matrix.cell_shadow_thickness;
354
if (row != mw->matrix.rows - 1)
357
y -= (mw->matrix.cell_shadow_thickness +
358
mw->matrix.cell_highlight_thickness);
360
y += mw->matrix.cell_shadow_thickness;
361
DRAW_HIGHLIGHT(XtDisplay(mw), win, gc, x, y, width, mw->core.height,
362
mw->matrix.cell_highlight_thickness,
367
if (NEED_VERT_FILL(mw) && (! HAS_ATTACHED_TRAILING_ROWS(mw)))
368
height = mw->core.height;
370
height += mw->matrix.cell_highlight_thickness;
372
y -= (mw->matrix.cell_shadow_thickness +
373
mw->matrix.cell_highlight_thickness);
375
DRAW_HIGHLIGHT(XtDisplay(mw), win, gc, x, y, width,
376
height, mw->matrix.cell_highlight_thickness,
379
if (NEED_VERT_FILL(mw) || need_vert_dead_space_fill)
383
xbaeCalcVertFill(mw, win, x, y, row, column, &ax, &ay,
386
/* If we're filling the dead space, then we only use
387
* the width and ax from above call. */
388
if (need_vert_dead_space_fill)
390
ay = UNATTACHED_TRAILING_ROWS_OFFSET(mw);
391
height = mw->matrix.cell_shadow_thickness +
392
mw->matrix.cell_highlight_thickness +
393
vert_dead_space_height;
396
rect[0].width = width;
397
rect[0].height = height;
398
XSetClipRectangles(XtDisplay(mw), gc, ax, ay, rect, 1,
400
width -= mw->matrix.cell_shadow_thickness * 2;
401
ay -= mw->matrix.cell_highlight_thickness;
402
height += (mw->matrix.cell_highlight_thickness -
403
mw->matrix.cell_shadow_thickness);
405
/* Make sure height extends past bottom clip */
406
if (need_vert_dead_space_fill && IS_FIXED_COLUMN(mw, column))
407
height += (mw->matrix.cell_shadow_thickness +
408
mw->matrix.cell_highlight_thickness);
410
DRAW_HIGHLIGHT(XtDisplay(mw), XtWindow(mw), gc, ax, ay,
412
mw->matrix.cell_highlight_thickness,
416
XSetClipMask(XtDisplay(mw), gc, None);
422
DrawRowShadow(mw, win, row, column, x, y, width, height, topGC, bottomGC)
435
unsigned char shadow = mw->matrix.row_shadow_types ?
436
mw->matrix.row_shadow_types[row] : mw->matrix.cell_shadow_type;
440
rect[0].width = width;
441
rect[0].height = height;
444
* Set up the clipping rectangle to be only over the current cell
446
XSetClipRectangles(XtDisplay(mw),
448
x, y, rect, 1, Unsorted);
449
if (topGC != bottomGC)
450
XSetClipRectangles(XtDisplay(mw),
452
x, y, rect, 1, Unsorted);
454
* Now, convert our coordinates to what we need to draw
456
if (column != mw->matrix.columns - 1)
459
* If column is 0, then we need to show the left hand side of the
460
* box, otherwise just draw the edges outside the clipping rectangle
462
width = mw->core.width;
464
x -= mw->matrix.cell_shadow_thickness;
466
DRAW_SHADOW(XtDisplay(mw), win,
468
mw->matrix.cell_shadow_thickness,
469
x, y, width, height, shadow);
473
if (NEED_HORIZ_FILL(mw))
475
* If we are going to fill, the right hand side of the shadow
476
* shouldn't be drawn - we'll do it later!
478
width = mw->core.width;
480
width += mw->matrix.cell_shadow_thickness;
482
DRAW_SHADOW(XtDisplay(mw), win,
484
mw->matrix.cell_shadow_thickness,
485
x - mw->matrix.cell_shadow_thickness, y, width,
488
if (NEED_HORIZ_FILL(mw))
491
* The filled part is drawn on the matrix's window so we need to
492
* do a bit of extra work.
496
xbaeCalcHorizFill(mw, win, x, y, row, column, &ax, &ay,
499
rect[0].width = width;
500
rect[0].height = height;
502
XSetClipRectangles(XtDisplay(mw),
504
ax, ay, rect, 1, Unsorted);
505
if (topGC != bottomGC)
506
XSetClipRectangles(XtDisplay(mw),
508
ax, ay, rect, 1, Unsorted);
511
* Final tweaks. Note that these _cannot_ be part of the calc
512
* horiz fill logic, since that is used to set the clipping
516
if ((win == XtWindow(ClipChild(mw))) &&
517
(height != ROW_HEIGHT(mw)))
519
if (height == (ClipChild(mw)->core.height +
520
ClipChild(mw)->core.y - ay))
521
height += mw->matrix.cell_shadow_thickness;
523
if (ay == ClipChild(mw)->core.y)
525
height += mw->matrix.cell_shadow_thickness;
526
ay -= mw->matrix.cell_shadow_thickness;
530
/* Do same check for RightClip. Now, why this is even
531
* necessary when we're drawing on the Matrix's window,
532
* I dunno. This one is only necessary when
533
* we've got trailing fixed columns. */
534
if (mw->matrix.trailing_fixed_columns &&
535
(win == XtWindow(RightClip(mw))) &&
536
(height != ROW_HEIGHT(mw)))
538
if (height == (RightClip(mw)->core.height +
539
RightClip(mw)->core.y - ay))
540
height += mw->matrix.cell_shadow_thickness;
542
if (ay == RightClip(mw)->core.y)
544
height += mw->matrix.cell_shadow_thickness;
545
ay -= mw->matrix.cell_shadow_thickness;
550
* Draw the remaining shadow directly onto the matrix window
552
DRAW_SHADOW(XtDisplay(mw), XtWindow(mw),
554
mw->matrix.cell_shadow_thickness,
555
ax - mw->matrix.cell_shadow_thickness,
556
ay, width + mw->matrix.cell_shadow_thickness,
561
* Reset our GC's clip mask
563
XSetClipMask(XtDisplay(mw), topGC,
565
if (topGC != bottomGC)
566
XSetClipMask(XtDisplay(mw), bottomGC,
571
DrawColumnShadow(mw, win, row, column, x, y, width, height, topGC, bottomGC)
584
unsigned char shadow = mw->matrix.column_shadow_types ?
585
mw->matrix.column_shadow_types[column] : mw->matrix.cell_shadow_type;
586
int vert_dead_space_height = VERT_DEAD_SPACE_HEIGHT(mw);
587
int clip_vert_visible_space = CLIP_VERT_VISIBLE_SPACE(mw);
588
int vert_sb_height = VERT_SB_HEIGHT(mw);
589
Boolean need_vert_dead_space_fill = NEED_VERT_DEAD_SPACE_FILL(mw);
591
/* This adjustment takes care of that little open area
592
* between the last nonfixed row and the first trailing
593
* fixed row when the matrix is smaller than its max height */
594
if ((vert_dead_space_height == 0) &&
595
((TRAILING_VERT_ORIGIN(mw) - 1) == row) &&
596
(vert_sb_height < clip_vert_visible_space))
597
height += (mw->matrix.cell_shadow_thickness +
598
clip_vert_visible_space - vert_sb_height);
602
rect[0].width = width;
603
rect[0].height = height;
606
* Set up the clipping rectangle to be only over the current cell
608
XSetClipRectangles(XtDisplay(mw),
610
x, y, rect, 1, Unsorted);
611
if (topGC != bottomGC)
612
XSetClipRectangles(XtDisplay(mw),
614
x, y, rect, 1, Unsorted);
616
* Now, convert our coordinates to what we need to draw
618
if (row != mw->matrix.rows - 1)
621
* If column is 0, then we need to show the left hand side of the
622
* box, otherwise just draw the edges outside the clipping rectangle
624
height = mw->core.height;
626
y -= mw->matrix.cell_shadow_thickness;
628
DRAW_SHADOW(XtDisplay(mw), win,
630
mw->matrix.cell_shadow_thickness,
631
x, y, width, height, shadow);
635
if (NEED_VERT_FILL(mw) && (! HAS_ATTACHED_TRAILING_ROWS(mw)))
637
* If we are going to fill, the bottom of the shadow
640
height = mw->core.height;
642
height += mw->matrix.cell_shadow_thickness;
644
DRAW_SHADOW(XtDisplay(mw), win,
646
mw->matrix.cell_shadow_thickness,
647
x, y - mw->matrix.cell_shadow_thickness,
648
width, height, shadow);
651
* The filled part is drawn on the matrix's window so we need to
652
* do a bit of extra work. We may need to fill either the entire
653
* bottom portion of the matrix, or the dead space, that is, the
654
* space between the last nonfixed row and the first trailing
655
* fixed row. We only need to do the latter case when we've got
656
* bottom attached trailing fixed rows with vertical dead space
657
* (vertical dead space only occurs when the matrix is bigger
658
* than its maximum height, i.e., we're filling).
660
if (NEED_VERT_FILL(mw) || need_vert_dead_space_fill)
664
xbaeCalcVertFill(mw, win, x, y, row, column, &ax, &ay,
667
/* If we're filling the dead space, then we only use
668
* the width and ax from above call. */
669
if (need_vert_dead_space_fill)
671
ay = UNATTACHED_TRAILING_ROWS_OFFSET(mw);
672
height = mw->matrix.cell_shadow_thickness +
673
vert_dead_space_height;
676
rect[0].width = width;
677
rect[0].height = height;
679
XSetClipRectangles(XtDisplay(mw),
681
ax, ay, rect, 1, Unsorted);
682
if (topGC != bottomGC)
683
XSetClipRectangles(XtDisplay(mw),
685
ax, ay, rect, 1, Unsorted);
688
* Final tweaks. Note that these _cannot_ be part of the
689
* calc vert fill logic, since that is used to set the
693
if ((win == XtWindow(ClipChild(mw))) &&
694
(width != COLUMN_WIDTH(mw, column)))
696
/* Make sure we don't draw a shadow along the matrix's
697
* shadow by extending our width past the edge of the
700
if (width == (ClipChild(mw)->core.width +
701
ClipChild(mw)->core.x - ax))
702
width += mw->matrix.cell_shadow_thickness;
705
* Make sure the shadow doesn't get drawn along the left
706
* side by moving the x pos outside the clipping
709
if (ax == ClipChild(mw)->core.x)
711
width += mw->matrix.cell_shadow_thickness;
712
ax -= mw->matrix.cell_shadow_thickness;
717
* Do same check for BottomClip. Now, why this is even
718
* necessary when we're drawing on the Matrix's window,
719
* I dunno. This one is only necessary when we've got
720
* trailing fixed rows.
722
if (mw->matrix.trailing_fixed_rows &&
723
(win == XtWindow(BottomClip(mw))) &&
724
(width != COLUMN_WIDTH(mw, column)))
726
if (width == (BottomClip(mw)->core.width +
727
BottomClip(mw)->core.x - ax))
728
width += mw->matrix.cell_shadow_thickness;
730
if (ax == BottomClip(mw)->core.x)
732
width += mw->matrix.cell_shadow_thickness;
733
ax -= mw->matrix.cell_shadow_thickness;
737
/* Make sure height extends past bottom clip */
738
if (need_vert_dead_space_fill && IS_FIXED_COLUMN(mw, column))
739
height += mw->matrix.cell_shadow_thickness;
742
* Draw the remaining shadow directly onto the matrix window
744
DRAW_SHADOW(XtDisplay(mw), XtWindow(mw),
746
mw->matrix.cell_shadow_thickness,
747
ax, ay - mw->matrix.cell_shadow_thickness,
748
width, height + mw->matrix.cell_shadow_thickness,
754
* Reset our GC's clip mask
756
XSetClipMask(XtDisplay(mw), topGC,
758
if (topGC != bottomGC)
759
XSetClipMask(XtDisplay(mw), bottomGC,