]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: samples/docview/view.cpp | |
3 | // Purpose: View classes implementation | |
4 | // Author: Julian Smart | |
5 | // Modified by: Vadim Zeitlin: merge with the MDI version and general cleanup | |
6 | // Created: 04/01/98 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 1998 Julian Smart | |
9 | // (c) 2008 Vadim Zeitlin | |
10 | // Licence: wxWindows license | |
11 | ///////////////////////////////////////////////////////////////////////////// | |
12 | ||
13 | // For compilers that support precompilation, includes "wx/wx.h". | |
14 | #include "wx/wxprec.h" | |
15 | ||
16 | #ifdef __BORLANDC__ | |
17 | #pragma hdrstop | |
18 | #endif | |
19 | ||
20 | #ifndef WX_PRECOMP | |
21 | #include "wx/wx.h" | |
22 | #endif | |
23 | ||
24 | #if !wxUSE_DOC_VIEW_ARCHITECTURE | |
25 | #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h! | |
26 | #endif | |
27 | ||
28 | #include "docview.h" | |
29 | #include "doc.h" | |
30 | #include "view.h" | |
31 | ||
32 | // ---------------------------------------------------------------------------- | |
33 | // DrawingView implementation | |
34 | // ---------------------------------------------------------------------------- | |
35 | ||
36 | IMPLEMENT_DYNAMIC_CLASS(DrawingView, wxView) | |
37 | ||
38 | BEGIN_EVENT_TABLE(DrawingView, wxView) | |
39 | EVT_MENU(wxID_CUT, DrawingView::OnCut) | |
40 | END_EVENT_TABLE() | |
41 | ||
42 | // What to do when a view is created. Creates actual | |
43 | // windows for displaying the view. | |
44 | bool DrawingView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) | |
45 | { | |
46 | MyApp& app = wxGetApp(); | |
47 | if ( app.GetMode() != MyApp::Mode_Single ) | |
48 | { | |
49 | // create a new window and canvas inside it | |
50 | m_frame = app.CreateChildFrame(doc, this, true); | |
51 | m_frame->SetTitle("Drawing View"); | |
52 | ||
53 | m_canvas = new MyCanvas(this, m_frame); | |
54 | m_frame->Show(true); | |
55 | } | |
56 | else // single document mode | |
57 | { | |
58 | // reuse the existing window and canvas | |
59 | m_frame = wxStaticCast(app.GetTopWindow(), wxFrame); | |
60 | m_canvas = app.GetMainWindowCanvas(); | |
61 | m_canvas->SetView(this); | |
62 | ||
63 | // Associate the appropriate frame with this view. | |
64 | SetFrame(m_frame); | |
65 | ||
66 | // Make sure the document manager knows that this is the | |
67 | // current view. | |
68 | Activate(true); | |
69 | ||
70 | // Initialize the edit menu Undo and Redo items | |
71 | doc->GetCommandProcessor()->SetEditMenu(app.GetMainWindowEditMenu()); | |
72 | doc->GetCommandProcessor()->Initialize(); | |
73 | } | |
74 | ||
75 | return true; | |
76 | } | |
77 | ||
78 | // Sneakily gets used for default print/preview as well as drawing on the | |
79 | // screen. | |
80 | void DrawingView::OnDraw(wxDC *dc) | |
81 | { | |
82 | dc->SetPen(*wxBLACK_PEN); | |
83 | ||
84 | // simply draw all lines of all segments | |
85 | const DoodleSegments& segments = GetDocument()->GetSegments(); | |
86 | for ( DoodleSegments::const_iterator i = segments.begin(); | |
87 | i != segments.end(); | |
88 | ++i ) | |
89 | { | |
90 | const DoodleLines& lines = i->GetLines(); | |
91 | for ( DoodleLines::const_iterator j = lines.begin(); | |
92 | j != lines.end(); | |
93 | ++j ) | |
94 | { | |
95 | const DoodleLine& line = *j; | |
96 | ||
97 | dc->DrawLine(line.x1, line.y1, line.x2, line.y2); | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
102 | DrawingDocument* DrawingView::GetDocument() | |
103 | { | |
104 | return wxStaticCast(wxView::GetDocument(), DrawingDocument); | |
105 | } | |
106 | ||
107 | void DrawingView::OnUpdate(wxView* sender, wxObject* hint) | |
108 | { | |
109 | wxView::OnUpdate(sender, hint); | |
110 | if ( m_canvas ) | |
111 | m_canvas->Refresh(); | |
112 | } | |
113 | ||
114 | // Clean up windows used for displaying the view. | |
115 | bool DrawingView::OnClose(bool deleteWindow) | |
116 | { | |
117 | if ( !GetDocument()->Close() ) | |
118 | return false; | |
119 | ||
120 | Activate(false); | |
121 | ||
122 | // Clear the canvas in single-window mode in which it stays alive | |
123 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) | |
124 | { | |
125 | m_canvas->ClearBackground(); | |
126 | m_canvas->ResetView(); | |
127 | m_canvas = NULL; | |
128 | ||
129 | if ( m_frame ) | |
130 | m_frame->SetTitle(wxTheApp->GetAppDisplayName()); | |
131 | } | |
132 | else // not single window mode | |
133 | { | |
134 | if ( deleteWindow ) | |
135 | wxDELETE(m_frame); | |
136 | } | |
137 | ||
138 | SetFrame(NULL); | |
139 | ||
140 | return true; | |
141 | } | |
142 | ||
143 | void DrawingView::OnCut(wxCommandEvent& WXUNUSED(event) ) | |
144 | { | |
145 | DrawingDocument * const doc = GetDocument(); | |
146 | ||
147 | doc->GetCommandProcessor()->Submit(new DrawingRemoveSegmentCommand(doc)); | |
148 | } | |
149 | ||
150 | // ---------------------------------------------------------------------------- | |
151 | // TextEditView implementation | |
152 | // ---------------------------------------------------------------------------- | |
153 | ||
154 | IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView) | |
155 | ||
156 | BEGIN_EVENT_TABLE(TextEditView, wxView) | |
157 | EVT_MENU(wxID_COPY, TextEditView::OnCopy) | |
158 | EVT_MENU(wxID_PASTE, TextEditView::OnPaste) | |
159 | EVT_MENU(wxID_SELECTALL, TextEditView::OnSelectAll) | |
160 | END_EVENT_TABLE() | |
161 | ||
162 | bool TextEditView::OnCreate(wxDocument *doc, long WXUNUSED(flags)) | |
163 | { | |
164 | m_frame = wxGetApp().CreateChildFrame(doc, this, false); | |
165 | m_text = new wxTextCtrl(m_frame, wxID_ANY, "", | |
166 | wxPoint(0, 0), m_frame->GetClientSize(), | |
167 | wxTE_MULTILINE); | |
168 | ||
169 | m_frame->SetTitle("Text View"); | |
170 | m_frame->Show(true); | |
171 | ||
172 | Activate(true); | |
173 | ||
174 | return true; | |
175 | } | |
176 | ||
177 | void TextEditView::OnDraw(wxDC *WXUNUSED(dc)) | |
178 | { | |
179 | // nothing to do here, wxTextCtrl draws itself | |
180 | } | |
181 | ||
182 | bool TextEditView::OnClose(bool deleteWindow) | |
183 | { | |
184 | if ( !GetDocument()->Close() ) | |
185 | return false; | |
186 | ||
187 | Activate(false); | |
188 | ||
189 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) | |
190 | { | |
191 | m_text->Clear(); | |
192 | } | |
193 | else // not single window mode | |
194 | { | |
195 | if ( deleteWindow ) | |
196 | wxDELETE(m_frame); | |
197 | } | |
198 | ||
199 | return true; | |
200 | } | |
201 | ||
202 | // ---------------------------------------------------------------------------- | |
203 | // MyCanvas implementation | |
204 | // ---------------------------------------------------------------------------- | |
205 | ||
206 | BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) | |
207 | EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent) | |
208 | END_EVENT_TABLE() | |
209 | ||
210 | // Define a constructor for my canvas | |
211 | MyCanvas::MyCanvas(wxView *view, wxWindow *parent) | |
212 | : wxScrolledWindow(parent, wxID_ANY, wxPoint(0, 0), parent->GetClientSize()) | |
213 | { | |
214 | m_view = view; | |
215 | m_currentSegment = NULL; | |
216 | m_lastMousePos = wxDefaultPosition; | |
217 | ||
218 | SetCursor(wxCursor(wxCURSOR_PENCIL)); | |
219 | ||
220 | // this is completely arbitrary and is done just for illustration purposes | |
221 | SetVirtualSize(1000, 1000); | |
222 | SetScrollRate(20, 20); | |
223 | ||
224 | SetBackgroundColour(*wxWHITE); | |
225 | } | |
226 | ||
227 | MyCanvas::~MyCanvas() | |
228 | { | |
229 | delete m_currentSegment; | |
230 | } | |
231 | ||
232 | // Define the repainting behaviour | |
233 | void MyCanvas::OnDraw(wxDC& dc) | |
234 | { | |
235 | if ( m_view ) | |
236 | m_view->OnDraw(& dc); | |
237 | } | |
238 | ||
239 | // This implements a tiny doodling program. Drag the mouse using the left | |
240 | // button. | |
241 | void MyCanvas::OnMouseEvent(wxMouseEvent& event) | |
242 | { | |
243 | if ( !m_view ) | |
244 | return; | |
245 | ||
246 | wxClientDC dc(this); | |
247 | PrepareDC(dc); | |
248 | ||
249 | dc.SetPen(*wxBLACK_PEN); | |
250 | ||
251 | const wxPoint pt(event.GetLogicalPosition(dc)); | |
252 | ||
253 | // is this the end of the current segment? | |
254 | if ( m_currentSegment && event.LeftUp() ) | |
255 | { | |
256 | if ( !m_currentSegment->IsEmpty() ) | |
257 | { | |
258 | // We've got a valid segment on mouse left up, so store it. | |
259 | DrawingDocument * const | |
260 | doc = wxStaticCast(m_view->GetDocument(), DrawingDocument); | |
261 | ||
262 | doc->GetCommandProcessor()->Submit( | |
263 | new DrawingAddSegmentCommand(doc, *m_currentSegment)); | |
264 | ||
265 | doc->Modify(true); | |
266 | } | |
267 | ||
268 | delete m_currentSegment; | |
269 | m_currentSegment = NULL; | |
270 | } | |
271 | ||
272 | // is this the start of a new segment? | |
273 | if ( m_lastMousePos != wxDefaultPosition && event.Dragging() ) | |
274 | { | |
275 | if ( !m_currentSegment ) | |
276 | m_currentSegment = new DoodleSegment; | |
277 | ||
278 | m_currentSegment->AddLine(m_lastMousePos, pt); | |
279 | ||
280 | dc.DrawLine(m_lastMousePos, pt); | |
281 | } | |
282 | ||
283 | m_lastMousePos = pt; | |
284 | } | |
285 | ||
286 | // ---------------------------------------------------------------------------- | |
287 | // wxImageCanvas implementation | |
288 | // ---------------------------------------------------------------------------- | |
289 | ||
290 | BEGIN_EVENT_TABLE(wxImageCanvas, wxScrolledWindow) | |
291 | END_EVENT_TABLE() | |
292 | ||
293 | // Define a constructor for my canvas | |
294 | wxImageCanvas::wxImageCanvas(wxView* view, wxWindow* parent) | |
295 | : wxScrolledWindow(parent, wxID_ANY, wxPoint(0, 0), parent->GetClientSize()) | |
296 | { | |
297 | m_view = view; | |
298 | } | |
299 | ||
300 | // Define the repainting behaviour | |
301 | void wxImageCanvas::OnDraw(wxDC& dc) | |
302 | { | |
303 | if ( m_view ) | |
304 | m_view->OnDraw(& dc); | |
305 | } | |
306 | ||
307 | // ---------------------------------------------------------------------------- | |
308 | // wxImageView implementation | |
309 | // ---------------------------------------------------------------------------- | |
310 | ||
311 | IMPLEMENT_DYNAMIC_CLASS(wxImageView, wxView) | |
312 | ||
313 | BEGIN_EVENT_TABLE(wxImageView, wxView) | |
314 | END_EVENT_TABLE() | |
315 | ||
316 | wxImageDocument* wxImageView::GetDocument() | |
317 | { | |
318 | return wxStaticCast(wxView::GetDocument(), wxImageDocument); | |
319 | } | |
320 | ||
321 | bool wxImageView::OnCreate(wxDocument* doc, long WXUNUSED(flags)) | |
322 | { | |
323 | m_frame = wxGetApp().CreateChildFrame(doc, this, false); | |
324 | m_frame->SetTitle("Image View"); | |
325 | m_canvas = new wxImageCanvas(this, m_frame); | |
326 | m_frame->Show(true); | |
327 | Activate(true); | |
328 | return true; | |
329 | } | |
330 | ||
331 | void wxImageView::OnUpdate(wxView* sender, wxObject* hint) | |
332 | { | |
333 | wxView::OnUpdate(sender, hint); | |
334 | const wxImage* image = GetDocument()->GetImage(); | |
335 | if (image->IsOk()) | |
336 | { | |
337 | m_canvas->SetScrollbars( 1, 1, image->GetWidth(), image->GetHeight() ); | |
338 | } | |
339 | } | |
340 | ||
341 | void wxImageView::OnDraw(wxDC* dc) | |
342 | { | |
343 | const wxImage* image = GetDocument()->GetImage(); | |
344 | if (image->IsOk()) | |
345 | { | |
346 | dc->DrawBitmap(wxBitmap(*image), 0, 0); | |
347 | } | |
348 | } | |
349 | ||
350 | bool wxImageView::OnClose(bool deleteWindow) | |
351 | { | |
352 | if ( !GetDocument()->Close() ) | |
353 | return false; | |
354 | ||
355 | Activate(false); | |
356 | ||
357 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) | |
358 | { | |
359 | GetDocument()->DeleteContents(); | |
360 | } | |
361 | else // not single window mode | |
362 | { | |
363 | if ( deleteWindow ) | |
364 | wxDELETE(m_frame); | |
365 | } | |
366 | return true; | |
367 | } | |
368 |