2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 ViewMan* ViewMan::instance = NULL;
39 ViewMan* ViewMan::getInstance()
46 if (initted) return 0;
51 int ViewMan::shutdown()
53 if (!initted) return 0;
55 // FIXME don't think this can work properly, removeAll leaves the wallpaper there!
62 int ViewMan::add(View* v)
64 if (!initted) return 0;
65 if (numViews == 16) return 0;
67 views[numViews++] = v;
72 // ---------------------------------------------------- REMOVE CODE
74 int ViewMan::removeView(View* toDelete)
76 if (!initted) return 0;
77 if (numViews == 0) return 0;
79 // Log::getInstance()->log("ViewMan", Log::DEBUG, "entering remove, numViews=%i", numViews);
85 toDelete = views[numViews-1];
90 // to be deleted view is more likely to be at the top
91 for (i = numViews-1; i >= 0; i--)
93 // Log::getInstance()->log("ViewMan", Log::DEBUG, "todel: %p, i=%i, views[i]=%p", toDelete, i, views[i]);
94 if (views[i] == toDelete) break;
99 // not a View we have!
104 // Log::getInstance()->log("ViewMan", Log::DEBUG, "Starting deleteView");
106 // Log::getInstance()->log("ViewMan", Log::DEBUG, "Done deleteView");
108 // Shift the views on top down one
110 for(int j = i; j < numViews; j++) views[j] = views[j+1];
115 // If there is only the wallpaper left signal command
118 Message* m = new Message();
119 m->to = Command::getInstance();
120 m->message = Message::LAST_VIEW_CLOSE;
121 Command::getInstance()->postMessageNoLock(m);
127 /////////////////////////////////////////////////////////////////////////////
129 /////////////////////////////////////////////////////////////////////////////
131 void ViewMan::deleteView(int z)
133 // Log::getInstance()->log("ViewMan", Log::DEBUG, "Delete view %i of %i", z, numViews);
135 boxSplit(views[z]->area, z + 1, numViews, 1, rl);
138 repaintRevealed(z, rl.front());
143 void ViewMan::updateView(View* toUpdate, Region* regionToUpdate)
145 // Log::getInstance()->log("ViewMan", Log::DEBUG, "UpdateView called");
146 // Get the z index of the view
149 for (z = 0; z < numViews; z++)
151 if (views[z] == toUpdate) break;
156 // not a View we have!
160 // get the region for the whole view, could be less than that
161 // for smaller updates
163 Region r = views[z]->area;
167 // Can be null if the whole view should be updated
168 // If this is given the numbers are relative to the size of the view, not the screen
170 r.x += regionToUpdate->x;
171 r.y += regionToUpdate->y;
172 r.w = regionToUpdate->w;
173 r.h = regionToUpdate->h;
179 boxSplit(r, z+1, numViews, 1, rl);
189 void ViewMan::repaintRevealed(int x, Region r)
192 boxSplit(r, x - 1, -1, -1, rl);
198 views[r2.z]->blt(r2);
203 void ViewMan::boxSplit(Region r, int start, int end, int direction, RegionList& rl)
205 // printf("Y= S=%i E=%i D=%i: Boxsplit: %i %i %i %i\n", start, end, direction, r.x, r.y, r.w, r.h);
207 for(int z = start; z != end; z += direction)
209 if (r.overlappedBy(views[z]->area))
211 // printf("Z=%i S=%i E=%i D=%i: %i overlaps\n", z, start, end, direction, z);
216 if (views[z]->area.y > r.y)
218 // printf("Z=%i S=%i E=%i D=%i: Case 1 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, views[z]->area.x, views[z]->area.y, views[z]->area.w, views[z]->area.h);
219 top = views[z]->area.y;
224 newR.h = views[z]->area.y - r.y;
225 boxSplit(newR, z + direction, end, direction, rl);
231 newR2.y = views[z]->area.y;
233 newR2.h = r.h - newR.h;
234 boxSplit(newR2, z, end, -1, rl);
239 if (views[z]->area.y2() < r.y2())
241 // printf("Z=%i S=%i E=%i D=%i: Case 2 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, views[z]->area.x, views[z]->area.y, views[z]->area.w, views[z]->area.h);
242 btm = views[z]->area.y2();
245 newR.y = views[z]->area.y2() + 1;
247 newR.h = r.y2() - newR.y + 1;
248 boxSplit(newR, z + direction, end, direction, rl);
256 newR2.h = r.h - newR.h;
257 boxSplit(newR2, z, end, -1, rl);
262 if (views[z]->area.x > r.x)
264 // printf("Z=%i S=%i E=%i D=%i: Case 3 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, views[z]->area.x, views[z]->area.y, views[z]->area.w, views[z]->area.h);
268 newR.w = views[z]->area.x - r.x;
269 newR.h = btm - top + 1;
270 boxSplit(newR, z + direction, end, direction, rl);
275 newR2.x = r.x + newR.w;
277 newR2.w = r.w - newR.w;
279 boxSplit(newR2, z, end, -1, rl);
284 if (views[z]->area.x2() < r.x2())
286 // printf("Z=%i S=%i E=%i D=%i: Case 4 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, views[z]->area.x, views[z]->area.y, views[z]->area.w, views[z]->area.h);
288 newR.x = views[z]->area.x2() + 1;
290 newR.w = r.x2() - newR.x + 1;
291 newR.h = btm - top + 1;
292 boxSplit(newR, z + direction, end, direction, rl);
299 newR2.w = r.w - newR.w;
301 boxSplit(newR2, z, end, -1, rl);
308 // we are going down the stack
309 // r is underlapped by views[z]
310 // but we have not split
311 // Therefore this region under test is
312 // completely covering views[z]
314 // don't go any further down, generate a region and quit
316 // printf("Repaint region: %i %i %i %i\n", r.x, r.y, r.w, r.h);
321 // printf("Returning from Z=%i\n", z);
326 // printf("Z=%i S=%i E=%i D=%i: %i does not overlap\n", z, start, end, direction, z);
330 // if direction = 1 then we have come to a region that is
331 // entirely clear of higher views and needs to be redrawn
333 // if direction = -1 then we have come to a region that is on
334 // the very bottom with nothing below it to repaint.
335 // do nothing. stale window data will be left on screen?
343 /////////////////////////////////////////////////////////////////////////////
345 /////////////////////////////////////////////////////////////////////////////
347 // ---------------------------------------------------- END OF REMOVE CODE
350 void ViewMan::removeAll()
352 // 1.. Don't delete wallpaper. No point.
353 for (; numViews > 1; --numViews)
355 delete views[numViews-1];
359 int ViewMan::handleCommand(UCHAR command)
365 if (command != Remote::NA_NONE)
367 // handle command return values
368 // 0 - drop through to next view
369 // 1 - dont drop to next view, but not handled
370 // 2 - handled - stop command here
371 // 4 - handled - delete this view
373 for (i=numViews-1; i>=0; i--)
375 // Log::getInstance()->log("ViewMan", Log::DEBUG, "Giving command to i=%i", i);
376 retVal = views[i]->handleCommand(command);
379 // not handled but don't give to any more views
389 else if (retVal == 4)
391 // Log::getInstance()->log("ViewMan", Log::DEBUG, "Return 4: i=%i, views[i]=%p", i, views[i]);
392 removeView(views[i]);
400 // fake the return code
407 void ViewMan::processMessage(Message* m)
411 for (int i = numViews-1; i >= 0; i--)
413 if (views[i] == m->to)
415 Log::getInstance()->log("ViewMan", Log::DEBUG, "sending message from view %p to view %p %lu", m->from, m->to, m->message);
416 views[i]->processMessage(m);
423 /* Handle mouse events*/
424 // They come in with m->to = NULL? and just need to be delivered to top view?
425 if ((numViews > 1) && ((m->message == Message::MOUSE_MOVE) || (m->message == Message::MOUSE_LBDOWN)))
427 views[numViews-1]->processMessage(m);
431 Log::getInstance()->log("ViewMan", Log::DEBUG, "it's for meeee!");
435 case Message::CLOSE_ME:
437 removeView((View*)m->from);
440 case Message::ADD_VIEW: // currently not used by anything but it might come in useful again
442 View* toAdd = (View*)m->parameter;