1 /* -*- C++ -*- Time-stamp: <08 May 99 15:05:38 Michael Bischoff>
2 XQtCardPile.cpp
3 This widget displays a pile of cards (slot, stack, etc...)
4 on the tableau widget
5 */
6
7 #include "XQtCardPile.h"
8 #include "XQtCards.h"
9 #include "XQtTableau.h"
10 #include <qpainter.h>
11 #include <qpixmap.h>
12 #include <qbitmap.h>
13 #include <qevent.h>
14 #include "xpatgeo.h"
15
sizeHint() const16 QSize XQtCardPile::sizeHint() const {
17 if (special_image != -1 && pileno >= 0 && pileno < game.numpiles) {
18 struct pilegeometry *p = geo.pg + pileno;
19 return QSize(p->w, p->h);
20 } else {
21 if (geo.cw > 0 && geo.ch > 0)
22 return QSize(geo.cw, geo.ch);
23 else
24 return QSize();
25 }
26 }
27
mousePressEvent(QMouseEvent * e)28 void XQtCardPile::mousePressEvent(QMouseEvent* e) {
29 Cardindex c;
30 int mx = e->x(), my = e->y();
31 int cw = graphics->cardwidth(), ch = graphics->cardheight();
32 int button = 0;
33 // printf("mouse is pressed in CardPile %d at %d,%d\n", pileno, mx, my);
34
35 c = FindCardOfMousePos(pileno, mx, my);
36
37 switch (e->button()) {
38 case LeftButton:
39 if (c < 0)
40 return;
41 button = 1;
42 button_pressed(pileno, c, 1); // quick move
43 return;
44 case MidButton:
45 button = 2;
46 if (c == -2)
47 return;
48 button_pressed(pileno, c, 2); // select / deselect
49 if (!tabl->dragndrop_on) {
50 return; // done
51 }
52 c = game.srcind; // reached card according to rules
53 break;
54 case RightButton:
55 if (c < 0)
56 return;
57 button = 3;
58 break;
59 default:
60 return;
61 }
62
63 if (c < 0)
64 return;
65 // printf(" pressed on card with value %d\n", game.cards[c]);
66 XQtCardPile *floating = new XQtCardPile(0, tabl);
67 int i, cx, cy, top;
68 struct pilegeometry *p = geo.pg + pileno;
69 i = c - INDEX_OF_FIRST_CARD(pileno);
70 if (e->button() == MidButton)
71 // visible card = topmost card
72 top = INDEX_OF_LAST_CARD(pileno);
73 else
74 top = c;
75 cx = p->ox + i * p->cdx;
76 cy = p->oy + i * p->cdy;
77 floating->move(x() + cx, y() + cy);
78 floating->setMask(*(graphics->get_clipmap()));
79 if (game.visible[top])
80 floating->special_image = game.cards[top];
81 else
82 floating->special_image = 99;
83
84 num_to_paint = -1;
85 if (e->button() == MidButton) {
86 /* drag it */
87 num_to_paint = c - INDEX_OF_FIRST_CARD(pileno); // cards remaining to paint
88 show_mark(0);
89 repaint();
90 tabl->startDrag(floating, mx - cx, my - cy, TRUE, cx + x(), cy + y(), pileno);
91 } else {
92 /* only expose it */
93 tabl->startDrag(floating, mx - cx, my - cy, FALSE, 0, 0, -1);
94 }
95 }
96
97 /* the release event is sent to the widget which got the pressed event, not
98 to the widget where the mouse currently is over! */
mouseReleaseEvent(QMouseEvent * e)99 void XQtCardPile::mouseReleaseEvent(QMouseEvent* e) {
100 // printf("Calling startAnimate(%d,%d)\n", special_image, pileno);
101 // if (special_image >= 0) {
102 // this is the dragged card
103 // start movement with mouse coordinates
104 tabl->startAnimate(x() + e->x(), y() + e->y());
105 // }
106 }
107
mouseMoveEvent(QMouseEvent * e)108 void XQtCardPile::mouseMoveEvent(QMouseEvent* e) {
109 tabl->Drag(x() + e->x(), y() + e->y());
110 }
111
setCorrectSize()112 void XQtCardPile::setCorrectSize() {
113 struct pilegeometry *p;
114 p = geo.pg + pileno;
115 setGeometry(p->x, p->y, p->w, p->h); // take values from geo.pg[]
116 }
117
XQtCardPile(int pilenr,XQtTableau * parent,const char * name=0)118 XQtCardPile::XQtCardPile(int pilenr, XQtTableau *parent, const char *name=0)
119 : QWidget(parent, name) {
120 pileno = pilenr;
121 tabl = parent;
122 graphics = tabl->getCards();
123 num_to_paint = -1;
124 special_image = -1;
125 if (!NOT_DISPLAYED(geo.pg+pileno)) {
126 setCorrectSize();
127 setBackgroundColor(darkGreen);
128 }
129 // fprintf(stderr, "created pile %d (type %d) at %d,%d, size %d,%d\n",
130 // pileno, game.piletype[pileno], x(), y(), width(), height());
131
132 }
133
compressCards()134 void XQtCardPile::compressCards() {
135 num_to_paint = -1;
136 if (pile_resize(pileno))
137 repaint();
138 }
139
paintEvent(QPaintEvent * event)140 void XQtCardPile::paintEvent(QPaintEvent *event) {
141 QPixmap *Pixmap_to_draw = 0;
142 int xdelta, ydelta, num;
143 struct pilegeometry *p = geo.pg + pileno;
144 xdelta = p->cdx;
145 ydelta = p->cdy;
146
147 if (special_image != -1) {
148 /* floating card */
149 if (special_image == 99)
150 Pixmap_to_draw = graphics->get_pm_cardback();
151 else
152 Pixmap_to_draw = graphics->get_pm_card(special_image);
153 if (event)
154 bitBlt(this, event->rect().topLeft(), Pixmap_to_draw, event->rect());
155 else
156 bitBlt(this, 0, 0, Pixmap_to_draw, graphics->cardwidth(), graphics->cardheight(), CopyROP, FALSE);
157 return;
158 }
159 if (pileno < 0 || pileno >= game.numpiles) {
160 printf("repaint request for pile %d (pos = %d,%d, size = %d,%d)\n",
161 pileno,
162 x(), y(), width(), height());
163 return;
164 }
165 if (game.disable[pileno]) /* don't draw THIS pile */
166 return;
167 if (NOT_DISPLAYED(p))
168 return; /* draw nothing */
169
170 num = num_to_paint < 0 ? CARDS_ON_PILE(pileno) : num_to_paint;
171
172 if (!num) { /* draw empty pile */
173 switch (game.piletype[pileno]) {
174 case Stack:
175 Pixmap_to_draw = graphics->get_pm_card(SUITSYMBOL + SUIT(pileno));
176 break;
177 default:
178 Pixmap_to_draw = graphics->get_pm_empty();
179 break;
180 }
181 if (event)
182 bitBlt(this, event->rect().topLeft(), Pixmap_to_draw, event->rect());
183 else
184 bitBlt(this, 0, 0, Pixmap_to_draw, graphics->cardwidth(), graphics->cardheight(), CopyROP, FALSE);
185 } else if (!ydelta && !xdelta) { /* only topmost card is visible */
186 Cardindex c;
187 c = INDEX_OF_FIRST_CARD(pileno) + num - 1;
188 Pixmap_to_draw = game.visible[c] ? graphics->get_pm_card(game.cards[c])
189 : graphics->get_pm_cardback();
190
191 if (event)
192 bitBlt(this, event->rect().topLeft(), Pixmap_to_draw, event->rect());
193 else
194 bitBlt(this, 0, 0, Pixmap_to_draw, graphics->cardwidth(), graphics->cardheight(), CopyROP, FALSE);
195
196 } else {
197 // at least one card, painting a slot
198 int cdelta = num;
199 Cardindex c = INDEX_OF_FIRST_CARD(pileno) + num - cdelta; // the lowest one to repaint
200 int i = c - INDEX_OF_FIRST_CARD(pileno);
201
202 // fprintf(stderr, "painting pile %d (%d cards, d=%d,%d)\n",
203 // pileno, cdelta, xdelta, ydelta);
204 while (--cdelta >= 0) {
205 int pw, ph; // paint-width and height
206 // fprintf(stderr, " visible=%d at %d,%d, size %d,%d\n", game.visible[c],
207 // xdelta*i, ydelta*i, graphics->cardwidth(), graphics->cardheight());
208 Pixmap_to_draw = game.visible[c] ? graphics->get_pm_card(game.cards[c])
209 : graphics->get_pm_cardback();
210 pw = geo.cw;
211 ph = geo.ch;
212 if (cdelta) {
213 /* Not the last card. May use card clipping optimisation */
214 if (p->cdx == 0 && p->cdy > 0)
215 ph = p->cdy + geo.ry;
216 if (p->cdy == 0 && p->cdx > 0)
217 pw = p->cdx + geo.rx;
218 }
219 bitBlt(this,
220 p->ox + p->cdx*i, p->oy + p->cdy*i,
221 Pixmap_to_draw, 0, 0,
222 pw, ph, CopyROP, FALSE);
223 ++c;
224 ++i;
225 }
226 }
227 }
228