OSDN Git Service

イニシャルコミット。
[marathon/ShapeFusion.git] / Shapes / FrameView.cpp
1 /*
2  * This file is part of ShapeFusion (Copyright 2000 Tito Dal Canton)
3  *
4  * ShapeFusion is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * ShapeFusion is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with ShapeFusion; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 #include "wx/image.h"
19 #include "FrameView.h"
20 #include "utilities.h"
21
22 DEFINE_EVENT_TYPE(wxEVT_FRAMEVIEW_DRAG)
23
24 BEGIN_EVENT_TABLE(FrameView, wxScrolledWindow)
25         EVT_PAINT(FrameView::OnPaint)
26         EVT_LEFT_DOWN(FrameView::OnDrag)
27         EVT_LEFT_UP(FrameView::OnDrag)
28         EVT_MOTION(FrameView::OnDrag)
29         EVT_SIZE(FrameView::OnSize)
30 END_EVENT_TABLE()
31
32 FrameView::FrameView(wxWindow *parent, wxWindowID id):
33         wxScrolledWindow(parent, id, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER | wxFULL_REPAINT_ON_RESIZE),
34         mFrame(NULL), mEncBmp(NULL), mColorTable(NULL), mPanning(false), mDraggingOrigin(false), mDraggingKey(false), mNearOrigin(false), mNearKey(false)
35 {
36         SetBackgroundColour(wxColour(255, 255, 255));
37         SetScrollRate(1, 1);
38         EnableScrolling(false, false);
39         // origin cursor pen
40         mOriginPen.SetColour(0, 128, 128);
41         // key cursor pen
42         mKeypointPen.SetColour(128, 0, 128);
43         // mouse cursors
44         mPanCursor = wxCursor(wxCURSOR_ARROW);
45         mPointCursor = wxCursor(wxCURSOR_CROSS);
46         mWhiteTransparency = true;
47         mCenterOrigin = false;
48 }
49
50 void FrameView::OnPaint(wxPaintEvent& e)
51 {
52         wxPaintDC   tempdc(this);
53         int                     vw, vh, cw, ch;
54
55         GetVirtualSize(&vw, &vh);
56         DoPrepareDC(tempdc);
57         GetClientSize(&cw, &ch);
58         if (mFrame != NULL && mColorTable != NULL) {
59                 if (mEncBmp != NULL) {
60                         int     origin_x, origin_y;
61
62                         if (mCenterOrigin) {
63                                 origin_x = vw/2 - mFrame->OriginX();
64                                 origin_y = vh/2 - mFrame->OriginY();
65                         } else {
66                                 origin_x = vw/2 - mDecBmp.GetWidth()/2;
67                                 origin_y = vh/2 - mDecBmp.GetHeight()/2;
68                         }
69                         // draw bitmap
70                         tempdc.DrawBitmap(mDecBmp, origin_x, origin_y);
71                         // mark bitmap origin
72                         tempdc.SetPen(mOriginPen);
73                         tempdc.CrossHair(mFrame->OriginX() + origin_x, mFrame->OriginY() + origin_y);
74                         tempdc.DrawCircle(mFrame->OriginX() + origin_x, mFrame->OriginY() + origin_y, 2);
75                         // mark bitmap keypoint
76                         tempdc.SetPen(mKeypointPen);
77                         tempdc.CrossHair(mFrame->KeyX() + origin_x, mFrame->KeyY() + origin_y);
78                         tempdc.DrawCircle(mFrame->KeyX() + origin_x, mFrame->KeyY() + origin_y, 2);
79                         // origin & key labels
80                         wxString        origin_label = wxT("Origin"),
81                                                 key_label = wxT("Keypoint");
82                         int                     text1w, text1h, text2w, text2h;
83
84                         tempdc.SetFont(*wxSMALL_FONT);
85                         tempdc.GetTextExtent(origin_label, &text1w, &text1h);
86                         tempdc.GetTextExtent(key_label, &text2w, &text2h);
87                         tempdc.SetTextForeground(wxColour(0, 128, 128));
88                         if (mFrame->OriginY() + origin_y >= text1h + 2)
89                                 tempdc.DrawText(origin_label, vw - text1w - 2, mFrame->OriginY() + origin_y - text1h - 2);
90                         else
91                                 tempdc.DrawText(origin_label, vw - text1w - 2, mFrame->OriginY() + origin_y + 2);
92                         tempdc.SetTextForeground(wxColour(128, 0, 128));
93                         if (mFrame->KeyY() + origin_y >= text2h + 2)
94                                 tempdc.DrawText(key_label, vw - text2w - 2, mFrame->KeyY() + origin_y - text2h - 2);
95                         else
96                                 tempdc.DrawText(key_label, vw - text2w - 2, mFrame->KeyY() + origin_y + 2);
97                 } else {
98                         wxString        no_bmp_label = wxT("No associated bitmap");
99                         int                     text_w, text_h,
100                                                 origin_x = vw/2, origin_y = vh/2;
101
102                         tempdc.GetTextExtent(no_bmp_label, &text_w, &text_h);
103                         origin_x -= text_w / 2;
104                         origin_y -= text_h / 2;
105                         tempdc.SetTextForeground(wxColour(255, 0, 0));
106                         tempdc.DrawText(no_bmp_label, origin_x, origin_y);
107                 }
108         }
109 }
110
111 // handle mouse drag (pan view, edit origin/keypoint)
112 void FrameView::OnDrag(wxMouseEvent &e)
113 {
114         if (mFrame == NULL || mEncBmp == NULL || mCenterOrigin)
115                 return;
116
117         if (e.ButtonDown()) {
118                 int scroll_x, scroll_y;
119
120                 GetViewStart(&scroll_x, &scroll_y);
121                 if (mNearOrigin) {
122                         // start dragging origin
123                         mDraggingOrigin = true;
124                 } else if (mNearKey) {
125                         // start dragging keypoint
126                         mDraggingKey = true;
127                 } else {
128                         // start panning
129                         mPanning = true;
130                         mDragStartX = e.GetPosition().x + scroll_x;
131                         mDragStartY = e.GetPosition().y + scroll_y;
132                 }
133         } else if (e.Dragging()) {
134                 if (mPanning) {
135                         // pan
136                         int     dx = mDragStartX - e.GetPosition().x,
137                                 dy = mDragStartY - e.GetPosition().y;
138
139                         Scroll(dx, dy);
140                 } else if (mDraggingOrigin) {
141                         // set origin
142                         int     vw, vh, scroll_x, scroll_y, origin_x, origin_y;
143
144                         GetVirtualSize(&vw, &vh);
145                         GetViewStart(&scroll_x, &scroll_y);
146                         origin_x = vw/2 - mDecBmp.GetWidth()/2;
147                         origin_y = vh/2 - mDecBmp.GetHeight()/2;
148                         mFrame->SetOriginX(e.GetPosition().x + scroll_x - origin_x);
149                         mFrame->SetOriginY(e.GetPosition().y + scroll_y - origin_y);
150                         // send an event so that other gui elements can update
151                         wxCommandEvent  event(wxEVT_FRAMEVIEW_DRAG, GetId());
152
153                         event.SetEventObject(this);
154                         //event.SetInt(j);
155                         GetEventHandler()->ProcessEvent(event);
156                         Refresh();
157                 } else if (mDraggingKey) {
158                         // set keypoint
159                         int vw, vh, scroll_x, scroll_y, origin_x, origin_y;
160
161                         GetVirtualSize(&vw, &vh);
162                         GetViewStart(&scroll_x, &scroll_y);
163                         origin_x = vw/2 - mDecBmp.GetWidth()/2;
164                         origin_y = vh/2 - mDecBmp.GetHeight()/2;
165                         mFrame->SetKeyX(e.GetPosition().x + scroll_x - origin_x);
166                         mFrame->SetKeyY(e.GetPosition().y + scroll_y - origin_y);
167                         // send an event so that other gui elements can update
168                         wxCommandEvent  event(wxEVT_FRAMEVIEW_DRAG, GetId());
169
170                         event.SetEventObject(this);
171                         //event.SetInt(j);
172                         GetEventHandler()->ProcessEvent(event);
173                         Refresh();
174                 }
175         } else if (e.ButtonUp()) {
176                 mPanning = mDraggingOrigin = mDraggingKey = false;
177         } else if (e.Moving()) {
178                 // mouse moved without buttons
179                 int     vw, vh, scroll_x, scroll_y;
180
181                 GetVirtualSize(&vw, &vh);
182                 GetViewStart(&scroll_x, &scroll_y);
183
184                 int origin_x = vw/2 - mDecBmp.GetWidth()/2,
185                         origin_y = vh/2 - mDecBmp.GetHeight()/2,
186                         x = e.GetPosition().x + scroll_x,
187                         y = e.GetPosition().y + scroll_y,
188                         delta_x,
189                         delta_y,
190                         dist_origin,
191                         dist_keypoint;
192
193                 delta_x = x - (mFrame->OriginX() + origin_x);
194                 delta_y = y - (mFrame->OriginY() + origin_y);
195                 dist_origin = delta_x*delta_x + delta_y*delta_y;
196                 delta_x = x - (mFrame->KeyX() + origin_x);
197                 delta_y = y - (mFrame->KeyY() + origin_y);
198                 dist_keypoint = delta_x*delta_x + delta_y*delta_y;
199                 // are we near origin or keypoint?
200                 if (dist_origin < 25) {
201                         SetCursor(mPointCursor);
202                         mNearOrigin = true;
203                         mNearKey = false;
204                 } else if (dist_keypoint < 25) {
205                         SetCursor(mPointCursor);
206                         mNearOrigin = false;
207                         mNearKey = true;
208                 } else {
209                         SetCursor(mPanCursor);
210                         mNearOrigin = mNearKey = false;
211                 }
212         }
213 }
214
215 void FrameView::OnSize(wxSizeEvent &e)
216 {
217         int cw, ch,
218                 vw = (mFrame == NULL || mEncBmp == NULL || mCenterOrigin) ? 0 : mEncBmp->Width(),
219                 vh = (mFrame == NULL || mEncBmp == NULL || mCenterOrigin) ? 0 : mEncBmp->Height();
220
221         GetClientSize(&cw, &ch);
222         if (mEncBmp != NULL && mEncBmp->Pixels() != NULL) {
223                 if (vw < cw)
224                         vw = cw;
225                 if (vh < ch)
226                         vh = ch;
227         } else {
228                 vw = cw;
229                 vh = ch;
230         }
231         SetVirtualSize(vw, vh);
232 }
233
234 void FrameView::SetTranspPixelsDisplay(bool show)
235 {
236         mWhiteTransparency = show;
237         SetBitmap(mEncBmp);
238         Refresh();
239 }
240
241 void FrameView::SetCenterOrigin(bool center)
242 {
243         mCenterOrigin = center;
244         SetBitmap(mEncBmp);
245         Refresh();
246 }
247
248 // associate a frame
249 void FrameView::SetFrame(ShapesFrame *fp)
250 {
251         mFrame = fp;
252         SetBitmap(mEncBmp);
253         Refresh();
254 }
255
256 ShapesFrame *FrameView::GetFrame(void) const
257 {
258         return mFrame;
259 }
260
261 // associate a bitmap to display (we could do this in SetFrame
262 // but we would need a pointer to the original Shapes object)
263 void FrameView::SetBitmap(ShapesBitmap *bp)
264 {
265         int     cw, ch;
266
267         GetClientSize(&cw, &ch);
268         mEncBmp = bp;
269         if (bp != NULL) {
270                 if (bp->Pixels() != NULL) {
271                         if (mCenterOrigin) {
272                                 // no scrolling
273                                 SetVirtualSize(cw, ch);
274                         } else {
275                                 // adjust sizes to make scrolling work
276                                 int     vw = mEncBmp->Width(),
277                                         vh = mEncBmp->Height();
278
279                                 if (vw < cw)
280                                         vw = cw;
281                                 if (vh < ch)
282                                         vh = ch;
283                                 SetVirtualSize(vw, vh);
284                         }
285                         // decode bitmap
286                         if (mColorTable != NULL) {
287                                 wxImage img = ShapesBitmapToImage(bp, mColorTable, mWhiteTransparency);
288
289                                 // apply transformations
290                                 if (mFrame) {
291                                         if (mFrame->IsXmirrored())
292                                                 img = img.Mirror(true);
293                                         if (mFrame->IsYmirrored())
294                                                 img = img.Mirror(false);
295                                 }
296                                 mDecBmp = wxBitmap(img);
297                         }
298                         Refresh();
299                 } else {
300                         wxLogError(wxT("[FrameView] Added a bitmap with NULL pixels"));
301                         SetVirtualSize(cw, ch);
302                 }
303         } else {
304                 SetVirtualSize(cw, ch);
305         }
306 }
307
308 // call this before Set'tingBitmap!
309 void FrameView::SetColorTable(ShapesColorTable *ct)
310 {
311         mColorTable = ct;
312         SetBitmap(mEncBmp);
313         Refresh();
314 }
315