]> Shamusworld >> Repos - apple2/blob - src/gui/draggablewindow.cpp
Moved stuff into trunk (part 2)...
[apple2] / src / gui / draggablewindow.cpp
1 //
2 // DRAGGABLEWINDOW.CPP
3 //
4 // Graphical User Interface draggable window class
5 // by James L. Hammons
6 //
7 // JLH = James L. Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  03/01/2006  Created this file
12 //
13 // STILL TO DO:
14 //
15 // - Check for parent's extents and clip movement against those extents
16 //
17
18 #include "draggablewindow.h"
19 #include "button.h"
20 #include "guimisc.h"                                                            // Various support functions
21 #include <algorithm>
22
23 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
24 #define MASK_R 0xFF000000
25 #define MASK_G 0x00FF0000
26 #define MASK_B 0x0000FF00
27 #define MASK_A 0x000000FF
28 #else
29 #define MASK_R 0x000000FF
30 #define MASK_G 0x0000FF00
31 #define MASK_B 0x00FF0000
32 #define MASK_A 0xFF000000
33 #endif
34
35 #define BACKGROUND_IMG_TEST
36 //#define USE_COVERAGE_LISTS
37
38 //
39 // DraggableWindow class implementation
40 //
41 // NOTE: FG/BG colors are hard-wired
42 //
43
44 DraggableWindow::DraggableWindow(uint32 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 h/*= 0*/,
45         void (* f)(Element *)/*= NULL*/):
46         Element(x, y, w, h, 0x4D, 0xFF, 0x84, 0xFF, 0x1F, 0x84, 0x84, 0xFF), handler(f),
47         clicked(false),
48         cbWidth((closeBox[0] << 8) | closeBox[1]), cbHeight((closeBox[2] << 8) | closeBox[3]),
49         cbUp(SDL_CreateRGBSurfaceFrom(&closeBox[4], cbWidth, cbHeight, 32, cbWidth * 4,
50                 MASK_R, MASK_G, MASK_B, MASK_A)),
51         cbDown(SDL_CreateRGBSurfaceFrom(&closeBoxDown[4], cbWidth, cbHeight, 32, cbWidth * 4,
52                 MASK_R, MASK_G, MASK_B, MASK_A)),
53         cbHover(SDL_CreateRGBSurfaceFrom(&closeBoxHover[4], cbWidth, cbHeight, 32, cbWidth * 4,
54                 MASK_R, MASK_G, MASK_B, MASK_A))
55 {
56 //Could probably move this into the initializer list as well...
57         closeButton = new Button(w - (cbWidth + 1), 1, cbUp, cbHover, cbDown, this);
58         list.push_back(closeButton);
59
60 #ifdef BACKGROUND_IMG_TEST
61 uint16 imgWidth = (floppyDiskImg[0] << 8) | floppyDiskImg[1];
62 uint16 imgHeight = (floppyDiskImg[2] << 8) | floppyDiskImg[3];
63 img = SDL_CreateRGBSurfaceFrom(&floppyDiskImg[4], imgWidth, imgHeight, 32, imgWidth * 4,
64         MASK_R, MASK_G, MASK_B, MASK_A);
65 #endif
66
67         CreateBackstore();
68         Draw(); // Can we do this in the constructor??? Mebbe.
69 }
70
71 DraggableWindow::~DraggableWindow()
72 {
73         for(uint32 i=0; i<list.size(); i++)
74                 if (list[i])
75                         delete list[i];
76
77 #ifdef BACKGROUND_IMG_TEST
78 SDL_FreeSurface(img);
79 #endif
80
81         SDL_FreeSurface(cbUp);
82         SDL_FreeSurface(cbDown);
83         SDL_FreeSurface(cbHover);
84 }
85
86 void DraggableWindow::HandleKey(SDLKey key)
87 {
88         if (key == SDLK_ESCAPE)
89         {
90                 SDL_Event event;
91                 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
92                 SDL_PushEvent(&event);
93         }
94
95         // Handle the items this window contains...
96         for(uint32 i=0; i<list.size(); i++)
97                 list[i]->HandleKey(key);
98 }
99
100 void DraggableWindow::HandleMouseMove(uint32 x, uint32 y)
101 {
102         if (clicked)
103         {
104 //Need to check whether or not we've run into the extents of the screen... !!! FIX !!!
105                 RestoreScreenFromBackstore();
106                 extents.x = x - offset.x;
107                 extents.y = y - offset.y;
108                 SDL_BlitSurface(screen, &extents, backstore, NULL);
109                 Draw();
110
111                 return;
112         }
113
114         // Handle the items this window contains...
115         for(uint32 i=0; i<list.size(); i++)
116                 // Make coords relative to upper right corner of this window...
117                 list[i]->HandleMouseMove(x - extents.x, y - extents.y);
118 }
119
120 void DraggableWindow::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
121 {
122         clicked = false;
123
124         if (mouseDown && Inside(x, y))
125         {
126                 clicked = true;
127                 offset.x = x - extents.x;
128                 offset.y = y - extents.y;
129         }
130
131         // Handle the items this window contains...
132         for(uint32 i=0; i<list.size(); i++)
133         {
134                 // Make coords relative to upper right corner of this window...
135                 list[i]->HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
136
137                 if (list[i]->Inside(x - extents.x, y - extents.y))
138                         clicked = false;
139         }
140 }
141
142 void DraggableWindow::Draw(void)
143 {
144 #ifdef USE_COVERAGE_LISTS
145         // These are *always* top level and parentless, so no need to traverse up through
146         // the parent chain...
147         for(std::list<SDL_Rect>::iterator i=coverList.begin(); i!=coverList.end(); i++)
148                 SDL_FillRect(screen, &(*i), bgColor);
149
150         // Handle the items this window contains...
151         for(uint32 i=0; i<list.size(); i++)
152                 list[i]->Draw();
153 #else
154         // These are *always* top level and parentless, so no need to traverse up through
155         // the parent chain...
156 //Perhaps we can make these parentable, put the parent traversal in the base class?
157 //Prolly.
158 #ifdef BACKGROUND_IMG_TEST
159         SDL_Rect src, dst;
160         src.x = 0, src.y = 0, src.w = extents.w, src.h = extents.h;
161         dst.x = extents.x, dst.y = extents.y;
162         SDL_BlitSurface(img, &src, screen, &dst);
163
164         extern char textChar2e[];
165         uint8 * fontAddr = (uint8 *)textChar2e + ((128 + 32) * 7 * 8);
166         SetNewFont(Font(fontAddr, 7, 8));
167         DrawStringOpaque(screen, extents.x + 8, extents.y +  6, 0xFF000000, 0xFFFFFFFF, "Ultima III - Boo");
168         DrawStringOpaque(screen, extents.x + 8, extents.y + 14, 0xFF000000, 0xFFFFFFFF, "0123456789012345");
169         DrawStringOpaque(screen, extents.x + 8, extents.y + 22, 0xFF000000, 0xFFFFFFFF, "1234567890123456");
170         DrawStringOpaque(screen, extents.x + 8, extents.y + 30, 0xFF000000, 0xFFFFFFFF, "2345678901234567");
171         RestoreOldFont();
172 #else
173         SDL_FillRect(screen, &extents, bgColor);
174 #endif
175
176         // Handle the items this window contains...
177         for(uint32 i=0; i<list.size(); i++)
178                 list[i]->Draw();
179 #endif
180
181 //Prolly don't need this since the close button will do this for us...
182         needToRefreshScreen = true;
183 }
184
185 void DraggableWindow::Notify(Element * e)
186 {
187         if (e == closeButton)
188         {
189                 SDL_Event event;
190                 event.type = SDL_USEREVENT, event.user.code = WINDOW_CLOSE;
191                 SDL_PushEvent(&event);
192         }
193 }
194
195 void DraggableWindow::AddElement(Element * e)
196 {
197         list.push_back(e);
198 }